From 8cc42555f87ebafad0519b0f42cdf015d09b1dde Mon Sep 17 00:00:00 2001 From: Bruno Galvao Date: Fri, 7 Nov 2025 12:30:44 +0700 Subject: [PATCH 01/12] add benchmark your pallet --- .ai/categories/parachains.md | 817 +- .ai/categories/smart-contracts.md | 154 + .ai/categories/tooling.md | 2 +- ...untime-add-smart-contract-functionality.md | 18 +- ...ime-pallet-development-benchmark-pallet.md | 811 +- ...time-pallet-development-create-a-pallet.md | 2 +- ...t-contracts-cookbook-dapps-zero-to-hero.md | 2 +- .../smart-contracts-for-eth-devs-migration.md | 148 +- .ai/site-index.json | 12302 +++++++--------- llms-full.jsonl | 121 +- llms.txt | 8 +- .../pallet-development/benchmark-pallet.md | 724 +- .../pallet-development/create-a-pallet.md | 2 +- 13 files changed, 7394 insertions(+), 7717 deletions(-) diff --git a/.ai/categories/parachains.md b/.ai/categories/parachains.md index 1bf9e54f8..9bad55195 100644 --- a/.ai/categories/parachains.md +++ b/.ai/categories/parachains.md @@ -1256,9 +1256,9 @@ Any language that can compile to PolkaVM bytecode and utilize `pallet-revive`'s ### Key Benefits -- **Unified Platform**: Deploys both PolkaVM-optimized and EVM-compatible contracts using a single pallet. +- **Unified platform**: Deploys both PolkaVM-optimized and EVM-compatible contracts using a single pallet. - **Performance**: PolkaVM execution provides improved performance compared to the traditional EVM, leveraging the [RISC-V](https://en.wikipedia.org/wiki/RISC-V){target=\_blank} architecture to map instructions to the CPU and requires little transpiling. -- **Ethereum Compatibility**: Supports full integration with Ethereum tooling via RPC adapter. +- **Ethereum compatibility**: Supports full integration with Ethereum tooling via RPC adapter. ### Implementation Examples @@ -1276,7 +1276,7 @@ Frontier offers flexible integration depending on your compatibility needs: For basic EVM support using Polkadot SDK native APIs: -- **[`pallet-evm`](https://github.com/polkadot-evm/frontier/tree/master/frame/evm){target=\_blank}**: Provides the core EVM execution environment +- **[`pallet-evm`](https://github.com/polkadot-evm/frontier/tree/master/frame/evm){target=\_blank}**: Provides the core EVM execution environment. This configuration allows EVM contract execution but requires using Polkadot SDK-specific APIs for interaction. @@ -1290,20 +1290,20 @@ For complete Ethereum ecosystem integration with Ethereum RPC support: ### Key Benefits -- **Ethereum tooling compatibility**: Full compatibility with MetaMask, Hardhat, Remix, Truffle, and other Ethereum development tools -- **Minimal-friction migration**: Deployment of existing Ethereum dApps with minimal or no modifications -- **Native Ethereum formats**: Support for Ethereum transaction formats, signatures, and gas mechanics -- **Block emulation**: Ethereum-style block structure within Substrate's block production +- **Ethereum tooling compatibility**: Full compatibility with MetaMask, Hardhat, Remix, Foundry, and other Ethereum development tools. +- **Minimal-friction migration**: Deployment of existing Ethereum dApps with minimal or no modifications. +- **Native Ethereum formats**: Support for Ethereum transaction formats, signatures, and gas mechanics. +- **Block emulation**: Ethereum-style block structure within Substrate's block production. ### Implementation Examples Production implementations demonstrate Frontier's capabilities: -- **Moonbeam**: See their implementation of [`pallet-evm`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L532){target=\_blank} and [`pallet-ethereum`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L698){target=\_blank} +- **Moonbeam**: See their implementation of [`pallet-evm`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L532){target=\_blank} and [`pallet-ethereum`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L698){target=\_blank}. ## pallet-contracts (Legacy) -[`pallet-contracts`](https://docs.rs/pallet-contracts/latest/pallet_contracts/index.html#contracts-pallet){target=\_blank} is the original Wasm-based smart contract pallet for Polkadot SDK chains. While still functional, it's considered legacy as development efforts have shifted to pallet-revive. +[`pallet-contracts`](https://docs.rs/pallet-contracts/latest/pallet_contracts/index.html#contracts-pallet){target=\_blank} is the original Wasm-based smart contract pallet for Polkadot SDK chains. While still functional, it's considered legacy as development efforts have shifted to `pallet-revive`. ### Implementation Example @@ -1326,310 +1326,687 @@ For reference, Astar's implementation of [`pallet-contracts`](https://github.com --- -Page Title: Benchmarking FRAME Pallets +Page Title: Benchmark Your Pallet - Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md - Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/pallet-development/benchmark-pallet/ -- Summary: Learn how to use FRAME's benchmarking framework to measure extrinsic execution costs and provide accurate weights for on-chain computations. - -# Benchmarking +- Summary: Learn how to benchmark your custom pallet extrinsics to generate accurate weight calculations for production use. ## Introduction -Benchmarking is a critical component of developing efficient and secure blockchain runtimes. In the Polkadot ecosystem, accurately benchmarking your custom pallets ensures that each extrinsic has a precise [weight](/reference/glossary/#weight){target=\_blank}, representing its computational and storage demands. This process is vital for maintaining the blockchain's performance and preventing potential vulnerabilities, such as Denial of Service (DoS) attacks. +Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks. -The Polkadot SDK leverages the [FRAME](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank} benchmarking framework, offering tools to measure and assign weights to extrinsics. These weights help determine the maximum number of transactions or system-level calls processed within a block. This guide covers how to use FRAME's [benchmarking framework](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank}, from setting up your environment to writing and running benchmarks for your custom pallets. You'll understand how to generate accurate weights by the end, ensuring your runtime remains performant and secure. +This guide continues the pallet development series, building on the [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet), [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime), and [Test Your Pallet](/parachains/customize-runtime/pallet-development/pallet-testing) tutorials. You'll learn how to benchmark the counter pallet extrinsics and integrate the generated weights into your runtime. -## The Case for Benchmarking +## Prerequisites -Benchmarking helps validate that the required execution time for different functions is within reasonable boundaries to ensure your blockchain runtime can handle transactions efficiently and securely. By accurately measuring the weight of each extrinsic, you can prevent service interruptions caused by computationally intensive calls that exceed block time limits. Without benchmarking, runtime performance could be vulnerable to DoS attacks, where malicious users exploit functions with unoptimized weights. +Before you begin, ensure you have: -Benchmarking also ensures predictable transaction fees. Weights derived from benchmark tests accurately reflect the resource usage of function calls, allowing fair fee calculation. This approach discourages abuse while maintaining network reliability. +- Completed the previous pallet development tutorials +- Basic understanding of computational complexity +- Familiarity with Rust's testing framework -### Benchmarking and Weight +## Why Benchmark? -In Polkadot SDK-based chains, weight quantifies the computational effort needed to process transactions. This weight includes factors such as: +In blockchain systems, every operation consumes resources. Weight is the mechanism Polkadot SDK uses to measure and limit resource consumption. Without accurate weights: -- Computational complexity. -- Storage complexity (proof size). -- Database reads and writes. -- Hardware specifications. +- **Security Risk**: Malicious actors could submit transactions that consume excessive resources, blocking legitimate transactions or halting the chain +- **Inefficiency**: Over-estimated weights waste block space and reduce throughput +- **User Experience**: Inaccurate weights lead to incorrect fee calculations -Benchmarking uses real-world testing to simulate worst-case scenarios for extrinsics. The framework generates a linear model for weight calculation by running multiple iterations with varied parameters. These worst-case weights ensure blocks remain within execution limits, enabling the runtime to maintain throughput under varying loads. Excess fees can be refunded if a call uses fewer resources than expected, offering users a fair cost model. - -Because weight is a generic unit of measurement based on computation time for a specific physical machine, the weight of any function can change based on the specifications of hardware used for benchmarking. By modeling the expected weight of each runtime function, the blockchain can calculate the number of transactions or system-level calls it can execute within a certain period. +Benchmarking provides empirical measurements of your extrinsics under various conditions, ensuring weights reflect real-world resource consumption. + +## Understanding Weights + +The [weight system](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank} serves multiple purposes: + +- **DoS Protection**: Limits the computational work per block, preventing attackers from overwhelming the network +- **Fee Calculation**: Determines transaction fees based on actual resource usage +- **Block Production**: Helps block authors maximize throughput while staying within block limits + +Weights are expressed as [`Weight::from_parts(ref_time, proof_size)`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.from_parts){target=\_blank} where: + +- [`ref_time`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.ref_time){target=\_blank}: Computational time measured in picoseconds +- [`proof_size`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.proof_size){target=\_blank}: Storage proof size in bytes + +## Step 1: Create the Benchmarking Module + +Create a new file `benchmarking.rs` in your pallet's `src` directory. This module will contain all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} for your pallet: + +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use frame::deps::frame_benchmarking::v2::*; +use frame::benchmarking::prelude::RawOrigin; + +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn set_counter_value() { + let new_value: u32 = 100; + + #[extrinsic_call] + _(RawOrigin::Root, new_value); + + assert_eq!(CounterValue::::get(), new_value); + } + + #[benchmark] + fn increment() { + let caller: T::AccountId = whitelisted_caller(); + let amount: u32 = 50; + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), amount); + + assert_eq!(CounterValue::::get(), amount); + assert_eq!(UserInteractions::::get(caller), 1); + } + + #[benchmark] + fn decrement() { + // First set the counter to a non-zero value + CounterValue::::put(100); + + let caller: T::AccountId = whitelisted_caller(); + let amount: u32 = 30; -Within FRAME, each function call that is dispatched must have a `#[pallet::weight]` annotation that can return the expected weight for the worst-case scenario execution of that function given its inputs: + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), amount); + + assert_eq!(CounterValue::::get(), 70); + assert_eq!(UserInteractions::::get(caller), 1); + } -```rust hl_lines="2" -#[pallet::call_index(0)] -#[pallet::weight(T::WeightInfo::do_something())] -pub fn do_something(origin: OriginFor) -> DispatchResultWithPostInfo { Ok(()) } + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} ``` -The `WeightInfo` file is automatically generated during benchmarking. Based on these tests, this file provides accurate weights for each extrinsic. +**Key components:** + +- **`#![cfg(feature = "runtime-benchmarks")]`**: Ensures benchmarking code only compiles when the feature is enabled +- **[`#[benchmarks]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmarks.html){target=\_blank}**: Marks the module containing benchmark definitions +- **[`#[benchmark]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmark.html){target=\_blank}**: Defines individual benchmark functions +- **[`#[extrinsic_call]`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.extrinsic_call.html){target=\_blank}**: Marks the actual extrinsic invocation to measure +- **[`whitelisted_caller()`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/fn.whitelisted_caller.html){target=\_blank}**: Generates a funded account for benchmarking +- **[`impl_benchmark_test_suite!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.impl_benchmark_test_suite.html){target=\_blank}**: Generates test functions to verify benchmarks work correctly -## Benchmarking Process +## Step 2: Define the Weight Trait -Benchmarking a pallet involves the following steps: +The [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. This enables you to use placeholder weights during development and testing, then switch to auto-generated benchmarked weights in production without modifying the pallet code itself. -1. Creating a `benchmarking.rs` file within your pallet's structure. -2. Writing a benchmarking test for each extrinsic. -3. Executing the benchmarking tool to calculate weights based on performance metrics. +Add a `weights` module to your pallet that defines the `WeightInfo` trait: -The benchmarking tool runs multiple iterations to model worst-case execution times and determine the appropriate weight. By default, the benchmarking pipeline is deactivated. To activate it, compile your runtime with the `runtime-benchmarks` feature flag. +```rust title="pallets/pallet-custom/src/lib.rs" +#[frame::pallet] +pub mod pallet { + use frame::prelude::*; + pub use weights::WeightInfo; -### Prepare Your Environment + pub mod weights { + use frame::prelude::*; -Install the [`frame-omni-bencher`](https://crates.io/crates/frame-omni-bencher){target=\_blank} command-line tool: + pub trait WeightInfo { + fn set_counter_value() -> Weight; + fn increment() -> Weight; + fn decrement() -> Weight; + } -```bash -cargo install frame-omni-bencher + impl WeightInfo for () { + fn set_counter_value() -> Weight { + Weight::from_parts(10_000, 0) + } + fn increment() -> Weight { + Weight::from_parts(15_000, 0) + } + fn decrement() -> Weight { + Weight::from_parts(15_000, 0) + } + } + } + + // ... rest of pallet +} ``` -Before writing benchmark tests, you need to ensure the `frame-benchmarking` crate is included in your pallet's `Cargo.toml` similar to the following: +The `()` implementation provides placeholder weights for development. Later, this will be replaced with auto-generated weights from benchmarking. + +## Step 3: Add WeightInfo to Config + +By making `WeightInfo` an associated type in the `Config` trait, you allow each runtime that uses your pallet to specify which weight implementation to use. Different deployment environments (testnets, production chains, or different hardware configurations) may have different performance characteristics and can use different weight calculations. -```toml title="Cargo.toml" -frame-benchmarking = { version = "37.0.0", default-features = false } +Update your pallet's `Config` trait to include `WeightInfo`: + +```rust title="pallets/pallet-custom/src/lib.rs" +#[pallet::config] +pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + #[pallet::constant] + type CounterMaxValue: Get; + + type WeightInfo: weights::WeightInfo; +} ``` -You must also ensure that you add the `runtime-benchmarks` feature flag as follows under the `[features]` section of your pallet's `Cargo.toml`: +## Step 4: Update Extrinsic Weight Annotations -```toml title="Cargo.toml" -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] +By calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. This allows you to easily switch between placeholder weights for testing and benchmarked weights for production without changing any pallet code. + +Replace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait: + +```rust title="pallets/pallet-custom/src/lib.rs" +#[pallet::call] +impl Pallet { + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::set_counter_value())] + pub fn set_counter_value(origin: OriginFor, new_value: u32) -> DispatchResult { + // ... implementation + } + + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::increment())] + pub fn increment(origin: OriginFor, amount: u32) -> DispatchResult { + // ... implementation + } + + #[pallet::call_index(2)] + #[pallet::weight(T::WeightInfo::decrement())] + pub fn decrement(origin: OriginFor, amount: u32) -> DispatchResult { + // ... implementation + } +} +``` + +## Step 5: Include the Benchmarking Module + +The `#[cfg(feature = "runtime-benchmarks")]` attribute ensures that benchmarking code is only compiled when explicitly needed. This keeps your production runtime lean by excluding benchmarking infrastructure from normal builds, as it's only needed when generating weights. + +At the top of your `lib.rs`, add the module declaration: + +```rust title="pallets/pallet-custom/src/lib.rs" +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +use alloc::vec::Vec; + +pub use pallet::*; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +// ... rest of the pallet ``` -Lastly, ensure that `frame-benchmarking` is included in `std = []`: +## Step 6: Configure Pallet Dependencies + +The feature flag system in Cargo allows you to conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds. + +Update your pallet's `Cargo.toml` to enable the benchmarking feature: -```toml title="Cargo.toml" +```toml title="pallets/pallet-custom/Cargo.toml" +[dependencies] +codec = { features = ["derive"], workspace = true } +scale-info = { features = ["derive"], workspace = true } +frame = { features = ["experimental", "runtime"], workspace = true } + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame/runtime-benchmarks", +] std = [ - # ... - "frame-benchmarking?/std", - # ... + "codec/std", + "scale-info/std", + "frame/std", ] ``` -Once complete, you have the required dependencies for writing benchmark tests for your pallet. +## Step 7: Update Mock Runtime -### Write Benchmark Tests +In your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo` since unit tests focus on verifying functional correctness rather than performance characteristics. This keeps tests fast and focused on validating logic. -Create a `benchmarking.rs` file in your pallet's `src/`. Your directory structure should look similar to the following: +Add the `WeightInfo` type to your test configuration in `mock.rs`: +```rust title="pallets/pallet-custom/src/mock.rs" +impl pallet_custom::Config for Test { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = (); +} ``` -my-pallet/ -├── src/ -│ ├── lib.rs # Main pallet implementation -│ └── benchmarking.rs # Benchmarking -└── Cargo.toml + +## Step 8: Configure Runtime Benchmarking + +To execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. This involves three configuration steps: + +### Update Runtime Cargo.toml + +When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. + +Add your pallet to the runtime's `runtime-benchmarks` feature in `runtime/Cargo.toml`: + +```toml title="runtime/Cargo.toml" +runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "hex-literal", + "pallet-parachain-template/runtime-benchmarks", + "polkadot-sdk/runtime-benchmarks", + "pallet-custom/runtime-benchmarks", +] ``` -With the directory structure set, you can use the [`polkadot-sdk-parachain-template`](https://github.com/paritytech/polkadot-sdk-parachain-template/tree/master/pallets){target=\_blank} to get started as follows: +### Update Runtime Configuration -```rust title="benchmarking.rs (starter template)" -//! Benchmarking setup for pallet-template -#![cfg(feature = "runtime-benchmarks")] +Start with the placeholder implementation during development. After successfully running benchmarks and generating the weights file, you'll update this to use the benchmarked weights. -use super::*; -use frame_benchmarking::v2::*; +In `runtime/src/configs/mod.rs`, add the `WeightInfo` type: -#[benchmarks] -mod benchmarks { - use super::*; - #[cfg(test)] - use crate::pallet::Pallet as Template; - use frame_system::RawOrigin; - - #[benchmark] - fn do_something() { - let caller: T::AccountId = whitelisted_caller(); - #[extrinsic_call] - do_something(RawOrigin::Signed(caller), 100); - - assert_eq!(Something::::get().map(|v| v.block_number), Some(100u32.into())); - } - - #[benchmark] - fn cause_error() { - Something::::put(CompositeStruct { block_number: 100u32.into() }); - let caller: T::AccountId = whitelisted_caller(); - #[extrinsic_call] - cause_error(RawOrigin::Signed(caller)); - - assert_eq!(Something::::get().map(|v| v.block_number), Some(101u32.into())); - } - - impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); +```rust title="runtime/src/configs/mod.rs" +impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = (); } ``` -In your benchmarking tests, employ these best practices: +### Register Benchmarks -- **Write custom testing functions**: The function `do_something` in the preceding example is a placeholder. Similar to writing unit tests, you must write custom functions to benchmark test your extrinsics. Access the mock runtime and use functions such as `whitelisted_caller()` to sign transactions and facilitate testing. -- **Use the `#[extrinsic_call]` macro**: This macro is used when calling the extrinsic itself and is a required part of a benchmarking function. See the [`extrinsic_call`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html#extrinsic_call-and-block){target=\_blank} docs for more details. -- **Validate extrinsic behavior**: The `assert_eq` expression ensures that the extrinsic is working properly within the benchmark context. +The `define_benchmarks!` macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks. -Add the `benchmarking` module to your pallet. In the pallet `lib.rs` file add the following: +Add your pallet to the benchmark list in `runtime/src/benchmarks.rs`: -```rust -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; +```rust title="runtime/src/benchmarks.rs" +polkadot_sdk::frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + // ... other pallets + [pallet_custom, CustomPallet] +); ``` -### Add Benchmarks to Runtime +## Step 9: Run Benchmarks -Before running the benchmarking tool, you must integrate benchmarks with your runtime as follows: +### Test Benchmark Compilation -1. Navigate to your `runtime/src` directory and check if a `benchmarks.rs` file exists. If not, create one. This file will contain the macro that registers all pallets for benchmarking along with their respective configurations: +The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the full runtime. - ```rust title="benchmarks.rs" - frame_benchmarking::define_benchmarks!( - [frame_system, SystemBench::] - [pallet_parachain_template, TemplatePallet] - [pallet_balances, Balances] - [pallet_session, SessionBench::] - [pallet_timestamp, Timestamp] - [pallet_message_queue, MessageQueue] - [pallet_sudo, Sudo] - [pallet_collator_selection, CollatorSelection] - [cumulus_pallet_parachain_system, ParachainSystem] - [cumulus_pallet_xcmp_queue, XcmpQueue] - ); - ``` +First, verify your benchmarks compile and run as tests: - For example, to add a new pallet named `pallet_parachain_template` for benchmarking, include it in the macro as shown: - ```rust title="benchmarks.rs" hl_lines="3" - frame_benchmarking::define_benchmarks!( - [frame_system, SystemBench::] - [pallet_parachain_template, TemplatePallet] - ); - ``` +```bash +cargo test -p pallet-custom --features runtime-benchmarks +``` - !!!warning "Updating `define_benchmarks!` macro is required" - Any pallet that needs to be benchmarked must be included in the [`define_benchmarks!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.define_benchmarks.html){target=\_blank} macro. The CLI will only be able to access and benchmark pallets that are registered here. +You should see your benchmark tests passing: -2. Check your runtime's `lib.rs` file to ensure the `benchmarks` module is imported. The import should look like this: +``` +test benchmarking::benchmarks::bench_set_counter_value ... ok +test benchmarking::benchmarks::bench_increment ... ok +test benchmarking::benchmarks::bench_decrement ... ok +``` - ```rust title="lib.rs" - #[cfg(feature = "runtime-benchmarks")] - mod benchmarks; - ``` +### Build the Runtime with Benchmarks - The `runtime-benchmarks` feature gate ensures benchmark tests are isolated from production runtime code. +This build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. This is a special build used only for benchmarking - you'll create a different build later for actually running your chain. -3. Enable runtime benchmarking for your pallet in `runtime/Cargo.toml`: +Compile the runtime with benchmarking enabled to generate the WASM binary: - ```toml - runtime-benchmarks = [ - # ... - "pallet_parachain_template/runtime-benchmarks", - ] +```bash +cargo build --release --features runtime-benchmarks +``` - ``` +This produces the runtime WASM file needed for benchmarking, typically located at: +``` +target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm +``` -### Run Benchmarks +### Install the Benchmarking Tool -You can now compile your runtime with the `runtime-benchmarks` feature flag. This feature flag is crucial as the benchmarking tool will look for this feature being enabled to know when it should run benchmark tests. Follow these steps to compile the runtime with benchmarking enabled: +[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} is the official Polkadot SDK tool specifically designed for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system. -1. Run `build` with the feature flag included: +Install the `frame-omni-bencher` CLI tool: - ```bash - cargo build --features runtime-benchmarks --release - ``` +```bash +cargo install frame-omni-bencher --locked +``` -2. Create a `weights.rs` file in your pallet's `src/` directory. This file will store the auto-generated weight calculations: +### Download the Weight Template - ```bash - touch weights.rs - ``` +The weight template is a Handlebars file that transforms raw benchmark data into a properly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow Polkadot SDK conventions and include all necessary metadata like benchmark execution parameters, storage operation counts, and hardware information. -3. Before running the benchmarking tool, you'll need a template file that defines how weight information should be formatted. Download the official template from the Polkadot SDK repository and save it in your project folders for future use: +Download the official weight template file: - ```bash - curl https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \ - --output ./pallets/benchmarking/frame-weight-template.hbs - ``` +```bash +curl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \ +--output ./pallets/pallet-custom/frame-weight-template.hbs +``` -4. Run the benchmarking tool to measure extrinsic weights: +### Hardware Requirements for Benchmarking - ```bash - frame-omni-bencher v1 benchmark pallet \ - --runtime INSERT_PATH_TO_WASM_RUNTIME \ - --pallet INSERT_NAME_OF_PALLET \ +!!! warning "Critical: Benchmark on Production-Like Hardware" + Benchmarks must be executed on hardware similar to what will run your chain in production. Weight measurements are hardware-dependent, and benchmarking on different hardware can lead to dangerous under-estimation or wasteful over-estimation of weights. + +Weights represent the actual computational time and resources consumed by extrinsics. These measurements vary significantly across different hardware configurations: + +- **CPU Performance**: Different processors execute instructions at different speeds. A faster development laptop will produce lower weight values than production server hardware +- **Storage Speed**: Database read/write performance varies between NVMe SSDs, SATA SSDs, and HDDs, affecting storage-related weights +- **Memory Bandwidth**: RAM speed impacts how quickly data can be accessed during execution +- **CPU Cache**: Cache size and architecture differences affect repeated operations + +Benchmarking on faster hardware than production leads to under-estimated weights - attackers could submit extrinsics that consume more resources than the weights suggest, potentially causing blocks to take longer than expected to produce or even halting the chain. Conversely, benchmarking on slower hardware creates over-estimated weights, resulting in unnecessarily high transaction fees and wasted block capacity. + +**Best practices:** + +1. **Match production specifications**: If your chain will run on specific validator hardware, benchmark on identical or very similar machines +2. **Use reference hardware**: The Polkadot ecosystem often uses standardized reference hardware specifications for consistency. Consider following these standards if your chain will connect to Polkadot or Kusama +3. **Dedicated benchmarking environment**: Run benchmarks on a machine without other heavy processes to ensure consistent measurements +4. **Document your hardware**: The generated weight files include hardware information in comments. Review this to ensure it matches your production environment +5. **Re-benchmark when hardware changes**: If your validator hardware specifications change, re-run benchmarks and update weights + +For development and testing purposes, you can run benchmarks on any available hardware to verify that your benchmark functions work correctly. However, before deploying to production, always re-run benchmarks on production-equivalent hardware. + +### Execute Benchmarks + +Benchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking the WASM ensures your weight measurements reflect real-world conditions. + +Run benchmarks for your pallet to generate weight files: + +```bash +frame-omni-bencher v1 benchmark pallet \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ + --pallet pallet_custom \ --extrinsic "" \ - --template ./frame-weight-template.hbs \ - --output weights.rs - ``` + --template ./pallets/pallet-custom/frame-weight-template.hbs \ + --output ./pallets/pallet-custom/src/weights.rs +``` - !!! tip "Flag definitions" - - **`--runtime`**: The path to your runtime's Wasm. - - **`--pallet`**: The name of the pallet you wish to benchmark. This pallet must be configured in your runtime and defined in `define_benchmarks`. - - **`--extrinsic`**: Which extrinsic to test. Using `""` implies all extrinsics will be benchmarked. - - **`--template`**: Defines how weight information should be formatted. - - **`--output`**: Where the output of the auto-generated weights will reside. +**Command breakdown:** -The generated `weights.rs` file contains weight annotations for your extrinsics, ready to be added to your pallet. The output should be similar to the following. Some output is omitted for brevity: +- `v1`: Specifies the benchmarking framework version (v2 API) +- `benchmark pallet`: Subcommand indicating you want to benchmark pallet extrinsics +- `--runtime`: Path to the compiled WASM runtime file that includes your pallet and benchmarks +- `--pallet pallet_custom`: Name of the pallet to benchmark (must match the name used in `define_benchmarks!`) +- `--extrinsic ""`: Empty string benchmarks all extrinsics in the pallet; you can specify a single extrinsic name to benchmark only that one +- `--template`: Path to the Handlebars template that formats the output +- `--output`: Destination file path for the generated weights module -
- frame-omni-bencher v1 benchmark pallet \ - --runtime INSERT_PATH_TO_WASM_RUNTIME \ - --pallet "INSERT_NAME_OF_PALLET" \ - --extrinsic "" \ - --template ./frame-weight-template.hbs \ - --output ./weights.rs - ... - 2025-01-15T16:41:33.557045Z INFO polkadot_sdk_frame::benchmark::pallet: [ 0 % ] Starting benchmark: pallet_parachain_template::do_something - 2025-01-15T16:41:33.564644Z INFO polkadot_sdk_frame::benchmark::pallet: [ 50 % ] Starting benchmark: pallet_parachain_template::cause_error - ... - Created file: "weights.rs" - -
+### Advanced Options + +You can customize benchmark execution with additional parameters for more detailed measurements: + +```bash +frame-omni-bencher v1 benchmark pallet \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ + --pallet pallet_custom \ + --extrinsic "" \ + --steps 50 \ + --repeat 20 \ + --template ./pallets/pallet-custom/frame-weight-template.hbs \ + --output ./pallets/pallet-custom/src/weights.rs +``` -#### Add Benchmark Weights to Pallet +**Additional parameters:** -Once the `weights.rs` is generated, you must integrate it with your pallet. +- `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time +- `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise and providing more reliable weight estimates +- `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution +- `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions -1. To begin the integration, import the `weights` module and the `WeightInfo` trait, then add both to your pallet's `Config` trait. Complete the following steps to set up the configuration: +## Step 10: Use Generated Weights - ```rust title="lib.rs" - pub mod weights; +After running benchmarks, a `weights.rs` file is generated containing measured weights. The generated weights are based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. Estimates or placeholder values cannot capture these nuances and will either waste block space (over-estimation) or create security risks (under-estimation). + +The file includes: + +- Detailed documentation about the benchmark execution environment (date, hardware, parameters) +- The `WeightInfo` trait definition matching your benchmark functions +- `SubstrateWeight` implementation with measured weights from your benchmarks +- Database read/write costs calculated based on observed storage operations +- Component complexity annotations for variable inputs (if you use linear components) +- A fallback `()` implementation for testing environments + +### Integrate the Generated Weights + +Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during normal operation to calculate transaction fees and enforce block limits. + +Add the weights module to your pallet's `lib.rs`: + +```rust title="pallets/pallet-custom/src/lib.rs" +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +use alloc::vec::Vec; + +pub use pallet::*; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +pub mod weights; + +#[frame::pallet] +pub mod pallet { + use super::*; + use frame::prelude::*; use crate::weights::WeightInfo; + // ... rest of pallet +} +``` - /// Configure the pallet by specifying the parameters and types on which it depends. - #[pallet::config] - pub trait Config: frame_system::Config { - // ... - /// A type representing the weights required by the dispatchables of this pallet. - type WeightInfo: WeightInfo; +### Update Runtime Configuration + +This change activates your benchmarked weights in the production runtime. Now when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits. + +Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation: + +```rust title="runtime/src/configs/mod.rs" +impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = pallet_custom::weights::SubstrateWeight; +} +``` + +### Example Generated Weight File + +The generated `weights.rs` file will look similar to this: + +```rust title="pallets/pallet-custom/src/weights.rs" +//! Autogenerated weights for `pallet_custom` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20` + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +pub trait WeightInfo { + fn set_counter_value() -> Weight; + fn increment() -> Weight; + fn decrement() -> Weight; +} + +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + fn set_counter_value() -> Weight { + Weight::from_parts(8_234_000, 0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } - ``` -2. Next, you must add this to the `#[pallet::weight]` annotation in all the extrinsics via the `Config` as follows: + fn increment() -> Weight { + Weight::from_parts(12_456_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } - ```rust hl_lines="2" title="lib.rs" - #[pallet::call_index(0)] - #[pallet::weight(T::WeightInfo::do_something())] - pub fn do_something(origin: OriginFor) -> DispatchResultWithPostInfo { Ok(()) } - ``` + fn decrement() -> Weight { + Weight::from_parts(11_987_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} +``` -3. Finally, configure the actual weight values in your runtime. In `runtime/src/config/mod.rs`, add the following code: +**Note**: The actual numbers will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} accounts for database read and write operations. - ```rust title="mod.rs" - // Configure pallet. - impl pallet_parachain_template::Config for Runtime { - // ... - type WeightInfo = pallet_parachain_template::weights::SubstrateWeight; +## Benchmarking Best Practices + +### 1. Test Worst-Case Scenarios + +Benchmarks should always measure maximum possible resource consumption. If you benchmark average or best-case scenarios, malicious users could craft transactions that hit worst-case paths in your code, consuming more resources than the weights indicate and potentially slowing down or halting block production. + +```rust +#[benchmark] +fn complex_operation() { + // Set up worst-case storage state + for i in 0..100 { + SomeStorage::::insert(i, vec![0u8; 1000]); } - ``` -## Where to Go Next + let caller = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller)); +} +``` + +### 2. Use Linear Components for Variable Complexity + +Many extrinsics have variable costs depending on input parameters. [Linear components](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/trait.BenchmarkingSetup.html){target=\_blank} tell the benchmarking framework to test your extrinsic with different values of `n`, measure the execution time for each, and calculate a formula like `Weight = base_weight + (n * per_item_weight)`. This produces dynamic weights that accurately reflect the actual work being done. + +When extrinsic complexity depends on input size, use linear components: + +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#[benchmark] +fn process_items(n: Linear<0, 100>) { + let caller = whitelisted_caller(); + let items: Vec = (0..n).collect(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), items); +} +``` + +### 3. Verify Results + +Assertions ensure that your benchmark is actually testing the code path you think it's testing. If your extrinsic fails silently or takes an early return, the benchmark would measure the wrong scenario and produce inaccurate weights. + +Always assert the expected state after extrinsic execution: + +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#[benchmark] +fn my_extrinsic() { + let caller = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone())); + + // Verify the extrinsic had the expected effect + assert_eq!(MyStorage::::get(&caller), expected_value); +} +``` + +### 4. Minimize Setup Code + +While the benchmarking framework tries to isolate the extrinsic execution, excessive setup code can add noise to measurements. More importantly, setup code that doesn't reflect real-world pre-conditions can lead to benchmarking unrealistic scenarios. + +Only include necessary setup in benchmarks: + +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#[benchmark] +fn efficient_benchmark() { + // Minimal setup + let caller = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller)); + + // Minimal assertions +} +``` + +## Run Your Chain Locally + +Now that you've added the pallet to your runtime, you can launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide. + +### Build the Production Runtime + +The `runtime-benchmarks` feature flag adds special host functions (like `ext_benchmarking_current_time` and `ext_benchmarking_get_read_and_written_keys`) that are only available in the benchmarking execution environment. These functions allow the benchmarking framework to precisely measure execution time and track storage operations. However, regular nodes don't provide these host functions, so a runtime compiled with benchmarking features will fail to start on a production node. + +Before running your chain, rebuild the runtime **without** the `runtime-benchmarks` feature: + +```bash +cargo build --release +``` + +!!! note "Build Types" + Understanding the difference between builds is critical: + + - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher` + - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your actual chain + +This produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. + +### Generate a Chain Specification + +The chain specification defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. By generating a new chain spec with your updated runtime (now containing your benchmarked pallet), you ensure that nodes starting from this spec will use the correct version of your code with proper weight calculations. + +Create a new chain specification file with the updated runtime: + +```bash +chain-spec-builder create -t development \ +--relay-chain paseo \ +--para-id 1000 \ +--runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ +named-preset development +``` + +This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime. + +### Start the Parachain Node + +Launch the parachain using the Polkadot Omni Node with the generated chain specification by running the following command: + +```bash +polkadot-omni-node --chain ./chain_spec.json --dev +``` + +The node will start and display initialization information including: + +- The chain specification name +- The node identity and peer ID +- Database location +- Network endpoints (JSON-RPC and Prometheus) + +### Verify Block Production + +Once the node is running, you should see log messages indicating successful block production: + +``` +[Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc) +[Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ... +[Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2) +[Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ... +[Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32) +``` + +The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. + +## Related Resources -- View the Rust Docs for a more comprehensive, low-level view of the [FRAME V2 Benchmarking Suite](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=_blank}. -- Read the [FRAME Benchmarking and Weights](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_benchmarking_weight/index.html){target=_blank} reference document, a concise guide which details how weights and benchmarking work. +- [FRAME Benchmarking Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/index.html){target=\_blank} +- [Weight Struct Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html){target=\_blank} +- [Benchmarking v2 API](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} +- [frame-omni-bencher Tool](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} --- @@ -3968,7 +4345,7 @@ This command validates all pallet configurations and prepares the build for depl ## Run Your Chain Locally -Launch your parachain locally to test the new pallet functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. +Launch your parachain locally to test the new pallet functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide. ### Generate a Chain Specification diff --git a/.ai/categories/smart-contracts.md b/.ai/categories/smart-contracts.md index 18e603f60..3a3f35da2 100644 --- a/.ai/categories/smart-contracts.md +++ b/.ai/categories/smart-contracts.md @@ -10585,6 +10585,160 @@ Your local development environment is now active and accessible at `http://local You can connect wallets, deploy contracts using Remix or Hardhat, and interact with your smart contracts as you would on any Ethereum-compatible network. +--- + +Page Title: Migration FAQs and Considerations + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/ +- Summary: Learn how to migrate your existing Ethereum contracts to the Polkadot Hub using REVM and PolkaVM by following these considerations. + +# Migration FAQs and Considerations + +## Introduction + +This guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns. + +## Migration Considerations + +Take into account the following considerations before migrating your contracts: + +- Standard ERC-20, ERC-721, ERC-1155 tokens work without changes. +- DeFi protocols, DEXs, and AMMs migrate seamlessly. +- DAOs and governance contracts are fully compatible. +- Most Solidity contracts deploy identically to Ethereum. + +## Migration Checklist + +Before migrating your contracts, review this checklist: + +- Factory contracts using PVM bytecode need pre-uploaded dependencies. +- Contracts using `EXTCODECOPY` for runtime manipulation require review (for projects that will use PVM bytecode, not EVM bytecode). +- Replace `transfer()` and `send()` with proper reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode). + +## Migration FAQs + +### Which backend should I choose? + +- Choose REVM if you want: + + - Zero-modification deployment of existing Ethereum contracts. + - Exact EVM behavior for audited code. + - Compatibility with tools that inspect EVM bytecode. + - Rapid deployment without optimization. + +- Choose PolkaVM if you want: + + - Better performance for computation-heavy applications. + - Lower execution costs for intensive operations. + - Access to next-generation smart contract features. + +If you are unsure which to choose, start with REVM for immediate compatibility, then consider PolkaVM for performance optimization once deployed. + +### Do I need to rewrite my Solidity code? + +No, for most contracts. Standard Solidity patterns work on both backends. + +### What about factory contracts? + +- **REVM**: Factory contracts work identically to Ethereum with no changes needed. + + The original factory pattern is: + + ```solidity + contract TokenFactory { + function createToken(string memory name) public returns (address) { + // Creates new contract at runtime + Token newToken = new Token(name); + return address(newToken); + } + } + ``` + +- **PolkaVM**: Factory contracts require pre-uploading dependent contracts. + + Here's how to adapt the original factory pattern: + + ```solidity + contract TokenFactory { + // Reference pre-uploaded Token contract by hash + bytes32 public tokenCodeHash; + + constructor(bytes32 _tokenCodeHash) { + tokenCodeHash = _tokenCodeHash; + } + + function createToken(string memory name) public returns (address) { + // Instantiate from pre-uploaded code + Token newToken = new Token{salt: keccak256(abi.encode(name))}(name); + return address(newToken); + } + } + ``` + +The deployment steps for PolkaVM factories are: + +1. Upload the contract code to the chain. +2. Note the returned code hash. +3. Deploy the Factory contract with the contract code hash. +4. Factory can now instantiate contracts using the pre-uploaded code. + +### How do gas costs compare? + +For more information on gas costs, see the [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} page. + +### Which Solidity features are not supported? + +For REVM, any Solidity feature will function smoothly without requiring changes or adaptations. For PVM, there are considerations, as was mentioned above. + +For PolkaVM, there are some considerations: + +- `EXTCODECOPY`: Only works in constructor code. +- Runtime code modification: Use on-chain constructors instead. +- **Gas stipends**: `address.send()` and `address.transfer()` don't provide reentrancy protection. +- **Unsupported operations**: `pc`, `extcodecopy`, `selfdestruct`, `blobhash`, and `blobbasefee` (blob-related operations). + +### How do I handle the existential deposit? + +Polkadot requires accounts to maintain a minimum balance (existential deposit or ED) to remain active. + +This is handled automatically for you: + +- Balance queries via Ethereum RPC automatically deduct the ED. +- New account transfers include ED in transaction fees. +- Contract-to-contract transfers draw ED from the transaction signer. + +You typically don't need to do anything special, but be aware: + +- Accounts below ED threshold are automatically deleted. +- ED is around 0.01 DOT (varies by network). +- Your contracts don't need to manage this explicitly. + +### Can I use my existing development tools? + +Yes. Both backends support: + +- **Wallets**: [MetaMask](https://metamask.io/){target=\_blank}, [Talisman](https://talisman.xyz/){target=\_blank}, [SubWallet](https://www.subwallet.app/){target=\_blank} +- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\_blank}, [Foundry](/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/){target=\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} (just consider that for PVM bytecode, you will use the Polkadot version of the tooling) +- **Libraries**: [ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank}, [web3.js](/smart-contracts/libraries/web3-js/){target=\_blank}, [viem](/smart-contracts/libraries/viem/){target=\_blank} +- **Testing tools**: Your existing test suites work + +Connect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow. + +## Conclusion + +Most Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance. + +There are a few key points to keep in mind during migration: + +- Replace `transfer()` and `send()` with `.call{value}("")` and use reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode). +- PolkaVM factory contracts using PVM bytecode need pre-uploaded dependencies. +- Don't hardcode gas values. +- Test thoroughly on [TestNet](/smart-contracts/connect/#__tabbed_1_1){target=\_blank} before mainnet deployment. + +Your existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns. + + --- Page Title: Networks diff --git a/.ai/categories/tooling.md b/.ai/categories/tooling.md index 41ae91e34..6f6a392c3 100644 --- a/.ai/categories/tooling.md +++ b/.ai/categories/tooling.md @@ -25913,7 +25913,7 @@ export default buildModule("StorageModule", (m) => { Deploy the contract to Polkadot Hub TestNet: ```bash -npx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotHub +npx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotTestNet ``` You should see output similar to: diff --git a/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md b/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md index eda88f870..e4d53a6e1 100644 --- a/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md +++ b/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md @@ -50,9 +50,9 @@ Any language that can compile to PolkaVM bytecode and utilize `pallet-revive`'s ### Key Benefits -- **Unified Platform**: Deploys both PolkaVM-optimized and EVM-compatible contracts using a single pallet. +- **Unified platform**: Deploys both PolkaVM-optimized and EVM-compatible contracts using a single pallet. - **Performance**: PolkaVM execution provides improved performance compared to the traditional EVM, leveraging the [RISC-V](https://en.wikipedia.org/wiki/RISC-V){target=\_blank} architecture to map instructions to the CPU and requires little transpiling. -- **Ethereum Compatibility**: Supports full integration with Ethereum tooling via RPC adapter. +- **Ethereum compatibility**: Supports full integration with Ethereum tooling via RPC adapter. ### Implementation Examples @@ -70,7 +70,7 @@ Frontier offers flexible integration depending on your compatibility needs: For basic EVM support using Polkadot SDK native APIs: -- **[`pallet-evm`](https://github.com/polkadot-evm/frontier/tree/master/frame/evm){target=\_blank}**: Provides the core EVM execution environment +- **[`pallet-evm`](https://github.com/polkadot-evm/frontier/tree/master/frame/evm){target=\_blank}**: Provides the core EVM execution environment. This configuration allows EVM contract execution but requires using Polkadot SDK-specific APIs for interaction. @@ -84,20 +84,20 @@ For complete Ethereum ecosystem integration with Ethereum RPC support: ### Key Benefits -- **Ethereum tooling compatibility**: Full compatibility with MetaMask, Hardhat, Remix, Truffle, and other Ethereum development tools -- **Minimal-friction migration**: Deployment of existing Ethereum dApps with minimal or no modifications -- **Native Ethereum formats**: Support for Ethereum transaction formats, signatures, and gas mechanics -- **Block emulation**: Ethereum-style block structure within Substrate's block production +- **Ethereum tooling compatibility**: Full compatibility with MetaMask, Hardhat, Remix, Foundry, and other Ethereum development tools. +- **Minimal-friction migration**: Deployment of existing Ethereum dApps with minimal or no modifications. +- **Native Ethereum formats**: Support for Ethereum transaction formats, signatures, and gas mechanics. +- **Block emulation**: Ethereum-style block structure within Substrate's block production. ### Implementation Examples Production implementations demonstrate Frontier's capabilities: -- **Moonbeam**: See their implementation of [`pallet-evm`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L532){target=\_blank} and [`pallet-ethereum`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L698){target=\_blank} +- **Moonbeam**: See their implementation of [`pallet-evm`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L532){target=\_blank} and [`pallet-ethereum`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L698){target=\_blank}. ## pallet-contracts (Legacy) -[`pallet-contracts`](https://docs.rs/pallet-contracts/latest/pallet_contracts/index.html#contracts-pallet){target=\_blank} is the original Wasm-based smart contract pallet for Polkadot SDK chains. While still functional, it's considered legacy as development efforts have shifted to pallet-revive. +[`pallet-contracts`](https://docs.rs/pallet-contracts/latest/pallet_contracts/index.html#contracts-pallet){target=\_blank} is the original Wasm-based smart contract pallet for Polkadot SDK chains. While still functional, it's considered legacy as development efforts have shifted to `pallet-revive`. ### Implementation Example diff --git a/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md b/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md index 748981792..263d742a9 100644 --- a/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md +++ b/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md @@ -1,305 +1,682 @@ --- -title: Benchmarking FRAME Pallets -description: Learn how to use FRAME's benchmarking framework to measure extrinsic execution costs and provide accurate weights for on-chain computations. +title: Benchmark Your Pallet +description: Learn how to benchmark your custom pallet extrinsics to generate accurate weight calculations for production use. categories: Parachains url: https://docs.polkadot.com/parachains/customize-runtime/pallet-development/benchmark-pallet/ --- -# Benchmarking - ## Introduction -Benchmarking is a critical component of developing efficient and secure blockchain runtimes. In the Polkadot ecosystem, accurately benchmarking your custom pallets ensures that each extrinsic has a precise [weight](/reference/glossary/#weight){target=\_blank}, representing its computational and storage demands. This process is vital for maintaining the blockchain's performance and preventing potential vulnerabilities, such as Denial of Service (DoS) attacks. +Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks. + +This guide continues the pallet development series, building on the [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet), [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime), and [Test Your Pallet](/parachains/customize-runtime/pallet-development/pallet-testing) tutorials. You'll learn how to benchmark the counter pallet extrinsics and integrate the generated weights into your runtime. + +## Prerequisites + +Before you begin, ensure you have: + +- Completed the previous pallet development tutorials +- Basic understanding of computational complexity +- Familiarity with Rust's testing framework + +## Why Benchmark? + +In blockchain systems, every operation consumes resources. Weight is the mechanism Polkadot SDK uses to measure and limit resource consumption. Without accurate weights: + +- **Security Risk**: Malicious actors could submit transactions that consume excessive resources, blocking legitimate transactions or halting the chain +- **Inefficiency**: Over-estimated weights waste block space and reduce throughput +- **User Experience**: Inaccurate weights lead to incorrect fee calculations + +Benchmarking provides empirical measurements of your extrinsics under various conditions, ensuring weights reflect real-world resource consumption. + +## Understanding Weights + +The [weight system](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank} serves multiple purposes: + +- **DoS Protection**: Limits the computational work per block, preventing attackers from overwhelming the network +- **Fee Calculation**: Determines transaction fees based on actual resource usage +- **Block Production**: Helps block authors maximize throughput while staying within block limits + +Weights are expressed as [`Weight::from_parts(ref_time, proof_size)`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.from_parts){target=\_blank} where: -The Polkadot SDK leverages the [FRAME](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank} benchmarking framework, offering tools to measure and assign weights to extrinsics. These weights help determine the maximum number of transactions or system-level calls processed within a block. This guide covers how to use FRAME's [benchmarking framework](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank}, from setting up your environment to writing and running benchmarks for your custom pallets. You'll understand how to generate accurate weights by the end, ensuring your runtime remains performant and secure. +- [`ref_time`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.ref_time){target=\_blank}: Computational time measured in picoseconds +- [`proof_size`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.proof_size){target=\_blank}: Storage proof size in bytes -## The Case for Benchmarking +## Step 1: Create the Benchmarking Module -Benchmarking helps validate that the required execution time for different functions is within reasonable boundaries to ensure your blockchain runtime can handle transactions efficiently and securely. By accurately measuring the weight of each extrinsic, you can prevent service interruptions caused by computationally intensive calls that exceed block time limits. Without benchmarking, runtime performance could be vulnerable to DoS attacks, where malicious users exploit functions with unoptimized weights. +Create a new file `benchmarking.rs` in your pallet's `src` directory. This module will contain all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} for your pallet: -Benchmarking also ensures predictable transaction fees. Weights derived from benchmark tests accurately reflect the resource usage of function calls, allowing fair fee calculation. This approach discourages abuse while maintaining network reliability. +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use frame::deps::frame_benchmarking::v2::*; +use frame::benchmarking::prelude::RawOrigin; + +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn set_counter_value() { + let new_value: u32 = 100; -### Benchmarking and Weight + #[extrinsic_call] + _(RawOrigin::Root, new_value); + + assert_eq!(CounterValue::::get(), new_value); + } + + #[benchmark] + fn increment() { + let caller: T::AccountId = whitelisted_caller(); + let amount: u32 = 50; + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), amount); + + assert_eq!(CounterValue::::get(), amount); + assert_eq!(UserInteractions::::get(caller), 1); + } -In Polkadot SDK-based chains, weight quantifies the computational effort needed to process transactions. This weight includes factors such as: + #[benchmark] + fn decrement() { + // First set the counter to a non-zero value + CounterValue::::put(100); -- Computational complexity. -- Storage complexity (proof size). -- Database reads and writes. -- Hardware specifications. + let caller: T::AccountId = whitelisted_caller(); + let amount: u32 = 30; -Benchmarking uses real-world testing to simulate worst-case scenarios for extrinsics. The framework generates a linear model for weight calculation by running multiple iterations with varied parameters. These worst-case weights ensure blocks remain within execution limits, enabling the runtime to maintain throughput under varying loads. Excess fees can be refunded if a call uses fewer resources than expected, offering users a fair cost model. - -Because weight is a generic unit of measurement based on computation time for a specific physical machine, the weight of any function can change based on the specifications of hardware used for benchmarking. By modeling the expected weight of each runtime function, the blockchain can calculate the number of transactions or system-level calls it can execute within a certain period. + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), amount); -Within FRAME, each function call that is dispatched must have a `#[pallet::weight]` annotation that can return the expected weight for the worst-case scenario execution of that function given its inputs: + assert_eq!(CounterValue::::get(), 70); + assert_eq!(UserInteractions::::get(caller), 1); + } -```rust hl_lines="2" -#[pallet::call_index(0)] -#[pallet::weight(T::WeightInfo::do_something())] -pub fn do_something(origin: OriginFor) -> DispatchResultWithPostInfo { Ok(()) } + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} ``` -The `WeightInfo` file is automatically generated during benchmarking. Based on these tests, this file provides accurate weights for each extrinsic. +**Key components:** + +- **`#![cfg(feature = "runtime-benchmarks")]`**: Ensures benchmarking code only compiles when the feature is enabled +- **[`#[benchmarks]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmarks.html){target=\_blank}**: Marks the module containing benchmark definitions +- **[`#[benchmark]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmark.html){target=\_blank}**: Defines individual benchmark functions +- **[`#[extrinsic_call]`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.extrinsic_call.html){target=\_blank}**: Marks the actual extrinsic invocation to measure +- **[`whitelisted_caller()`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/fn.whitelisted_caller.html){target=\_blank}**: Generates a funded account for benchmarking +- **[`impl_benchmark_test_suite!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.impl_benchmark_test_suite.html){target=\_blank}**: Generates test functions to verify benchmarks work correctly + +## Step 2: Define the Weight Trait + +The [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. This enables you to use placeholder weights during development and testing, then switch to auto-generated benchmarked weights in production without modifying the pallet code itself. + +Add a `weights` module to your pallet that defines the `WeightInfo` trait: + +```rust title="pallets/pallet-custom/src/lib.rs" +#[frame::pallet] +pub mod pallet { + use frame::prelude::*; + pub use weights::WeightInfo; + + pub mod weights { + use frame::prelude::*; + + pub trait WeightInfo { + fn set_counter_value() -> Weight; + fn increment() -> Weight; + fn decrement() -> Weight; + } + + impl WeightInfo for () { + fn set_counter_value() -> Weight { + Weight::from_parts(10_000, 0) + } + fn increment() -> Weight { + Weight::from_parts(15_000, 0) + } + fn decrement() -> Weight { + Weight::from_parts(15_000, 0) + } + } + } -## Benchmarking Process + // ... rest of pallet +} +``` -Benchmarking a pallet involves the following steps: +The `()` implementation provides placeholder weights for development. Later, this will be replaced with auto-generated weights from benchmarking. -1. Creating a `benchmarking.rs` file within your pallet's structure. -2. Writing a benchmarking test for each extrinsic. -3. Executing the benchmarking tool to calculate weights based on performance metrics. +## Step 3: Add WeightInfo to Config -The benchmarking tool runs multiple iterations to model worst-case execution times and determine the appropriate weight. By default, the benchmarking pipeline is deactivated. To activate it, compile your runtime with the `runtime-benchmarks` feature flag. +By making `WeightInfo` an associated type in the `Config` trait, you allow each runtime that uses your pallet to specify which weight implementation to use. Different deployment environments (testnets, production chains, or different hardware configurations) may have different performance characteristics and can use different weight calculations. -### Prepare Your Environment +Update your pallet's `Config` trait to include `WeightInfo`: -Install the [`frame-omni-bencher`](https://crates.io/crates/frame-omni-bencher){target=\_blank} command-line tool: +```rust title="pallets/pallet-custom/src/lib.rs" +#[pallet::config] +pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; -```bash -cargo install frame-omni-bencher + #[pallet::constant] + type CounterMaxValue: Get; + + type WeightInfo: weights::WeightInfo; +} ``` -Before writing benchmark tests, you need to ensure the `frame-benchmarking` crate is included in your pallet's `Cargo.toml` similar to the following: +## Step 4: Update Extrinsic Weight Annotations + +By calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. This allows you to easily switch between placeholder weights for testing and benchmarked weights for production without changing any pallet code. + +Replace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait: + +```rust title="pallets/pallet-custom/src/lib.rs" +#[pallet::call] +impl Pallet { + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::set_counter_value())] + pub fn set_counter_value(origin: OriginFor, new_value: u32) -> DispatchResult { + // ... implementation + } + + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::increment())] + pub fn increment(origin: OriginFor, amount: u32) -> DispatchResult { + // ... implementation + } -```toml title="Cargo.toml" -frame-benchmarking = { version = "37.0.0", default-features = false } + #[pallet::call_index(2)] + #[pallet::weight(T::WeightInfo::decrement())] + pub fn decrement(origin: OriginFor, amount: u32) -> DispatchResult { + // ... implementation + } +} ``` -You must also ensure that you add the `runtime-benchmarks` feature flag as follows under the `[features]` section of your pallet's `Cargo.toml`: +## Step 5: Include the Benchmarking Module -```toml title="Cargo.toml" -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] +The `#[cfg(feature = "runtime-benchmarks")]` attribute ensures that benchmarking code is only compiled when explicitly needed. This keeps your production runtime lean by excluding benchmarking infrastructure from normal builds, as it's only needed when generating weights. + +At the top of your `lib.rs`, add the module declaration: + +```rust title="pallets/pallet-custom/src/lib.rs" +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +use alloc::vec::Vec; + +pub use pallet::*; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +// ... rest of the pallet ``` -Lastly, ensure that `frame-benchmarking` is included in `std = []`: +## Step 6: Configure Pallet Dependencies + +The feature flag system in Cargo allows you to conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds. + +Update your pallet's `Cargo.toml` to enable the benchmarking feature: + +```toml title="pallets/pallet-custom/Cargo.toml" +[dependencies] +codec = { features = ["derive"], workspace = true } +scale-info = { features = ["derive"], workspace = true } +frame = { features = ["experimental", "runtime"], workspace = true } -```toml title="Cargo.toml" +[features] +default = ["std"] +runtime-benchmarks = [ + "frame/runtime-benchmarks", +] std = [ - # ... - "frame-benchmarking?/std", - # ... + "codec/std", + "scale-info/std", + "frame/std", ] ``` -Once complete, you have the required dependencies for writing benchmark tests for your pallet. +## Step 7: Update Mock Runtime -### Write Benchmark Tests +In your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo` since unit tests focus on verifying functional correctness rather than performance characteristics. This keeps tests fast and focused on validating logic. -Create a `benchmarking.rs` file in your pallet's `src/`. Your directory structure should look similar to the following: +Add the `WeightInfo` type to your test configuration in `mock.rs`: +```rust title="pallets/pallet-custom/src/mock.rs" +impl pallet_custom::Config for Test { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = (); +} ``` -my-pallet/ -├── src/ -│ ├── lib.rs # Main pallet implementation -│ └── benchmarking.rs # Benchmarking -└── Cargo.toml + +## Step 8: Configure Runtime Benchmarking + +To execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. This involves three configuration steps: + +### Update Runtime Cargo.toml + +When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. + +Add your pallet to the runtime's `runtime-benchmarks` feature in `runtime/Cargo.toml`: + +```toml title="runtime/Cargo.toml" +runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "hex-literal", + "pallet-parachain-template/runtime-benchmarks", + "polkadot-sdk/runtime-benchmarks", + "pallet-custom/runtime-benchmarks", +] ``` -With the directory structure set, you can use the [`polkadot-sdk-parachain-template`](https://github.com/paritytech/polkadot-sdk-parachain-template/tree/master/pallets){target=\_blank} to get started as follows: +### Update Runtime Configuration -```rust title="benchmarking.rs (starter template)" -//! Benchmarking setup for pallet-template -#![cfg(feature = "runtime-benchmarks")] +Start with the placeholder implementation during development. After successfully running benchmarks and generating the weights file, you'll update this to use the benchmarked weights. -use super::*; -use frame_benchmarking::v2::*; +In `runtime/src/configs/mod.rs`, add the `WeightInfo` type: -#[benchmarks] -mod benchmarks { - use super::*; - #[cfg(test)] - use crate::pallet::Pallet as Template; - use frame_system::RawOrigin; - - #[benchmark] - fn do_something() { - let caller: T::AccountId = whitelisted_caller(); - #[extrinsic_call] - do_something(RawOrigin::Signed(caller), 100); - - assert_eq!(Something::::get().map(|v| v.block_number), Some(100u32.into())); - } - - #[benchmark] - fn cause_error() { - Something::::put(CompositeStruct { block_number: 100u32.into() }); - let caller: T::AccountId = whitelisted_caller(); - #[extrinsic_call] - cause_error(RawOrigin::Signed(caller)); - - assert_eq!(Something::::get().map(|v| v.block_number), Some(101u32.into())); - } - - impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test); +```rust title="runtime/src/configs/mod.rs" +impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = (); } ``` -In your benchmarking tests, employ these best practices: +### Register Benchmarks -- **Write custom testing functions**: The function `do_something` in the preceding example is a placeholder. Similar to writing unit tests, you must write custom functions to benchmark test your extrinsics. Access the mock runtime and use functions such as `whitelisted_caller()` to sign transactions and facilitate testing. -- **Use the `#[extrinsic_call]` macro**: This macro is used when calling the extrinsic itself and is a required part of a benchmarking function. See the [`extrinsic_call`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html#extrinsic_call-and-block){target=\_blank} docs for more details. -- **Validate extrinsic behavior**: The `assert_eq` expression ensures that the extrinsic is working properly within the benchmark context. +The `define_benchmarks!` macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks. -Add the `benchmarking` module to your pallet. In the pallet `lib.rs` file add the following: +Add your pallet to the benchmark list in `runtime/src/benchmarks.rs`: -```rust -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; +```rust title="runtime/src/benchmarks.rs" +polkadot_sdk::frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + // ... other pallets + [pallet_custom, CustomPallet] +); ``` -### Add Benchmarks to Runtime +## Step 9: Run Benchmarks -Before running the benchmarking tool, you must integrate benchmarks with your runtime as follows: +### Test Benchmark Compilation -1. Navigate to your `runtime/src` directory and check if a `benchmarks.rs` file exists. If not, create one. This file will contain the macro that registers all pallets for benchmarking along with their respective configurations: +The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the full runtime. - ```rust title="benchmarks.rs" - frame_benchmarking::define_benchmarks!( - [frame_system, SystemBench::] - [pallet_parachain_template, TemplatePallet] - [pallet_balances, Balances] - [pallet_session, SessionBench::] - [pallet_timestamp, Timestamp] - [pallet_message_queue, MessageQueue] - [pallet_sudo, Sudo] - [pallet_collator_selection, CollatorSelection] - [cumulus_pallet_parachain_system, ParachainSystem] - [cumulus_pallet_xcmp_queue, XcmpQueue] - ); - ``` +First, verify your benchmarks compile and run as tests: - For example, to add a new pallet named `pallet_parachain_template` for benchmarking, include it in the macro as shown: - ```rust title="benchmarks.rs" hl_lines="3" - frame_benchmarking::define_benchmarks!( - [frame_system, SystemBench::] - [pallet_parachain_template, TemplatePallet] - ); - ``` +```bash +cargo test -p pallet-custom --features runtime-benchmarks +``` - !!!warning "Updating `define_benchmarks!` macro is required" - Any pallet that needs to be benchmarked must be included in the [`define_benchmarks!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.define_benchmarks.html){target=\_blank} macro. The CLI will only be able to access and benchmark pallets that are registered here. +You should see your benchmark tests passing: -2. Check your runtime's `lib.rs` file to ensure the `benchmarks` module is imported. The import should look like this: +``` +test benchmarking::benchmarks::bench_set_counter_value ... ok +test benchmarking::benchmarks::bench_increment ... ok +test benchmarking::benchmarks::bench_decrement ... ok +``` - ```rust title="lib.rs" - #[cfg(feature = "runtime-benchmarks")] - mod benchmarks; - ``` +### Build the Runtime with Benchmarks - The `runtime-benchmarks` feature gate ensures benchmark tests are isolated from production runtime code. +This build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. This is a special build used only for benchmarking - you'll create a different build later for actually running your chain. -3. Enable runtime benchmarking for your pallet in `runtime/Cargo.toml`: +Compile the runtime with benchmarking enabled to generate the WASM binary: - ```toml - runtime-benchmarks = [ - # ... - "pallet_parachain_template/runtime-benchmarks", - ] +```bash +cargo build --release --features runtime-benchmarks +``` - ``` +This produces the runtime WASM file needed for benchmarking, typically located at: +``` +target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm +``` -### Run Benchmarks +### Install the Benchmarking Tool -You can now compile your runtime with the `runtime-benchmarks` feature flag. This feature flag is crucial as the benchmarking tool will look for this feature being enabled to know when it should run benchmark tests. Follow these steps to compile the runtime with benchmarking enabled: +[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} is the official Polkadot SDK tool specifically designed for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system. -1. Run `build` with the feature flag included: +Install the `frame-omni-bencher` CLI tool: + +```bash +cargo install frame-omni-bencher --locked +``` + +### Download the Weight Template + +The weight template is a Handlebars file that transforms raw benchmark data into a properly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow Polkadot SDK conventions and include all necessary metadata like benchmark execution parameters, storage operation counts, and hardware information. + +Download the official weight template file: + +```bash +curl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \ +--output ./pallets/pallet-custom/frame-weight-template.hbs +``` - ```bash - cargo build --features runtime-benchmarks --release - ``` +### Hardware Requirements for Benchmarking -2. Create a `weights.rs` file in your pallet's `src/` directory. This file will store the auto-generated weight calculations: +!!! warning "Critical: Benchmark on Production-Like Hardware" + Benchmarks must be executed on hardware similar to what will run your chain in production. Weight measurements are hardware-dependent, and benchmarking on different hardware can lead to dangerous under-estimation or wasteful over-estimation of weights. - ```bash - touch weights.rs - ``` +Weights represent the actual computational time and resources consumed by extrinsics. These measurements vary significantly across different hardware configurations: -3. Before running the benchmarking tool, you'll need a template file that defines how weight information should be formatted. Download the official template from the Polkadot SDK repository and save it in your project folders for future use: +- **CPU Performance**: Different processors execute instructions at different speeds. A faster development laptop will produce lower weight values than production server hardware +- **Storage Speed**: Database read/write performance varies between NVMe SSDs, SATA SSDs, and HDDs, affecting storage-related weights +- **Memory Bandwidth**: RAM speed impacts how quickly data can be accessed during execution +- **CPU Cache**: Cache size and architecture differences affect repeated operations - ```bash - curl https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \ - --output ./pallets/benchmarking/frame-weight-template.hbs - ``` +Benchmarking on faster hardware than production leads to under-estimated weights - attackers could submit extrinsics that consume more resources than the weights suggest, potentially causing blocks to take longer than expected to produce or even halting the chain. Conversely, benchmarking on slower hardware creates over-estimated weights, resulting in unnecessarily high transaction fees and wasted block capacity. -4. Run the benchmarking tool to measure extrinsic weights: +**Best practices:** - ```bash - frame-omni-bencher v1 benchmark pallet \ - --runtime INSERT_PATH_TO_WASM_RUNTIME \ - --pallet INSERT_NAME_OF_PALLET \ +1. **Match production specifications**: If your chain will run on specific validator hardware, benchmark on identical or very similar machines +2. **Use reference hardware**: The Polkadot ecosystem often uses standardized reference hardware specifications for consistency. Consider following these standards if your chain will connect to Polkadot or Kusama +3. **Dedicated benchmarking environment**: Run benchmarks on a machine without other heavy processes to ensure consistent measurements +4. **Document your hardware**: The generated weight files include hardware information in comments. Review this to ensure it matches your production environment +5. **Re-benchmark when hardware changes**: If your validator hardware specifications change, re-run benchmarks and update weights + +For development and testing purposes, you can run benchmarks on any available hardware to verify that your benchmark functions work correctly. However, before deploying to production, always re-run benchmarks on production-equivalent hardware. + +### Execute Benchmarks + +Benchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking the WASM ensures your weight measurements reflect real-world conditions. + +Run benchmarks for your pallet to generate weight files: + +```bash +frame-omni-bencher v1 benchmark pallet \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ + --pallet pallet_custom \ --extrinsic "" \ - --template ./frame-weight-template.hbs \ - --output weights.rs - ``` - - !!! tip "Flag definitions" - - **`--runtime`**: The path to your runtime's Wasm. - - **`--pallet`**: The name of the pallet you wish to benchmark. This pallet must be configured in your runtime and defined in `define_benchmarks`. - - **`--extrinsic`**: Which extrinsic to test. Using `""` implies all extrinsics will be benchmarked. - - **`--template`**: Defines how weight information should be formatted. - - **`--output`**: Where the output of the auto-generated weights will reside. - -The generated `weights.rs` file contains weight annotations for your extrinsics, ready to be added to your pallet. The output should be similar to the following. Some output is omitted for brevity: - -
- frame-omni-bencher v1 benchmark pallet \ - --runtime INSERT_PATH_TO_WASM_RUNTIME \ - --pallet "INSERT_NAME_OF_PALLET" \ - --extrinsic "" \ - --template ./frame-weight-template.hbs \ - --output ./weights.rs - ... - 2025-01-15T16:41:33.557045Z INFO polkadot_sdk_frame::benchmark::pallet: [ 0 % ] Starting benchmark: pallet_parachain_template::do_something - 2025-01-15T16:41:33.564644Z INFO polkadot_sdk_frame::benchmark::pallet: [ 50 % ] Starting benchmark: pallet_parachain_template::cause_error - ... - Created file: "weights.rs" - -
- -#### Add Benchmark Weights to Pallet - -Once the `weights.rs` is generated, you must integrate it with your pallet. - -1. To begin the integration, import the `weights` module and the `WeightInfo` trait, then add both to your pallet's `Config` trait. Complete the following steps to set up the configuration: - - ```rust title="lib.rs" - pub mod weights; + --template ./pallets/pallet-custom/frame-weight-template.hbs \ + --output ./pallets/pallet-custom/src/weights.rs +``` + +**Command breakdown:** + +- `v1`: Specifies the benchmarking framework version (v2 API) +- `benchmark pallet`: Subcommand indicating you want to benchmark pallet extrinsics +- `--runtime`: Path to the compiled WASM runtime file that includes your pallet and benchmarks +- `--pallet pallet_custom`: Name of the pallet to benchmark (must match the name used in `define_benchmarks!`) +- `--extrinsic ""`: Empty string benchmarks all extrinsics in the pallet; you can specify a single extrinsic name to benchmark only that one +- `--template`: Path to the Handlebars template that formats the output +- `--output`: Destination file path for the generated weights module + +### Advanced Options + +You can customize benchmark execution with additional parameters for more detailed measurements: + +```bash +frame-omni-bencher v1 benchmark pallet \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ + --pallet pallet_custom \ + --extrinsic "" \ + --steps 50 \ + --repeat 20 \ + --template ./pallets/pallet-custom/frame-weight-template.hbs \ + --output ./pallets/pallet-custom/src/weights.rs +``` + +**Additional parameters:** + +- `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time +- `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise and providing more reliable weight estimates +- `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution +- `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions + +## Step 10: Use Generated Weights + +After running benchmarks, a `weights.rs` file is generated containing measured weights. The generated weights are based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. Estimates or placeholder values cannot capture these nuances and will either waste block space (over-estimation) or create security risks (under-estimation). + +The file includes: + +- Detailed documentation about the benchmark execution environment (date, hardware, parameters) +- The `WeightInfo` trait definition matching your benchmark functions +- `SubstrateWeight` implementation with measured weights from your benchmarks +- Database read/write costs calculated based on observed storage operations +- Component complexity annotations for variable inputs (if you use linear components) +- A fallback `()` implementation for testing environments + +### Integrate the Generated Weights + +Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during normal operation to calculate transaction fees and enforce block limits. + +Add the weights module to your pallet's `lib.rs`: + +```rust title="pallets/pallet-custom/src/lib.rs" +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +use alloc::vec::Vec; + +pub use pallet::*; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +pub mod weights; + +#[frame::pallet] +pub mod pallet { + use super::*; + use frame::prelude::*; use crate::weights::WeightInfo; + // ... rest of pallet +} +``` + +### Update Runtime Configuration - /// Configure the pallet by specifying the parameters and types on which it depends. - #[pallet::config] - pub trait Config: frame_system::Config { - // ... - /// A type representing the weights required by the dispatchables of this pallet. - type WeightInfo: WeightInfo; +This change activates your benchmarked weights in the production runtime. Now when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits. + +Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation: + +```rust title="runtime/src/configs/mod.rs" +impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = pallet_custom::weights::SubstrateWeight; +} +``` + +### Example Generated Weight File + +The generated `weights.rs` file will look similar to this: + +```rust title="pallets/pallet-custom/src/weights.rs" +//! Autogenerated weights for `pallet_custom` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20` + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +pub trait WeightInfo { + fn set_counter_value() -> Weight; + fn increment() -> Weight; + fn decrement() -> Weight; +} + +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + fn set_counter_value() -> Weight { + Weight::from_parts(8_234_000, 0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) } - ``` -2. Next, you must add this to the `#[pallet::weight]` annotation in all the extrinsics via the `Config` as follows: + fn increment() -> Weight { + Weight::from_parts(12_456_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } - ```rust hl_lines="2" title="lib.rs" - #[pallet::call_index(0)] - #[pallet::weight(T::WeightInfo::do_something())] - pub fn do_something(origin: OriginFor) -> DispatchResultWithPostInfo { Ok(()) } - ``` + fn decrement() -> Weight { + Weight::from_parts(11_987_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} +``` + +**Note**: The actual numbers will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} accounts for database read and write operations. + +## Benchmarking Best Practices -3. Finally, configure the actual weight values in your runtime. In `runtime/src/config/mod.rs`, add the following code: +### 1. Test Worst-Case Scenarios - ```rust title="mod.rs" - // Configure pallet. - impl pallet_parachain_template::Config for Runtime { - // ... - type WeightInfo = pallet_parachain_template::weights::SubstrateWeight; +Benchmarks should always measure maximum possible resource consumption. If you benchmark average or best-case scenarios, malicious users could craft transactions that hit worst-case paths in your code, consuming more resources than the weights indicate and potentially slowing down or halting block production. + +```rust +#[benchmark] +fn complex_operation() { + // Set up worst-case storage state + for i in 0..100 { + SomeStorage::::insert(i, vec![0u8; 1000]); } - ``` -## Where to Go Next + let caller = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller)); +} +``` + +### 2. Use Linear Components for Variable Complexity + +Many extrinsics have variable costs depending on input parameters. [Linear components](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/trait.BenchmarkingSetup.html){target=\_blank} tell the benchmarking framework to test your extrinsic with different values of `n`, measure the execution time for each, and calculate a formula like `Weight = base_weight + (n * per_item_weight)`. This produces dynamic weights that accurately reflect the actual work being done. + +When extrinsic complexity depends on input size, use linear components: + +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#[benchmark] +fn process_items(n: Linear<0, 100>) { + let caller = whitelisted_caller(); + let items: Vec = (0..n).collect(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller), items); +} +``` + +### 3. Verify Results + +Assertions ensure that your benchmark is actually testing the code path you think it's testing. If your extrinsic fails silently or takes an early return, the benchmark would measure the wrong scenario and produce inaccurate weights. + +Always assert the expected state after extrinsic execution: + +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#[benchmark] +fn my_extrinsic() { + let caller = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone())); + + // Verify the extrinsic had the expected effect + assert_eq!(MyStorage::::get(&caller), expected_value); +} +``` + +### 4. Minimize Setup Code + +While the benchmarking framework tries to isolate the extrinsic execution, excessive setup code can add noise to measurements. More importantly, setup code that doesn't reflect real-world pre-conditions can lead to benchmarking unrealistic scenarios. + +Only include necessary setup in benchmarks: + +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#[benchmark] +fn efficient_benchmark() { + // Minimal setup + let caller = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller)); + + // Minimal assertions +} +``` + +## Run Your Chain Locally + +Now that you've added the pallet to your runtime, you can launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide. + +### Build the Production Runtime + +The `runtime-benchmarks` feature flag adds special host functions (like `ext_benchmarking_current_time` and `ext_benchmarking_get_read_and_written_keys`) that are only available in the benchmarking execution environment. These functions allow the benchmarking framework to precisely measure execution time and track storage operations. However, regular nodes don't provide these host functions, so a runtime compiled with benchmarking features will fail to start on a production node. + +Before running your chain, rebuild the runtime **without** the `runtime-benchmarks` feature: + +```bash +cargo build --release +``` + +!!! note "Build Types" + Understanding the difference between builds is critical: + + - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher` + - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your actual chain + +This produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. + +### Generate a Chain Specification + +The chain specification defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. By generating a new chain spec with your updated runtime (now containing your benchmarked pallet), you ensure that nodes starting from this spec will use the correct version of your code with proper weight calculations. + +Create a new chain specification file with the updated runtime: + +```bash +chain-spec-builder create -t development \ +--relay-chain paseo \ +--para-id 1000 \ +--runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ +named-preset development +``` + +This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime. + +### Start the Parachain Node + +Launch the parachain using the Polkadot Omni Node with the generated chain specification by running the following command: + +```bash +polkadot-omni-node --chain ./chain_spec.json --dev +``` + +The node will start and display initialization information including: + +- The chain specification name +- The node identity and peer ID +- Database location +- Network endpoints (JSON-RPC and Prometheus) + +### Verify Block Production + +Once the node is running, you should see log messages indicating successful block production: + +``` +[Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc) +[Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ... +[Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2) +[Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ... +[Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32) +``` + +The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. + +## Related Resources -- View the Rust Docs for a more comprehensive, low-level view of the [FRAME V2 Benchmarking Suite](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=_blank}. -- Read the [FRAME Benchmarking and Weights](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_benchmarking_weight/index.html){target=_blank} reference document, a concise guide which details how weights and benchmarking work. +- [FRAME Benchmarking Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/index.html){target=\_blank} +- [Weight Struct Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html){target=\_blank} +- [Benchmarking v2 API](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} +- [frame-omni-bencher Tool](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} diff --git a/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md b/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md index 6b36c500f..6dd373bcb 100644 --- a/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md +++ b/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md @@ -671,7 +671,7 @@ This command validates all pallet configurations and prepares the build for depl ## Run Your Chain Locally -Launch your parachain locally to test the new pallet functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. +Launch your parachain locally to test the new pallet functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide. ### Generate a Chain Specification diff --git a/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md b/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md index d2c8e9ade..b0cc72fa0 100644 --- a/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md +++ b/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md @@ -213,7 +213,7 @@ export default buildModule("StorageModule", (m) => { Deploy the contract to Polkadot Hub TestNet: ```bash -npx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotHub +npx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotTestNet ``` You should see output similar to: diff --git a/.ai/pages/smart-contracts-for-eth-devs-migration.md b/.ai/pages/smart-contracts-for-eth-devs-migration.md index e791fd24d..58c91eb15 100644 --- a/.ai/pages/smart-contracts-for-eth-devs-migration.md +++ b/.ai/pages/smart-contracts-for-eth-devs-migration.md @@ -1,5 +1,151 @@ --- +title: Migration FAQs and Considerations +description: Learn how to migrate your existing Ethereum contracts to the Polkadot Hub using REVM and PolkaVM by following these considerations. +categories: Smart Contracts url: https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/ --- -TODO +# Migration FAQs and Considerations + +## Introduction + +This guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns. + +## Migration Considerations + +Take into account the following considerations before migrating your contracts: + +- Standard ERC-20, ERC-721, ERC-1155 tokens work without changes. +- DeFi protocols, DEXs, and AMMs migrate seamlessly. +- DAOs and governance contracts are fully compatible. +- Most Solidity contracts deploy identically to Ethereum. + +## Migration Checklist + +Before migrating your contracts, review this checklist: + +- Factory contracts using PVM bytecode need pre-uploaded dependencies. +- Contracts using `EXTCODECOPY` for runtime manipulation require review (for projects that will use PVM bytecode, not EVM bytecode). +- Replace `transfer()` and `send()` with proper reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode). + +## Migration FAQs + +### Which backend should I choose? + +- Choose REVM if you want: + + - Zero-modification deployment of existing Ethereum contracts. + - Exact EVM behavior for audited code. + - Compatibility with tools that inspect EVM bytecode. + - Rapid deployment without optimization. + +- Choose PolkaVM if you want: + + - Better performance for computation-heavy applications. + - Lower execution costs for intensive operations. + - Access to next-generation smart contract features. + +If you are unsure which to choose, start with REVM for immediate compatibility, then consider PolkaVM for performance optimization once deployed. + +### Do I need to rewrite my Solidity code? + +No, for most contracts. Standard Solidity patterns work on both backends. + +### What about factory contracts? + +- **REVM**: Factory contracts work identically to Ethereum with no changes needed. + + The original factory pattern is: + + ```solidity + contract TokenFactory { + function createToken(string memory name) public returns (address) { + // Creates new contract at runtime + Token newToken = new Token(name); + return address(newToken); + } + } + ``` + +- **PolkaVM**: Factory contracts require pre-uploading dependent contracts. + + Here's how to adapt the original factory pattern: + + ```solidity + contract TokenFactory { + // Reference pre-uploaded Token contract by hash + bytes32 public tokenCodeHash; + + constructor(bytes32 _tokenCodeHash) { + tokenCodeHash = _tokenCodeHash; + } + + function createToken(string memory name) public returns (address) { + // Instantiate from pre-uploaded code + Token newToken = new Token{salt: keccak256(abi.encode(name))}(name); + return address(newToken); + } + } + ``` + +The deployment steps for PolkaVM factories are: + +1. Upload the contract code to the chain. +2. Note the returned code hash. +3. Deploy the Factory contract with the contract code hash. +4. Factory can now instantiate contracts using the pre-uploaded code. + +### How do gas costs compare? + +For more information on gas costs, see the [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} page. + +### Which Solidity features are not supported? + +For REVM, any Solidity feature will function smoothly without requiring changes or adaptations. For PVM, there are considerations, as was mentioned above. + +For PolkaVM, there are some considerations: + +- `EXTCODECOPY`: Only works in constructor code. +- Runtime code modification: Use on-chain constructors instead. +- **Gas stipends**: `address.send()` and `address.transfer()` don't provide reentrancy protection. +- **Unsupported operations**: `pc`, `extcodecopy`, `selfdestruct`, `blobhash`, and `blobbasefee` (blob-related operations). + +### How do I handle the existential deposit? + +Polkadot requires accounts to maintain a minimum balance (existential deposit or ED) to remain active. + +This is handled automatically for you: + +- Balance queries via Ethereum RPC automatically deduct the ED. +- New account transfers include ED in transaction fees. +- Contract-to-contract transfers draw ED from the transaction signer. + +You typically don't need to do anything special, but be aware: + +- Accounts below ED threshold are automatically deleted. +- ED is around 0.01 DOT (varies by network). +- Your contracts don't need to manage this explicitly. + +### Can I use my existing development tools? + +Yes. Both backends support: + +- **Wallets**: [MetaMask](https://metamask.io/){target=\_blank}, [Talisman](https://talisman.xyz/){target=\_blank}, [SubWallet](https://www.subwallet.app/){target=\_blank} +- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\_blank}, [Foundry](/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/){target=\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} (just consider that for PVM bytecode, you will use the Polkadot version of the tooling) +- **Libraries**: [ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank}, [web3.js](/smart-contracts/libraries/web3-js/){target=\_blank}, [viem](/smart-contracts/libraries/viem/){target=\_blank} +- **Testing tools**: Your existing test suites work + +Connect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow. + +## Conclusion + +Most Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance. + +There are a few key points to keep in mind during migration: + +- Replace `transfer()` and `send()` with `.call{value}("")` and use reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode). +- PolkaVM factory contracts using PVM bytecode need pre-uploaded dependencies. +- Don't hardcode gas values. +- Test thoroughly on [TestNet](/smart-contracts/connect/#__tabbed_1_1){target=\_blank} before mainnet deployment. + +Your existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns. diff --git a/.ai/site-index.json b/.ai/site-index.json index 64e35be44..1882988e9 100644 --- a/.ai/site-index.json +++ b/.ai/site-index.json @@ -17,7 +17,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -38,7 +37,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -59,7 +57,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -80,7 +77,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -101,7 +97,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -122,7 +117,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -234,7 +228,6 @@ "estimated_token_count_total": 4830 }, "hash": "sha256:a6bf7623a535e7a9162c0913b07bd59d43c8535025ad8225fb3e5adc83084c7a", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -306,7 +299,6 @@ "estimated_token_count_total": 7755 }, "hash": "sha256:086a87823ab67ceac102358030e316583cd733c0ec326316e7f29061fe7f6934", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -327,7 +319,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -389,7 +380,6 @@ "estimated_token_count_total": 5207 }, "hash": "sha256:91f59a76dd33641ca2b5bf6d58230f65034fa3cc5f8313525fb57e854a878a56", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -481,7 +471,6 @@ "estimated_token_count_total": 2132 }, "hash": "sha256:1b9efd2fe00b251d3b4054c9cfcb55f9b5a1384238eeaca81a6f1542fc36d75c", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -502,7 +491,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -569,7 +557,6 @@ "estimated_token_count_total": 4063 }, "hash": "sha256:bd07cdae71bf63786994865d2f33fba5f7bf8855dce6399414ad44ab0ec6635c", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -626,7 +613,6 @@ "estimated_token_count_total": 2225 }, "hash": "sha256:e916033f54c2874eb5ce9a43d58af058eb935429f73b7b1acc7da1592218e0b8", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -674,7 +660,6 @@ "estimated_token_count_total": 1523 }, "hash": "sha256:d9d85827d2c14bff8dd6b3301617345430cf63db603e37859720713004ecafae", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -694,9 +679,7 @@ "headings": 0, "estimated_token_count_total": 0 }, - "hash": "sha256:2b017d8a89f8734b9cbb501f03612a22657d2f8d4d85c51e490e4c8ca4bf771b", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", "token_estimator": "heuristic-v1" }, { @@ -754,7 +737,6 @@ "estimated_token_count_total": 1635 }, "hash": "sha256:46252e238b0b51105148dc622da6d8809c55ec11da7ec7b2953c35ca52f5f585", - "last_modified": "2025-10-28T14:42:10+00:00", "token_estimator": "heuristic-v1" }, { @@ -797,7 +779,6 @@ "estimated_token_count_total": 1491 }, "hash": "sha256:db37b2f5888f283b5eb5bd84a5f8c81fc66b2313e3f94f510a73dfeb310ae3f0", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -864,7 +845,6 @@ "estimated_token_count_total": 955 }, "hash": "sha256:72ee7394fd1308c111a8d548cb4dc63c6b9bc5b6e2bb556dd1baacbaedb92286", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -916,7 +896,6 @@ "estimated_token_count_total": 876 }, "hash": "sha256:d6cb22337280a19bdf24981dcba98f337d48ee4f79ce7ac040466ef1cb4b330b", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -998,7 +977,6 @@ "estimated_token_count_total": 2744 }, "hash": "sha256:1a2d34ccab19bd71263763bbc294977acf34f5800398f51398753594cfc7d7a6", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -1070,7 +1048,6 @@ "estimated_token_count_total": 608 }, "hash": "sha256:7bba6105d99721373aa6f494627d20af97b1851c19703f26be26c32f0c83524b", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -1137,7 +1114,6 @@ "estimated_token_count_total": 558 }, "hash": "sha256:b79fe56c9604712825bdf30d17667fd8f237fce9691be0d8d042d38691dbba7a", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -1189,7 +1165,58 @@ "estimated_token_count_total": 348 }, "hash": "sha256:11cd8d428fa9c3e70490da5c63ce4597cd89ec46306d2bb49b016ced6aa68c3d", - "last_modified": "2025-10-28T14:42:11+00:00", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-versions-v5", + "title": "XCMv5", + "slug": "develop-interoperability-versions-v5", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/", + "preview": "The latest iteration of XCM is version 5. The main RFCs defining the changes in version 5 are the following:", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 2970, + "words": 438, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:3821c2ef97699091b76e1de58e6d95e866df69d39fca16f2a15c156b71da5b22", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-versions", + "title": "XCM Versions", + "slug": "develop-interoperability-versions", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/", + "preview": "XCM is a versioned language that evolves to meet the growing needs of cross-chain communication in the Polkadot ecosystem. Understanding XCM versioning is essential for developers building interoperable applications to keep up with the latest improvements.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 835, + "words": 114, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:634e299f347beb8ad690697943bb7f99915d62d40cda4227179619ed18abe2ff", "token_estimator": "heuristic-v1" }, { @@ -1237,7 +1264,6 @@ "estimated_token_count_total": 1365 }, "hash": "sha256:5f8fa89fc725c5c559975012fe2f9ae92c3b62f10024b5688dcd118331118f1a", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -1290,7 +1316,6 @@ "estimated_token_count_total": 4979 }, "hash": "sha256:ed3b7c8101b69f9c907cca7c5edfef67fdb5e7bc3c8df8d9fbad297f9dd3c80a", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -1347,7 +1372,6 @@ "estimated_token_count_total": 1781 }, "hash": "sha256:35c71a215558cd0642d363e4515ad240093995d42720e6495cd2994c859243e4", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -1394,7 +1418,6 @@ "estimated_token_count_total": 1447 }, "hash": "sha256:0e39aee80fbcf3dfaa19133f31d664914ed45b42a1a929270f05d8ae876b89e2", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -1441,7 +1464,6 @@ "estimated_token_count_total": 1082 }, "hash": "sha256:ec82957c768c2c07a272e7a28659c812b223df836e21372b1642f0bb249d7b39", - "last_modified": "2025-10-28T14:42:11+00:00", "token_estimator": "heuristic-v1" }, { @@ -1483,7 +1505,63 @@ "estimated_token_count_total": 4178 }, "hash": "sha256:d480791a76082937b47c77f7cf3794e701f193452ed347fcb1c04c3c67577bf5", - "last_modified": "2025-10-28T14:42:11+00:00", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-xcm-guides-from-apps", + "title": "From Apps", + "slug": "develop-interoperability-xcm-guides-from-apps", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/", + "preview": "This section shows how to interact with XCM from applications, providing practical guidance for implementing cross-chain functionality in your dApps and services.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 511, + "words": 70, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:63584f5b1dab7b67b18b35b47dfc19d00ad5c013804772f0d653a11ac3fca38d", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-xcm-guides", + "title": "XCM Guides", + "slug": "develop-interoperability-xcm-guides", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/", + "preview": "This section provides comprehensive guides for implementing XCM functionality, including application development patterns, fee management, asset transfers, and cross-chain transaction handling.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1663, + "words": 215, + "headings": 2, + "estimated_token_count_total": 340 + }, + "hash": "sha256:d4c2d7fd46ddf60f638f948c88ba3940de6d69f140923ba8df52ed787b0afede", "token_estimator": "heuristic-v1" }, { @@ -1551,7 +1629,37 @@ "estimated_token_count_total": 6510 }, "hash": "sha256:353ad782303ef79bce1262bfa945e6f11b3c3c9ca1edf5705b778c46bada6200", - "last_modified": "2025-10-28T14:42:12+00:00", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability", + "title": "Interoperability", + "slug": "develop-interoperability", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/", + "preview": "This section covers everything you need to know about building and implementing [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\\_blank} solutions in the Polkadot ecosystem. Whether you're working on establishing cross-chain channels, sending and receiving XCM messages, or testing and debugging your cross-chain configurations, you'll find the essential resources and tools here to support your interoperability needs, regardless of your development focus.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 2363, + "words": 323, + "headings": 2, + "estimated_token_count_total": 402 + }, + "hash": "sha256:5da6bdeec1deee5ef3d7ab1a43f546067bcef91acdc67df4ce114ee8f8669e82", "token_estimator": "heuristic-v1" }, { @@ -1614,19 +1722,19 @@ "estimated_token_count_total": 1520 }, "hash": "sha256:ed09ef7a6abe21204006186fd5791ada7597688fad67e30244dc449c51330309", - "last_modified": "2025-10-28T14:42:12+00:00", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-customize-parachain-add-existing-pallets", - "title": "Add a Pallet to the Runtime", - "slug": "develop-parachains-customize-parachain-add-existing-pallets", + "id": "develop-parachains-customize-parachain-overview", + "title": "Overview of FRAME", + "slug": "develop-parachains-customize-parachain-overview", "categories": [ + "Basics", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain-add-existing-pallets.md", - "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/add-existing-pallets/", - "preview": "The [Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk-solochain-template){target=\\_blank} provides a functional runtime that includes default FRAME development modules (pallets) to help you get started with building a custom blockchain.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain-overview.md", + "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/overview/", + "preview": "The runtime is the heart of any Polkadot SDK-based blockchain, handling the essential logic that governs state changes and transaction processing. With Polkadot SDK’s [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_bank}, developers gain access to a powerful suite of tools for building custom blockchain runtimes. FRAME offers a modular architecture, featuring reusable pallets and su", "outline": [ { "depth": 2, @@ -1635,91 +1743,38 @@ }, { "depth": 2, - "title": "Configuring Runtime Dependencies", - "anchor": "configuring-runtime-dependencies" - }, - { - "depth": 2, - "title": "Dependencies for a New Pallet", - "anchor": "dependencies-for-a-new-pallet" - }, - { - "depth": 2, - "title": "Config Trait for Pallets", - "anchor": "config-trait-for-pallets" + "title": "FRAME Runtime Architecture", + "anchor": "frame-runtime-architecture" }, { "depth": 3, - "title": "Utility Pallet Example", - "anchor": "utility-pallet-example" - }, - { - "depth": 2, - "title": "Parameter Configuration for Pallets", - "anchor": "parameter-configuration-for-pallets" - }, - { - "depth": 2, - "title": "Pallet Config in the Runtime", - "anchor": "pallet-config-in-the-runtime" + "title": "Pallets", + "anchor": "pallets" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 11939, - "words": 1615, - "headings": 8, - "estimated_token_count_total": 2598 - }, - "hash": "sha256:b2b3d8c048863e7760f633b12ab2a0202c741be3050ea4beafb9a7265cfe96b5", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-customize-parachain-add-pallet-instances", - "title": "Add Multiple Pallet Instances", - "slug": "develop-parachains-customize-parachain-add-pallet-instances", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain-add-pallet-instances.md", - "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/add-pallet-instances/", - "preview": "Running multiple instances of the same pallet within a runtime is a powerful technique in Polkadot SDK development. This approach lets you reuse pallet functionality without reimplementing it, enabling diverse use cases with the same codebase. The Polkadot SDK provides developer-friendly traits for creating instantiable pallets and, in most cases, handles unique storage allocation for different instances automatically. This guide teaches you how to implement and configure multiple instances of a", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Support Libraries", + "anchor": "support-libraries" }, { "depth": 2, - "title": "Understanding Instantiable Pallets", - "anchor": "understanding-instantiable-pallets" + "title": "Compose a Runtime with Pallets", + "anchor": "compose-a-runtime-with-pallets" }, { "depth": 2, - "title": "Adding Instantiable Pallets to Your Runtime", - "anchor": "adding-instantiable-pallets-to-your-runtime" - }, - { - "depth": 3, - "title": "Define Pallet Parameters", - "anchor": "define-pallet-parameters" + "title": "Starting from Templates", + "anchor": "starting-from-templates" }, { "depth": 3, - "title": "Configure the Pallet Instances", - "anchor": "configure-the-pallet-instances" + "title": "Solochain Templates", + "anchor": "solochain-templates" }, { "depth": 3, - "title": "Add Pallet Instances to the Runtime", - "anchor": "add-pallet-instances-to-the-runtime" + "title": "Parachain Templates", + "anchor": "parachain-templates" }, { "depth": 2, @@ -1728,69 +1783,55 @@ } ], "stats": { - "chars": 6294, - "words": 729, - "headings": 7, - "estimated_token_count_total": 1219 + "chars": 9427, + "words": 1267, + "headings": 9, + "estimated_token_count_total": 2019 }, - "hash": "sha256:262e7a3ad3d0a0102897c52c7589e3f94c7827c441398b3b446b205f6c6753d3", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:d03ea172f2af9f4648e730d60033a80c2c1e64efa9241fed0c1ba40a5f846ae5", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-customize-parachain-add-smart-contract-functionality", - "title": "Add Smart Contract Functionality", - "slug": "develop-parachains-customize-parachain-add-smart-contract-functionality", + "id": "develop-parachains-customize-parachain", + "title": "Customize Your Parachain", + "slug": "develop-parachains-customize-parachain", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain-add-smart-contract-functionality.md", - "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/add-smart-contract-functionality/", - "preview": "When building your custom blockchain with the Polkadot SDK, you have the flexibility to add smart contract capabilities through specialized pallets. These pallets allow blockchain users to deploy and execute smart contracts, enhancing your chain's functionality and programmability.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain.md", + "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/", + "preview": "Learn how to build a custom parachain with Polkadot SDK's FRAME framework, which includes pallet development, testing, smart contracts, and runtime customization. Pallets are modular components within the FRAME ecosystem that contain specific blockchain functionalities. This modularity grants developers increased flexibility and control around which behaviors to include in the core logic of their parachain.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "EVM Smart Contracts", - "anchor": "evm-smart-contracts" - }, - { - "depth": 2, - "title": "Wasm Smart Contracts", - "anchor": "wasm-smart-contracts" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 3896, - "words": 523, - "headings": 4, - "estimated_token_count_total": 905 + "chars": 1899, + "words": 259, + "headings": 2, + "estimated_token_count_total": 335 }, - "hash": "sha256:ad8e6d9c77d5451c5f4d17f8e6311b21e6ad24eae8780fd4c3ae6013744822cf", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:9a08b66442c564c7116c686d8914b74ad617326f450d0894b05e753462f69aac", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-customize-parachain-make-custom-pallet", - "title": "Make a Custom Pallet", - "slug": "develop-parachains-customize-parachain-make-custom-pallet", + "id": "develop-parachains-deployment-build-deterministic-runtime", + "title": "Build a deterministic runtime", + "slug": "develop-parachains-deployment-build-deterministic-runtime", "categories": [ "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain-make-custom-pallet.md", - "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/make-custom-pallet/", - "preview": "FRAME provides a powerful set of tools for blockchain development, including a library of pre-built pallets. However, its true strength lies in the ability to create custom pallets tailored to your specific needs. This section will guide you through creating your own custom pallet, allowing you to extend your blockchain's functionality in unique ways.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-build-deterministic-runtime.md", + "html_url": "https://docs.polkadot.com/develop/parachains/deployment/build-deterministic-runtime/", + "preview": "By default, the Rust compiler produces optimized Wasm binaries. These binaries are suitable for working in an isolated environment, such as local development. However, the Wasm binaries the compiler builds by default aren't guaranteed to be deterministically reproducible. Each time the compiler generates the Wasm runtime, it might produce a slightly different Wasm byte code. This is problematic in a blockchain network where all nodes must use exactly the same raw chain specification file.", "outline": [ { "depth": 2, @@ -1799,67 +1840,64 @@ }, { "depth": 2, - "title": "Initial Setup", - "anchor": "initial-setup" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Pallet Configuration", - "anchor": "pallet-configuration" + "title": "Tooling for Wasm Runtime", + "anchor": "tooling-for-wasm-runtime" }, { "depth": 2, - "title": "Pallet Events", - "anchor": "pallet-events" + "title": "Working with the Docker Container", + "anchor": "working-with-the-docker-container" }, { "depth": 2, - "title": "Pallet Errors", - "anchor": "pallet-errors" + "title": "Prepare the Environment", + "anchor": "prepare-the-environment" }, { "depth": 2, - "title": "Pallet Storage", - "anchor": "pallet-storage" + "title": "Start a Deterministic Build", + "anchor": "start-a-deterministic-build" }, { "depth": 2, - "title": "Pallet Dispatchable Extrinsics", - "anchor": "pallet-dispatchable-extrinsics" + "title": "Use srtool in GitHub Actions", + "anchor": "use-srtool-in-github-actions" }, { "depth": 2, - "title": "Pallet Implementation Overview", - "anchor": "pallet-implementation-overview" + "title": "Use the srtool Image via Docker Hub", + "anchor": "use-the-srtool-image-via-docker-hub" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Naming Convention for Images", + "anchor": "naming-convention-for-images" } ], "stats": { - "chars": 17824, - "words": 2311, + "chars": 8470, + "words": 1227, "headings": 9, - "estimated_token_count_total": 3995 + "estimated_token_count_total": 1944 }, - "hash": "sha256:19997d390abf2847824024ba923f46a61106ef77544d256d50b371210816b309", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:4fc8cab40e982e860b64d9aede1058fe7fa82ec321ac215b919db00c4df0a9c0", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-customize-parachain-overview", - "title": "Overview of FRAME", - "slug": "develop-parachains-customize-parachain-overview", + "id": "develop-parachains-deployment-coretime-renewal", + "title": "Coretime Renewal", + "slug": "develop-parachains-deployment-coretime-renewal", "categories": [ - "Basics", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain-overview.md", - "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/overview/", - "preview": "The runtime is the heart of any Polkadot SDK-based blockchain, handling the essential logic that governs state changes and transaction processing. With Polkadot SDK’s [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_bank}, developers gain access to a powerful suite of tools for building custom blockchain runtimes. FRAME offers a modular architecture, featuring reusable pallets and su", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-coretime-renewal.md", + "html_url": "https://docs.polkadot.com/develop/parachains/deployment/coretime-renewal/", + "preview": "Coretime can be purchased in bulk for a period of 28 days, providing access to Polkadot's shared security and interoperability for Polkadot parachains. The bulk purchase of coretime includes a rent-control mechanism that keeps future purchases within a predictable price range of the initial purchase. This allows cores to be renewed at a known price without competing against other participants in the open market.", "outline": [ { "depth": 2, @@ -1868,162 +1906,28 @@ }, { "depth": 2, - "title": "FRAME Runtime Architecture", - "anchor": "frame-runtime-architecture" - }, - { - "depth": 3, - "title": "Pallets", - "anchor": "pallets" + "title": "Bulk Sale Phases", + "anchor": "bulk-sale-phases" }, { - "depth": 3, - "title": "Support Libraries", - "anchor": "support-libraries" + "depth": 2, + "title": "Renewal Timing", + "anchor": "renewal-timing" }, { "depth": 2, - "title": "Compose a Runtime with Pallets", - "anchor": "compose-a-runtime-with-pallets" + "title": "Manual Renewal", + "anchor": "manual-renewal" }, { "depth": 2, - "title": "Starting from Templates", - "anchor": "starting-from-templates" + "title": "Auto-Renewal", + "anchor": "auto-renewal" }, { "depth": 3, - "title": "Solochain Templates", - "anchor": "solochain-templates" - }, - { - "depth": 3, - "title": "Parachain Templates", - "anchor": "parachain-templates" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 9427, - "words": 1267, - "headings": 9, - "estimated_token_count_total": 2019 - }, - "hash": "sha256:0becb82886d34e2ed23d963efd2c14120112e6e080ea4072e864531299b59753", - "last_modified": "2025-10-28T14:42:12+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-deployment-build-deterministic-runtime", - "title": "Build a deterministic runtime", - "slug": "develop-parachains-deployment-build-deterministic-runtime", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-build-deterministic-runtime.md", - "html_url": "https://docs.polkadot.com/develop/parachains/deployment/build-deterministic-runtime/", - "preview": "By default, the Rust compiler produces optimized Wasm binaries. These binaries are suitable for working in an isolated environment, such as local development. However, the Wasm binaries the compiler builds by default aren't guaranteed to be deterministically reproducible. Each time the compiler generates the Wasm runtime, it might produce a slightly different Wasm byte code. This is problematic in a blockchain network where all nodes must use exactly the same raw chain specification file.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Tooling for Wasm Runtime", - "anchor": "tooling-for-wasm-runtime" - }, - { - "depth": 2, - "title": "Working with the Docker Container", - "anchor": "working-with-the-docker-container" - }, - { - "depth": 2, - "title": "Prepare the Environment", - "anchor": "prepare-the-environment" - }, - { - "depth": 2, - "title": "Start a Deterministic Build", - "anchor": "start-a-deterministic-build" - }, - { - "depth": 2, - "title": "Use srtool in GitHub Actions", - "anchor": "use-srtool-in-github-actions" - }, - { - "depth": 2, - "title": "Use the srtool Image via Docker Hub", - "anchor": "use-the-srtool-image-via-docker-hub" - }, - { - "depth": 3, - "title": "Naming Convention for Images", - "anchor": "naming-convention-for-images" - } - ], - "stats": { - "chars": 8470, - "words": 1227, - "headings": 9, - "estimated_token_count_total": 1944 - }, - "hash": "sha256:4fc8cab40e982e860b64d9aede1058fe7fa82ec321ac215b919db00c4df0a9c0", - "last_modified": "2025-10-28T14:42:12+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-deployment-coretime-renewal", - "title": "Coretime Renewal", - "slug": "develop-parachains-deployment-coretime-renewal", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-coretime-renewal.md", - "html_url": "https://docs.polkadot.com/develop/parachains/deployment/coretime-renewal/", - "preview": "Coretime can be purchased in bulk for a period of 28 days, providing access to Polkadot's shared security and interoperability for Polkadot parachains. The bulk purchase of coretime includes a rent-control mechanism that keeps future purchases within a predictable price range of the initial purchase. This allows cores to be renewed at a known price without competing against other participants in the open market.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Bulk Sale Phases", - "anchor": "bulk-sale-phases" - }, - { - "depth": 2, - "title": "Renewal Timing", - "anchor": "renewal-timing" - }, - { - "depth": 2, - "title": "Manual Renewal", - "anchor": "manual-renewal" - }, - { - "depth": 2, - "title": "Auto-Renewal", - "anchor": "auto-renewal" - }, - { - "depth": 3, - "title": "Set Up an HRMP Channel", - "anchor": "set-up-an-hrmp-channel" + "title": "Set Up an HRMP Channel", + "anchor": "set-up-an-hrmp-channel" }, { "depth": 3, @@ -2053,7 +1957,6 @@ "estimated_token_count_total": 3068 }, "hash": "sha256:9918593a46c12a1756552ddfaf7421ad6262600735b6f1fec030911420fe1736", - "last_modified": "2025-10-28T14:42:12+00:00", "token_estimator": "heuristic-v1" }, { @@ -2135,7 +2038,6 @@ "estimated_token_count_total": 3025 }, "hash": "sha256:a60fe36a5ba6d1cafe12eab75300afd24a46d3ace1e791087adb7e3e538afcc3", - "last_modified": "2025-10-28T14:42:12+00:00", "token_estimator": "heuristic-v1" }, { @@ -2187,7 +2089,6 @@ "estimated_token_count_total": 1289 }, "hash": "sha256:39c58dbe2ddcd542d7074d08d72f1811318dc8a3130419025480fd5cbe9fc3e7", - "last_modified": "2025-10-28T14:42:12+00:00", "token_estimator": "heuristic-v1" }, { @@ -2223,152 +2124,7 @@ "headings": 3, "estimated_token_count_total": 966 }, - "hash": "sha256:358ed14147b96b47deb61df9a1ea0e1103a139ea5edb78c5d50a48d5a779b80d", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-install-polkadot-sdk", - "title": "Install Polkadot SDK Dependencies", - "slug": "develop-parachains-install-polkadot-sdk", - "categories": [ - "Basics", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-install-polkadot-sdk.md", - "html_url": "https://docs.polkadot.com/develop/parachains/install-polkadot-sdk/", - "preview": "This guide provides step-by-step instructions for installing the dependencies you need to work with the Polkadot SDK-based chains on macOS, Linux, and Windows. Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly.", - "outline": [ - { - "depth": 2, - "title": "macOS", - "anchor": "macos" - }, - { - "depth": 3, - "title": "Before You Begin", - "anchor": "before-you-begin" - }, - { - "depth": 3, - "title": "Install Required Packages and Rust", - "anchor": "install-required-packages-and-rust" - }, - { - "depth": 2, - "title": "Linux", - "anchor": "linux" - }, - { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-linux }", - "anchor": "before-you-begin-before-you-begin-linux" - }, - { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-linux }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-linux" - }, - { - "depth": 2, - "title": "Windows (WSL)", - "anchor": "windows-wsl" - }, - { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-windows }", - "anchor": "before-you-begin-before-you-begin-windows" - }, - { - "depth": 3, - "title": "Set Up Windows Subsystem for Linux", - "anchor": "set-up-windows-subsystem-for-linux" - }, - { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-windows }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-windows" - }, - { - "depth": 2, - "title": "Verifying Installation", - "anchor": "verifying-installation" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 12756, - "words": 1840, - "headings": 12, - "estimated_token_count_total": 2709 - }, - "hash": "sha256:2ee5656f749b4bca445172f2bc66c7fc39af40ff173626662ae4c399f49cf909", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-intro-polkadot-sdk", - "title": "Introduction to Polkadot SDK", - "slug": "develop-parachains-intro-polkadot-sdk", - "categories": [ - "Basics", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-intro-polkadot-sdk.md", - "html_url": "https://docs.polkadot.com/develop/parachains/intro-polkadot-sdk/", - "preview": "The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2){target=\\_blank} is a powerful and versatile developer kit designed to facilitate building on the Polkadot network. It provides the necessary components for creating custom blockchains, parachains, generalized rollups, and more. Written in the Rust programming language, it puts security and robustness at the forefront of its design.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Polkadot SDK Overview", - "anchor": "polkadot-sdk-overview" - }, - { - "depth": 3, - "title": "Substrate", - "anchor": "substrate" - }, - { - "depth": 3, - "title": "FRAME", - "anchor": "frame" - }, - { - "depth": 3, - "title": "Cumulus", - "anchor": "cumulus" - }, - { - "depth": 2, - "title": "Why Use Polkadot SDK?", - "anchor": "why-use-polkadot-sdk" - }, - { - "depth": 2, - "title": "Create a Custom Blockchain Using the SDK", - "anchor": "create-a-custom-blockchain-using-the-sdk" - } - ], - "stats": { - "chars": 8758, - "words": 1156, - "headings": 7, - "estimated_token_count_total": 1892 - }, - "hash": "sha256:74de798c287cae75729e7db54019507f03a361dbbd1f2bb58c4694605f83efab", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:b25618dc598f4f946da06f854211645768214e0b51d06b684b0cab668b66124c", "token_estimator": "heuristic-v1" }, { @@ -2420,7 +2176,6 @@ "estimated_token_count_total": 4719 }, "hash": "sha256:bfad885d8053d052c55dbffc3c09e6196586795c3a1d07ab6ad58f9006ec3345", - "last_modified": "2025-10-28T14:42:12+00:00", "token_estimator": "heuristic-v1" }, { @@ -2482,7 +2237,6 @@ "estimated_token_count_total": 1819 }, "hash": "sha256:b0c1535fa8e969a9bdeee426a5a35a42b4649121fb8ce6fd2b15fdeba35b5d5f", - "last_modified": "2025-10-28T14:42:12+00:00", "token_estimator": "heuristic-v1" }, { @@ -2513,9 +2267,7 @@ "headings": 2, "estimated_token_count_total": 236 }, - "hash": "sha256:07e63e1e99b9acf1cc3b5ef8fa1f06ff22182b2a801582ce800eba37d7d39408", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:3b0a9e8037c7634c33ac6674170bd763599fca914855d9d2fbf490d359140130", "token_estimator": "heuristic-v1" }, { @@ -2546,9 +2298,7 @@ "headings": 2, "estimated_token_count_total": 211 }, - "hash": "sha256:55dc252fdecf1590048ce8d009b822e90231442abe81e9593cf1635944a31336", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:0ce1fe38de00827a0735b9fa8076492205c2450c61da9fbd1937d9f38cfe7825", "token_estimator": "heuristic-v1" }, { @@ -2579,61 +2329,29 @@ "headings": 2, "estimated_token_count_total": 330 }, - "hash": "sha256:f4964f894f7cd2fdfd699c017b4bd25cffc322b03a5a88a36c682cf952832ccc", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:75a6fa2f21b67009be62e07bab01655a10b2c35a5292dc1f7ca57df846d709f3", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-testing-benchmarking", - "title": "Benchmarking FRAME Pallets", - "slug": "develop-parachains-testing-benchmarking", + "id": "develop-smart-contracts-connect-to-kusama", + "title": "Connect to Kusama", + "slug": "develop-smart-contracts-connect-to-kusama", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-testing-benchmarking.md", - "html_url": "https://docs.polkadot.com/develop/parachains/testing/benchmarking/", - "preview": "Benchmarking is a critical component of developing efficient and secure blockchain runtimes. In the Polkadot ecosystem, accurately benchmarking your custom pallets ensures that each extrinsic has a precise [weight](/polkadot-protocol/glossary/#weight){target=\\_blank}, representing its computational and storage demands. This process is vital for maintaining the blockchain's performance and preventing potential vulnerabilities, such as Denial of Service (DoS) attacks.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-connect-to-kusama.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/connect-to-kusama/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Networks Details", + "anchor": "networks-details" }, { "depth": 2, - "title": "The Case for Benchmarking", - "anchor": "the-case-for-benchmarking" - }, - { - "depth": 3, - "title": "Benchmarking and Weight", - "anchor": "benchmarking-and-weight" - }, - { - "depth": 2, - "title": "Benchmarking Process", - "anchor": "benchmarking-process" - }, - { - "depth": 3, - "title": "Prepare Your Environment", - "anchor": "prepare-your-environment" - }, - { - "depth": 3, - "title": "Write Benchmark Tests", - "anchor": "write-benchmark-tests" - }, - { - "depth": 3, - "title": "Add Benchmarks to Runtime", - "anchor": "add-benchmarks-to-runtime" - }, - { - "depth": 3, - "title": "Run Benchmarks", - "anchor": "run-benchmarks" + "title": "Important Deployment Considerations", + "anchor": "important-deployment-considerations" }, { "depth": 2, @@ -2642,217 +2360,206 @@ } ], "stats": { - "chars": 14731, - "words": 1881, - "headings": 9, - "estimated_token_count_total": 3342 + "chars": 3601, + "words": 476, + "headings": 3, + "estimated_token_count_total": 514 }, - "hash": "sha256:9d6daa3f4daf149ae822b60060d14ff022bd4b3440cecdc969a48c105eb82a21", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:e8ffeaa3a17e20437a59f2c95a63821eb75bf3c33001e748c23958b2b99ac3c2", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-testing-mock-runtime", - "title": "Mock Runtime for Pallet Testing", - "slug": "develop-parachains-testing-mock-runtime", + "id": "develop-smart-contracts-dev-environments", + "title": "Dev Environments", + "slug": "develop-smart-contracts-dev-environments", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-testing-mock-runtime.md", - "html_url": "https://docs.polkadot.com/develop/parachains/testing/mock-runtime/", - "preview": "Testing is essential in Polkadot SDK development to ensure your blockchain operates as intended and effectively handles various potential scenarios. This guide walks you through setting up an environment to test pallets within the [runtime](/polkadot-protocol/glossary#runtime){target=_blank}, allowing you to evaluate how different pallets, their configurations, and system components interact to ensure reliable blockchain functionality.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-dev-environments.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/dev-environments/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Explore the tools and frameworks available for building and testing smart contracts on the Polkadot network. These environments streamline the development process, from writing and compiling to testing and deploying smart contracts. The guides in this section will help you evaluate each tool's strengths, making it easier to choose t", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "What to Consider", + "anchor": "what-to-consider" }, { "depth": 2, - "title": "Configuring a Mock Runtime", - "anchor": "configuring-a-mock-runtime" + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 1601, + "words": 154, + "headings": 2, + "estimated_token_count_total": 323 + }, + "hash": "sha256:5c3a10769e30b4da62e6c188e99310354e6e9af4595c7920c2977a54b8e1853c", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-smart-contracts-faqs", + "title": "Polkadot Hub Smart Contract FAQs", + "slug": "develop-smart-contracts-faqs", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-faqs.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/faqs/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. !!! note For a list of known incompatibilities, please refer to the [Solidity and Yul IR translation incompatibilities](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#solidity-and-yul-ir-translation-incompatibilities){target=\\_blank} section.", + "outline": [ + { + "depth": 2, + "title": "General Questions", + "anchor": "general-questions" }, { "depth": 3, - "title": "Testing Module", - "anchor": "testing-module" + "title": "What are the different types of smart contracts I can build on Polkadot?", + "anchor": "what-are-the-different-types-of-smart-contracts-i-can-build-on-polkadot" }, { "depth": 3, - "title": "Genesis Storage", - "anchor": "genesis-storage" + "title": "Should I build a smart contract or a parachain?", + "anchor": "should-i-build-a-smart-contract-or-a-parachain" }, { "depth": 3, - "title": "Pallet Configuration", - "anchor": "pallet-configuration" + "title": "What's the difference between Polkadot Hub smart contracts and other EVM chains?", + "anchor": "whats-the-difference-between-polkadot-hub-smart-contracts-and-other-evm-chains" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 7493, - "words": 904, - "headings": 6, - "estimated_token_count_total": 1572 - }, - "hash": "sha256:68fc67390e24741081c9a04d78951e76c7d4ff7cf6eddaba7dcbbdc1812c71d3", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-testing-pallet-testing", - "title": "Pallet Testing", - "slug": "develop-parachains-testing-pallet-testing", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-testing-pallet-testing.md", - "html_url": "https://docs.polkadot.com/develop/parachains/testing/pallet-testing/", - "preview": "Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.", - "outline": [ + "title": "Development Environment", + "anchor": "development-environment" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Can I use my existing Ethereum development tools?", + "anchor": "can-i-use-my-existing-ethereum-development-tools" + }, + { + "depth": 3, + "title": "How do I set up local development?", + "anchor": "how-do-i-set-up-local-development" + }, + { + "depth": 3, + "title": "What networks are available for testing and deployment?", + "anchor": "what-networks-are-available-for-testing-and-deployment" }, { "depth": 2, - "title": "Writing Unit Tests", - "anchor": "writing-unit-tests" + "title": "Technical Implementation", + "anchor": "technical-implementation" }, { "depth": 3, - "title": "Test Initialization", - "anchor": "test-initialization" + "title": "How do Ethereum addresses work on Polkadot?", + "anchor": "how-do-ethereum-addresses-work-on-polkadot" }, { "depth": 3, - "title": "Function Call Testing", - "anchor": "function-call-testing" + "title": "What are the key differences in the gas model?", + "anchor": "what-are-the-key-differences-in-the-gas-model" }, { "depth": 3, - "title": "Storage Testing", - "anchor": "storage-testing" + "title": "How does contract deployment work?", + "anchor": "how-does-contract-deployment-work" }, { "depth": 3, - "title": "Event Testing", - "anchor": "event-testing" + "title": "Which Solidity features are not supported?", + "anchor": "which-solidity-features-are-not-supported" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 6871, - "words": 909, - "headings": 7, - "estimated_token_count_total": 1559 - }, - "hash": "sha256:0024f5e4c12ab7b019e5ee183e7c78d175e1125868c5458b97d3accd9fac75bc", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-smart-contracts-connect-to-kusama", - "title": "Connect to Kusama", - "slug": "develop-smart-contracts-connect-to-kusama", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-connect-to-kusama.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/connect-to-kusama/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", - "outline": [ + "depth": 3, + "title": "How do I handle the existential deposit requirement?", + "anchor": "how-do-i-handle-the-existential-deposit-requirement" + }, { "depth": 2, - "title": "Networks Details", - "anchor": "networks-details" + "title": "Migration and Compatibility", + "anchor": "migration-and-compatibility" }, { - "depth": 2, - "title": "Important Deployment Considerations", - "anchor": "important-deployment-considerations" + "depth": 3, + "title": "Can I migrate my existing Ethereum contracts?", + "anchor": "can-i-migrate-my-existing-ethereum-contracts" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 3601, - "words": 476, - "headings": 3, - "estimated_token_count_total": 514 - }, - "hash": "sha256:e8ffeaa3a17e20437a59f2c95a63821eb75bf3c33001e748c23958b2b99ac3c2", - "last_modified": "2025-10-28T14:42:12+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-smart-contracts-connect-to-polkadot", - "title": "Connect to Polkadot", - "slug": "develop-smart-contracts-connect-to-polkadot", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-connect-to-polkadot.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/connect-to-polkadot/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", - "outline": [ + "title": "Troubleshooting", + "anchor": "troubleshooting" + }, { - "depth": 2, - "title": "Networks Details", - "anchor": "networks-details" + "depth": 3, + "title": "Why are my gas calculations different?", + "anchor": "why-are-my-gas-calculations-different" }, { - "depth": 2, - "title": "Test Tokens", - "anchor": "test-tokens" + "depth": 3, + "title": "I deployed a contract with MetaMask, and got a `code size` error - why?", + "anchor": "i-deployed-a-contract-with-metamask-and-got-a-code-size-error-why" + }, + { + "depth": 3, + "title": "I found a bug, where can I log it?", + "anchor": "i-found-a-bug-where-can-i-log-it" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Known Issues", + "anchor": "known-issues" + }, + { + "depth": 3, + "title": "Runtime Behavior", + "anchor": "runtime-behavior" + }, + { + "depth": 3, + "title": "Development Tools", + "anchor": "development-tools" + }, + { + "depth": 3, + "title": "Contract Patterns", + "anchor": "contract-patterns" + }, + { + "depth": 3, + "title": "Compilation", + "anchor": "compilation" } ], "stats": { - "chars": 3496, - "words": 482, - "headings": 3, - "estimated_token_count_total": 570 + "chars": 7480, + "words": 984, + "headings": 25, + "estimated_token_count_total": 1618 }, - "hash": "sha256:1247dfb5f5ac040bca81cd1002153e0ee53f4052b2a3d40b623834bd7f00d065", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:5cc63ff0a377ef0ec96a064748e13b88bc852bd1862c6e344066855a7fe93b19", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-dev-environments-foundry", - "title": "Use Foundry with Polkadot Hub", - "slug": "develop-smart-contracts-dev-environments-foundry", + "id": "develop-smart-contracts-libraries", + "title": "Libraries", + "slug": "develop-smart-contracts-libraries", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-dev-environments.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/dev-environments/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Explore the tools and frameworks available for building and testing smart contracts on the Polkadot network. These environments streamline the development process, from writing and compiling to testing and deploying smart contracts. The guides in this section will help you evaluate each tool's strengths, making it easier to choose t", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-libraries.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/libraries/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Explore the key libraries for interacting with smart contracts on Polkadot-based networks. These libraries simplify contract calls, event listening, and transaction handling.", "outline": [ { "depth": 2, - "title": "What to Consider", - "anchor": "what-to-consider" + "title": "Library Comparison", + "anchor": "library-comparison" }, { "depth": 2, @@ -2861,322 +2568,352 @@ } ], "stats": { - "chars": 1601, - "words": 154, + "chars": 2056, + "words": 203, "headings": 2, - "estimated_token_count_total": 323 + "estimated_token_count_total": 415 }, - "hash": "sha256:72e41f816f07026d96c803f399c71852aa1151c464e79cec3e1746b282d5eaae", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:23137f6c74412fd98c0b6aeee3ff59938e44b817ec42974c453f9b0f66e36513", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-dev-environments-hardhat", - "title": "Use Hardhat with Polkadot Hub", - "slug": "develop-smart-contracts-dev-environments-hardhat", + "id": "develop-smart-contracts-precompiles-interact-with-precompiles", + "title": "Interact with Precompiles", + "slug": "develop-smart-contracts-precompiles-interact-with-precompiles", "categories": [ - "Smart Contracts", - "Tooling" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-dev-environments-hardhat.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/dev-environments/hardhat/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
- :octicons-code-16:{ .lg .middle } __Test and Deploy with Hardhat__", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-precompiles-interact-with-precompiles.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/precompiles/interact-with-precompiles/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, - "title": "Overview", - "anchor": "overview" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Basic Precompile Interaction Pattern", + "anchor": "basic-precompile-interaction-pattern" }, { "depth": 2, - "title": "Set Up Hardhat", - "anchor": "set-up-hardhat" + "title": "ECRecover (0x01)", + "anchor": "ecrecover-0x01" }, { "depth": 2, - "title": "Compile Your Contract", - "anchor": "compile-your-contract" + "title": "SHA-256 (0x02)", + "anchor": "sha-256-0x02" }, { "depth": 2, - "title": "Set Up a Testing Environment", - "anchor": "set-up-a-testing-environment" + "title": "RIPEMD-160 (0x03)", + "anchor": "ripemd-160-0x03" }, { "depth": 2, - "title": "Test Your Contract", - "anchor": "test-your-contract" + "title": "Identity (Data Copy) (0x04)", + "anchor": "identity-data-copy-0x04" }, { "depth": 2, - "title": "Deploy to a Local Node", - "anchor": "deploy-to-a-local-node" + "title": "Modular Exponentiation (0x05)", + "anchor": "modular-exponentiation-0x05" }, { "depth": 2, - "title": "Deploying to a Live Network", - "anchor": "deploying-to-a-live-network" + "title": "BN128 Addition (0x06)", + "anchor": "bn128-addition-0x06" }, { "depth": 2, - "title": "Interacting with Your Contract", - "anchor": "interacting-with-your-contract" + "title": "BN128 Scalar Multiplication (0x07)", + "anchor": "bn128-scalar-multiplication-0x07" }, { "depth": 2, - "title": "Upgrading the Plugin", - "anchor": "upgrading-the-plugin" + "title": "BN128 Pairing Check (0x08)", + "anchor": "bn128-pairing-check-0x08" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Blake2F (0x09)", + "anchor": "blake2f-0x09" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 18520, - "words": 2475, - "headings": 11, - "estimated_token_count_total": 4188 + "chars": 18054, + "words": 2190, + "headings": 12, + "estimated_token_count_total": 3847 }, - "hash": "sha256:fe008393aa37c27bb71b4483d4e2c4fbcda94f8c1be461fdd07eff40efbb4e26", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:4b705b8dbe9b0ad8d19a897d91f3c64dbc4541297dadacbea2a31b4778e50a46", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-dev-environments-remix", - "title": "Use the Polkadot Remix IDE", - "slug": "develop-smart-contracts-dev-environments-remix", + "id": "develop-smart-contracts", + "title": "Smart Contracts", + "slug": "develop-smart-contracts", "categories": [ - "Smart Contracts", - "Tooling" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-dev-environments-remix.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/dev-environments/remix/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
- :octicons-code-16:{ .lg .middle } __Deploy NFTs Using Remix IDE__", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Polkadot allows scalable execution of smart contracts, offering cross-chain compatibility and lower fees than legacy L1 platforms. Polkadot provides developers with flexibility in building smart contracts, supporting both Solidity contracts executed by the [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\\_blank} (a Polkadot", "outline": [ { "depth": 2, - "title": "Overview", - "anchor": "overview" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Accessing Remix IDE", - "anchor": "accessing-remix-ide" - }, - { - "depth": 2, - "title": "Creating a New Contract", - "anchor": "creating-a-new-contract" - }, - { - "depth": 2, - "title": "Compiling Your Contract", - "anchor": "compiling-your-contract" + "title": "Smart Contract Development Process", + "anchor": "smart-contract-development-process" }, { "depth": 2, - "title": "Deploying Contracts", - "anchor": "deploying-contracts" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1867, + "words": 247, + "headings": 2, + "estimated_token_count_total": 189 + }, + "hash": "sha256:4b56a119cbc63d87de98554cf4019e48ddb4f7cee11a51553ea234f91d78f8b8", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-api-libraries", + "title": "API Libraries", + "slug": "develop-toolkit-api-libraries", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/", + "preview": "Explore the powerful API libraries designed for interacting with the Polkadot network. These libraries offer developers versatile tools to build, query, and manage blockchain interactions. Whether you’re working with JavaScript, TypeScript, Python, or RESTful services, they provide the flexibility to efficiently interact with and retrieve data from Polkadot-based chains.", + "outline": [ { "depth": 2, - "title": "Interacting with Contracts", - "anchor": "interacting-with-contracts" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 6732, - "words": 913, - "headings": 8, - "estimated_token_count_total": 1375 + "chars": 1082, + "words": 139, + "headings": 2, + "estimated_token_count_total": 187 }, - "hash": "sha256:8e6bfed5fa59bb748e80698ea702f62ce6951c48bdb955ee9ef0d3516e856887", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:746788d1068fe3eaafc34eb461566d1682c27fcad7d448e65810b9662b45dd85", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-faqs", - "title": "Polkadot Hub Smart Contract FAQs", - "slug": "develop-smart-contracts-faqs", + "id": "develop-toolkit-integrations-storage", + "title": "Storage", + "slug": "develop-toolkit-integrations-storage", "categories": [ - "Smart Contracts" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-faqs.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/faqs/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. !!! note For a list of known incompatibilities, please refer to the [Solidity and Yul IR translation incompatibilities](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#solidity-and-yul-ir-translation-incompatibilities){target=\\_blank} section.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-storage.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/storage/", + "preview": "Polkadot offers developers a range of decentralized storage solutions to manage dApp data, host front ends, and store large files in a censorship-resistant and resilient manner. These integrations are essential for building fully decentralized applications, ensuring that all components of your dApp, from the front end to the data, are not reliant on centralized servers.", "outline": [ { "depth": 2, - "title": "General Questions", - "anchor": "general-questions" + "title": "Key Storage Solutions", + "anchor": "key-storage-solutions" }, { - "depth": 3, - "title": "What are the different types of smart contracts I can build on Polkadot?", - "anchor": "what-are-the-different-types-of-smart-contracts-i-can-build-on-polkadot" + "depth": 2, + "title": "Crust Network", + "anchor": "crust-network" }, { "depth": 3, - "title": "Should I build a smart contract or a parachain?", - "anchor": "should-i-build-a-smart-contract-or-a-parachain" + "title": "Key Features of Crust", + "anchor": "key-features-of-crust" }, { "depth": 3, - "title": "What's the difference between Polkadot Hub smart contracts and other EVM chains?", - "anchor": "whats-the-difference-between-polkadot-hub-smart-contracts-and-other-evm-chains" + "title": "Use Cases", + "anchor": "use-cases" }, { "depth": 2, - "title": "Development Environment", - "anchor": "development-environment" - }, - { - "depth": 3, - "title": "Can I use my existing Ethereum development tools?", - "anchor": "can-i-use-my-existing-ethereum-development-tools" - }, - { - "depth": 3, - "title": "How do I set up local development?", - "anchor": "how-do-i-set-up-local-development" + "title": "IPFS", + "anchor": "ipfs" }, { "depth": 3, - "title": "What networks are available for testing and deployment?", - "anchor": "what-networks-are-available-for-testing-and-deployment" + "title": "Using IPFS with Polkadot", + "anchor": "using-ipfs-with-polkadot" }, { "depth": 2, - "title": "Technical Implementation", - "anchor": "technical-implementation" - }, + "title": "Other Solutions", + "anchor": "other-solutions" + } + ], + "stats": { + "chars": 4369, + "words": 642, + "headings": 7, + "estimated_token_count_total": 847 + }, + "hash": "sha256:a206dd86fc3d80aed22384000839ca0c9c75c69ad461abd9810d96c03cf6a3bd", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-integrations-transaction-construction", + "title": "Transaction Construction", + "slug": "develop-toolkit-integrations-transaction-construction", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-transaction-construction.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/transaction-construction/", + "preview": "This page will discuss the transaction format in Polkadot and how to create, sign, and broadcast transactions, as well as highlight some of the commands and tools available for integrators.", + "outline": [ { - "depth": 3, - "title": "How do Ethereum addresses work on Polkadot?", - "anchor": "how-do-ethereum-addresses-work-on-polkadot" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "What are the key differences in the gas model?", - "anchor": "what-are-the-key-differences-in-the-gas-model" + "depth": 2, + "title": "Transaction Format", + "anchor": "transaction-format" }, { "depth": 3, - "title": "How does contract deployment work?", - "anchor": "how-does-contract-deployment-work" + "title": "Mode and Metadata Hash", + "anchor": "mode-and-metadata-hash" }, { "depth": 3, - "title": "Which Solidity features are not supported?", - "anchor": "which-solidity-features-are-not-supported" + "title": "Serialized Transactions and Metadata", + "anchor": "serialized-transactions-and-metadata" }, { "depth": 3, - "title": "How do I handle the existential deposit requirement?", - "anchor": "how-do-i-handle-the-existential-deposit-requirement" + "title": "Transaction Flow", + "anchor": "transaction-flow" }, { "depth": 2, - "title": "Migration and Compatibility", - "anchor": "migration-and-compatibility" + "title": "Polkadot-JS Tools", + "anchor": "polkadot-js-tools" }, { "depth": 3, - "title": "Can I migrate my existing Ethereum contracts?", - "anchor": "can-i-migrate-my-existing-ethereum-contracts" + "title": "Creating a Transaction, Signing, and Submitting", + "anchor": "creating-a-transaction-signing-and-submitting" }, { "depth": 2, - "title": "Troubleshooting", - "anchor": "troubleshooting" - }, - { - "depth": 3, - "title": "Why are my gas calculations different?", - "anchor": "why-are-my-gas-calculations-different" + "title": "Txwrapper", + "anchor": "txwrapper" }, { "depth": 3, - "title": "I deployed a contract with MetaMask, and got a `code size` error - why?", - "anchor": "i-deployed-a-contract-with-metamask-and-got-a-code-size-error-why" - }, - { - "depth": 3, - "title": "I found a bug, where can I log it?", - "anchor": "i-found-a-bug-where-can-i-log-it" + "title": "Creating a Transaction, Signing, and Submitting", + "anchor": "creating-a-transaction-signing-and-submitting-2" }, { "depth": 2, - "title": "Known Issues", - "anchor": "known-issues" - }, - { - "depth": 3, - "title": "Runtime Behavior", - "anchor": "runtime-behavior" - }, - { - "depth": 3, - "title": "Development Tools", - "anchor": "development-tools" - }, + "title": "Additional Libraries for Submitting a Transaction", + "anchor": "additional-libraries-for-submitting-a-transaction" + } + ], + "stats": { + "chars": 27671, + "words": 2949, + "headings": 10, + "estimated_token_count_total": 6280 + }, + "hash": "sha256:9b03477d13a285fced6bf845c3827084f790a626989dc2c09ef9ff53643045f4", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-integrations", + "title": "Integrations", + "slug": "develop-toolkit-integrations", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/", + "preview": "Polkadot offers a wide range of integrations that allow developers to enhance their decentralized applications (dApps) and leverage the full capabilities of the ecosystem. Whether you’re looking to extend your application’s functionality, integrate with other chains, or access specialized services, these integrations provide the tools and resources you need to build efficiently and effectively. Explore the available options to find the solutions that best suit your development needs.", + "outline": [ { - "depth": 3, - "title": "Contract Patterns", - "anchor": "contract-patterns" + "depth": 2, + "title": "Key Integration Solutions", + "anchor": "key-integration-solutions" }, { - "depth": 3, - "title": "Compilation", - "anchor": "compilation" + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 7480, - "words": 984, - "headings": 25, - "estimated_token_count_total": 1618 + "chars": 988, + "words": 135, + "headings": 2, + "estimated_token_count_total": 92 }, - "hash": "sha256:5cc63ff0a377ef0ec96a064748e13b88bc852bd1862c6e344066855a7fe93b19", - "last_modified": "2025-10-28T14:42:12+00:00", + "hash": "sha256:0de8c1655a1524784010b6cec5fa522b2f764e32f18913f0d262283e0ec0779e", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-libraries", - "title": "Libraries", - "slug": "develop-smart-contracts-libraries", + "id": "develop-toolkit-interoperability", + "title": "Interoperability", + "slug": "develop-toolkit-interoperability", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-libraries.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/libraries/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Explore the key libraries for interacting with smart contracts on Polkadot-based networks. These libraries simplify contract calls, event listening, and transaction handling.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-interoperability.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/interoperability/", + "preview": "Polkadot's XCM tooling ecosystem redefines the boundaries of cross-chain communication and asset movement. With unparalleled flexibility and scalability, these advanced tools empower developers to build decentralized applications that connect parachains, relay chains, and external networks. By bridging siloed blockchains, Polkadot paves the way for a unified, interoperable ecosystem that accelerates innovation and collaboration.", "outline": [ { "depth": 2, - "title": "Library Comparison", - "anchor": "library-comparison" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 1010, + "words": 128, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:c72d7d30a019fe1db8ab3993f91dfd4f1bdb4a932aaa685d3baaa0578091d5ce", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains-e2e-testing", + "title": "E2E Testing on Polkadot SDK Chains", + "slug": "develop-toolkit-parachains-e2e-testing", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-e2e-testing.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/e2e-testing/", + "preview": ":::INSERT_IN_THIS_SECTION:::", + "outline": [ { "depth": 2, "title": "In This Section", @@ -3184,87 +2921,117 @@ } ], "stats": { - "chars": 31726, - "words": 3942, - "headings": 35, - "estimated_token_count_total": 9750 + "chars": 64, + "words": 6, + "headings": 1, + "estimated_token_count_total": 12 }, - "hash": "sha256:1fb7a20bc4a799a771954720428029419ec73afa640e589590c43dd041a7e307", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:cc49fdcc63a43247d80de2f309b9c7501d3054782746d80c003d95f3c43da90d", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-libraries-ethers-js", - "title": "Deploy Contracts to Polkadot Hub with Ethers.js", - "slug": "develop-smart-contracts-libraries-ethers-js", + "id": "develop-toolkit-parachains-fork-chains-chopsticks", + "title": "Chopsticks", + "slug": "develop-toolkit-parachains-fork-chains-chopsticks", "categories": [ - "Smart Contracts", - "Tooling" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-libraries-ethers-js.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/libraries/ethers-js/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-fork-chains-chopsticks.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/fork-chains/chopsticks/", + "preview": "Chopsticks is a powerful tool that lets you create local copies of running Polkadot SDK-based networks. By forking live chains locally, you can safely test features, analyze network behavior, and simulate complex scenarios without affecting production networks.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "What Can I Do with Chopsticks?", + "anchor": "what-can-i-do-with-chopsticks" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Project Structure", - "anchor": "project-structure" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1495, + "words": 201, + "headings": 3, + "estimated_token_count_total": 291 + }, + "hash": "sha256:b568596033cdf68e60d72bcb7ee62a794def2bd3ff5b3317ef15895f58a12c57", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains-fork-chains", + "title": "Fork Chains for Testing", + "slug": "develop-toolkit-parachains-fork-chains", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-fork-chains.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/fork-chains/", + "preview": "Explore tools for forking live blockchain networks. These tools enable you to replicate real-world conditions in a local environment for accurate testing and debugging. They also allow you to analyze network behavior, test new features, and simulate complex scenarios in a controlled environment without affecting production systems.", + "outline": [ { "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" + "title": "Why Fork a Live Chain?", + "anchor": "why-fork-a-live-chain" }, { "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Set Up the Ethers.js Provider", - "anchor": "set-up-the-ethersjs-provider" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1269, + "words": 173, + "headings": 3, + "estimated_token_count_total": 183 + }, + "hash": "sha256:d29a845b00b24e03f9877a5331c33619918decf453657969115d5ec18033ba28", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains-quickstart-pop-cli", + "title": "Quickstart Parachain Development with Pop CLI", + "slug": "develop-toolkit-parachains-quickstart-pop-cli", + "categories": [ + "Parachains", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-quickstart-pop-cli.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/quickstart/pop-cli/", + "preview": "[Pop CLI](https://onpop.io/cli/){target=\\_blank} is a powerful command-line tool designed explicitly for rapid parachain development within the Polkadot ecosystem. It addresses essential developer needs by providing streamlined commands to set up development environments, scaffold parachain templates, and manage local blockchain networks.", + "outline": [ { "depth": 2, - "title": "Compile Contracts", - "anchor": "compile-contracts" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 3, - "title": "Install the Revive Library", - "anchor": "install-the-revive-library" + "title": "Install Pop CLI", + "anchor": "install-pop-cli" }, { "depth": 3, - "title": "Sample Storage Smart Contract", - "anchor": "sample-storage-smart-contract" + "title": "Set Up Your Development Environment", + "anchor": "set-up-your-development-environment" }, { "depth": 3, - "title": "Compile the Smart Contract", - "anchor": "compile-the-smart-contract" - }, - { - "depth": 2, - "title": "Deploy the Compiled Contract", - "anchor": "deploy-the-compiled-contract" - }, - { - "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" + "title": "Initialize a Project", + "anchor": "initialize-a-project" }, { "depth": 2, @@ -3273,27 +3040,50 @@ } ], "stats": { - "chars": 20464, - "words": 2334, - "headings": 13, - "estimated_token_count_total": 4475 + "chars": 4236, + "words": 610, + "headings": 5, + "estimated_token_count_total": 999 }, - "hash": "sha256:f0cee7ccb3cd294e8f909a220bb63987239ef8155c187a04f8c4864ffdcde288", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:6d6c66430a7302f29113924c5208e64d7c244497e50c61ab2f45c4b5141620e4", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-libraries-viem", - "title": "viem for Polkadot Hub Smart Contracts", - "slug": "develop-smart-contracts-libraries-viem", + "id": "develop-toolkit-parachains-quickstart", + "title": "Quickstart Parachain Development", + "slug": "develop-toolkit-parachains-quickstart", "categories": [ - "Smart Contracts", - "Tooling" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-libraries-viem.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/libraries/viem/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-quickstart.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/quickstart/", + "preview": ":::INSERT_IN_THIS_SECTION:::", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 85, + "words": 7, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:91de375b7f822ed56b5e6b4d609d0d36e806d3f77041b4e180b6679b10a3e1c8", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains-remote-proxies", + "title": "Remote Proxies", + "slug": "develop-toolkit-parachains-remote-proxies", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-remote-proxies.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/remote-proxies/", + "preview": "!!!warning \"Kusama Implementation Only\" Remote proxies are currently only available on Kusama and its parachains (such as Kusama Asset Hub). This feature is not yet deployed on Polkadot MainNet. The examples and implementations described in this guide are specific to the Kusama ecosystem.", "outline": [ { "depth": 2, @@ -3302,92 +3092,59 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Remote Proxy Architecture", + "anchor": "remote-proxy-architecture" }, { "depth": 2, - "title": "Project Structure", - "anchor": "project-structure" + "title": "Implementation Workflow", + "anchor": "implementation-workflow" }, { "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" + "title": "Practical Implementation", + "anchor": "practical-implementation" }, { - "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" - }, - { - "depth": 2, - "title": "Initialize Project", - "anchor": "initialize-project" - }, - { - "depth": 2, - "title": "Set Up the Chain Configuration", - "anchor": "set-up-the-chain-configuration" - }, - { - "depth": 2, - "title": "Set Up the viem Client", - "anchor": "set-up-the-viem-client" - }, - { - "depth": 2, - "title": "Set Up a Wallet", - "anchor": "set-up-a-wallet" - }, - { - "depth": 2, - "title": "Sample Smart Contract", - "anchor": "sample-smart-contract" - }, - { - "depth": 2, - "title": "Compile the Contract", - "anchor": "compile-the-contract" + "depth": 3, + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 2, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" + "depth": 3, + "title": "Installation and Setup", + "anchor": "installation-and-setup" }, { - "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" + "depth": 3, + "title": "Implementation Example", + "anchor": "implementation-example" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Resources", + "anchor": "resources" } ], "stats": { - "chars": 16645, - "words": 1945, - "headings": 14, - "estimated_token_count_total": 3900 + "chars": 9063, + "words": 1113, + "headings": 8, + "estimated_token_count_total": 1863 }, - "hash": "sha256:a7541553a50a250521c0a280f997d614763c643b1028147f3fb61391950bda15", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:7086406b31e7aa9089b221ffaa548ee5540a3d147ec1e93136f481c883f2e434", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-libraries-wagmi", - "title": "Wagmi for Polkadot Hub Smart Contracts", - "slug": "develop-smart-contracts-libraries-wagmi", + "id": "develop-toolkit-parachains-rpc-calls", + "title": "RPC Calls to Polkadot SDK chains.", + "slug": "develop-toolkit-parachains-rpc-calls", "categories": [ - "Smart Contracts", - "Tooling" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-libraries-wagmi.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/libraries/wagmi/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-rpc-calls.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/rpc-calls/", + "preview": "[Remote Procedure Call](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\\_blank} (RPC) interfaces are the primary way to interact programmatically with Polkadot SDK-based parachains and relay chains. RPC calls allow you to query chain state, submit transactions, and monitor network health from external applications or scripts.", "outline": [ { "depth": 2, @@ -3396,72 +3153,85 @@ }, { "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" + "title": "How Do RPC Calls Work?", + "anchor": "how-do-rpc-calls-work" }, { "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" + "title": "Making RPC Calls with Curl", + "anchor": "making-rpc-calls-with-curl" }, { "depth": 2, - "title": "Configure Wagmi for Polkadot Hub", - "anchor": "configure-wagmi-for-polkadot-hub" + "title": "Essential RPC Methods", + "anchor": "essential-rpc-methods" }, { - "depth": 2, - "title": "Set Up the Wagmi Provider", - "anchor": "set-up-the-wagmi-provider" + "depth": 3, + "title": "system_health", + "anchor": "system_health" }, { - "depth": 2, - "title": "Connect a Wallet", - "anchor": "connect-a-wallet" + "depth": 3, + "title": "chain_getBlock", + "anchor": "chain_getblock" }, { - "depth": 2, - "title": "Fetch Blockchain Data", - "anchor": "fetch-blockchain-data" + "depth": 3, + "title": "state_getStorage", + "anchor": "state_getstorage" }, { - "depth": 2, - "title": "Interact with Deployed Contract", - "anchor": "interact-with-deployed-contract" + "depth": 3, + "title": "author_submitExtrinsic", + "anchor": "author_submitextrinsic" + }, + { + "depth": 3, + "title": "state_getMetadata", + "anchor": "state_getmetadata" }, { "depth": 2, - "title": "Integrate Components", - "anchor": "integrate-components" + "title": "Check Available RPC Calls", + "anchor": "check-available-rpc-calls" + }, + { + "depth": 3, + "title": "Using curl", + "anchor": "using-curl" + }, + { + "depth": 3, + "title": "Using Polkadot.js Apps", + "anchor": "using-polkadotjs-apps" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Resources", + "anchor": "resources" } ], "stats": { - "chars": 13604, - "words": 1515, - "headings": 10, - "estimated_token_count_total": 3250 + "chars": 6496, + "words": 909, + "headings": 13, + "estimated_token_count_total": 1870 }, - "hash": "sha256:bc771f912627fa09cad64adab1bc81c052f650d6c5a3b4f0c91883a98f6628da", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:3b766e00e55a224201bc6744386a6dabc7da54ed9199b16abab3b94cff449eca", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-libraries-web3-js", - "title": "Web3.js", - "slug": "develop-smart-contracts-libraries-web3-js", + "id": "develop-toolkit-parachains-spawn-chains-zombienet-write-tests", + "title": "Write Tests", + "slug": "develop-toolkit-parachains-spawn-chains-zombienet-write-tests", "categories": [ - "Smart Contracts", + "Parachains", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-libraries-web3-js.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/libraries/web3-js/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. !!! warning Web3.js has been [sunset](https://blog.chainsafe.io/web3-js-sunset/){target=\\_blank}. You can find guides on using [Ethers.js](/develop/smart-contracts/libraries/ethers-js){target=\\_blank} and [viem](/develop/smart-contracts/libraries/viem){target=\\_blank} in the [Libraries](/develop/smart-contracts/libraries/){target=\\_", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet-write-tests.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/", + "preview": "Testing is a critical step in blockchain development, ensuring reliability, performance, and security. Zombienet simplifies this process with its intuitive Domain Specific Language (DSL), enabling developers to write natural-language test scripts tailored to their network needs.", "outline": [ { "depth": 2, @@ -3470,391 +3240,438 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Project Structure", - "anchor": "project-structure" - }, - { - "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" + "title": "Testing DSL", + "anchor": "testing-dsl" }, { "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" + "title": "The Test File", + "anchor": "the-test-file" }, { - "depth": 2, - "title": "Set Up the Web3 Provider", - "anchor": "set-up-the-web3-provider" + "depth": 3, + "title": "Name", + "anchor": "name" }, { - "depth": 2, - "title": "Compile Contracts", - "anchor": "compile-contracts" + "depth": 3, + "title": "Assertions", + "anchor": "assertions" }, { - "depth": 2, - "title": "Contract Deployment", - "anchor": "contract-deployment" + "depth": 3, + "title": "Commands", + "anchor": "commands" }, { "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" + "title": "Running a Test", + "anchor": "running-a-test" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Example Test Files", + "anchor": "example-test-files" } ], "stats": { - "chars": 13347, - "words": 1586, - "headings": 10, - "estimated_token_count_total": 3033 + "chars": 11297, + "words": 1491, + "headings": 8, + "estimated_token_count_total": 2661 }, - "hash": "sha256:bc87533eaf42a979a0c17f50ecdc668c364889257c7e0d27b81129770660fd53", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:04e85c4cddb58252f8253d78a3924bb56952dac2a3e9a057704a91a0d1f21d75", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-libraries-web3-py", - "title": "Web3.py", - "slug": "develop-smart-contracts-libraries-web3-py", + "id": "develop-toolkit-parachains-spawn-chains-zombienet", + "title": "Zombienet", + "slug": "develop-toolkit-parachains-spawn-chains-zombienet", "categories": [ - "Smart Contracts", - "Tooling" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-libraries-web3-py.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/libraries/web3-py/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/zombienet/", + "preview": "Zombienet is a testing framework that lets you quickly spin up ephemeral blockchain networks for development and testing. With support for multiple deployment targets, such as Kubernetes, Podman, and native environments, Zombienet makes it easy to validate your blockchain implementation in a controlled environment.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" - }, - { - "depth": 2, - "title": "Set Up the Web3 Provider", - "anchor": "set-up-the-web3-provider" - }, - { - "depth": 2, - "title": "Contract Deployment", - "anchor": "contract-deployment" + "title": "What Can I Do with Zombienet?", + "anchor": "what-can-i-do-with-zombienet" }, { "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 11652, - "words": 1335, - "headings": 6, - "estimated_token_count_total": 2512 + "chars": 1237, + "words": 164, + "headings": 3, + "estimated_token_count_total": 193 }, - "hash": "sha256:5d13a0873a78a9802b06686d7caafbf4d23b6ba1edf7d3518943301f2b0110c4", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:1355969b6b0e723b42815b960c15eb128e4d936d0d707cd66e43820cff765ee3", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-local-development-node", - "title": "Local Development Node", - "slug": "develop-smart-contracts-local-development-node", + "id": "develop-toolkit-parachains-spawn-chains", + "title": "Spawn Networks for Testing", + "slug": "develop-toolkit-parachains-spawn-chains", "categories": [ - "Smart Contracts" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-local-development-node.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/local-development-node/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/", + "preview": "Testing blockchain networks in a controlled environment is essential for development and validation. The Polkadot ecosystem provides specialized tools that enable you to spawn test networks, helping you verify functionality and catch issues before deploying to production.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Why Spawn a Network?", + "anchor": "why-spawn-a-network" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Install the Revive Dev Node and ETH-RPC Adapter", - "anchor": "install-the-revive-dev-node-and-eth-rpc-adapter" + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1180, + "words": 155, + "headings": 3, + "estimated_token_count_total": 171 + }, + "hash": "sha256:f11bfd20cb9a0932ce263b2dd763729320261bb25e1fa0039a45ccc609541391", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains", + "title": "Parachains", + "slug": "develop-toolkit-parachains", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/", + "preview": "Within the Polkadot ecosystem, you'll find a robust set of development tools that empower developers to build, test, and deploy blockchain applications efficiently. Whether you're designing a custom parachain, testing new features, or validating network configurations, these tools streamline the development process and ensure your blockchain setup is secure and optimized.", + "outline": [ + { + "depth": 2, + "title": "Quick Links", + "anchor": "quick-links" }, { "depth": 2, - "title": "Run the Local Node", - "anchor": "run-the-local-node" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 9064, - "words": 1433, - "headings": 4, - "estimated_token_count_total": 2432 + "chars": 986, + "words": 136, + "headings": 2, + "estimated_token_count_total": 106 }, - "hash": "sha256:809d0ff921587f29045df1d31a5a9fe32ee13fa7b9698aa27ff9f60b2aa7a4d8", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:88dda8aeab06294ccb773d8732d4791b052351ed0b1307d62019a637c9be341a", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-overview", - "title": "Smart Contracts Overview", - "slug": "develop-smart-contracts-overview", + "id": "develop-toolkit", + "title": "Toolkit", + "slug": "develop-toolkit", "categories": [ - "Basics", - "Smart Contracts" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-overview.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/overview/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/", + "preview": "Explore Polkadot's core development toolkit, designed to support a variety of developers and use cases within the ecosystem. Whether you're building blockchain infrastructure, developing cross-chain applications, or integrating with external services, this section offers essential tools and resources to help you succeed.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 902, + "words": 113, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:20c667a337791538e3997f1f449bf69b248ccc4cc806e22615075f24fd3f0202", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop", + "title": "Develop", + "slug": "develop", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop.md", + "html_url": "https://docs.polkadot.com/develop/", + "preview": "This guide is a starting point for developers who wish to build in the Polkadot ecosystem. To get the most from this section:", + "outline": [ { "depth": 2, - "title": "Native Smart Contracts", - "anchor": "native-smart-contracts" - }, - { - "depth": 3, "title": "Introduction", - "anchor": "introduction-2" - }, - { - "depth": 3, - "title": "Smart Contract Development", - "anchor": "smart-contract-development" + "anchor": "introduction" }, { - "depth": 3, - "title": "Technical Architecture", - "anchor": "technical-architecture" + "depth": 2, + "title": "Development Pathways", + "anchor": "development-pathways" }, { "depth": 3, - "title": "Development Tools and Resources", - "anchor": "development-tools-and-resources" + "title": "Parachain Developers", + "anchor": "parachain-developers" }, { "depth": 3, - "title": "Cross-Chain Capabilities", - "anchor": "cross-chain-capabilities" + "title": "Smart Contract Developers", + "anchor": "smart-contract-developers" }, { "depth": 3, - "title": "Use Cases", - "anchor": "use-cases" - }, - { - "depth": 2, - "title": "Other Smart Contract Environments", - "anchor": "other-smart-contract-environments" + "title": "Application Developers", + "anchor": "application-developers" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 6294, - "words": 802, - "headings": 10, - "estimated_token_count_total": 1118 + "chars": 6923, + "words": 882, + "headings": 6, + "estimated_token_count_total": 1843 }, - "hash": "sha256:0468268436ffdb759cad8390a838d5fba2391118baa8fd8cd494b36397b10329", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:1784f7b9e0552ab893c9d7d252299d53e36b6f57ef57c49cd5e36805399675ab", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-precompiles-interact-with-precompiles", - "title": "Interact with Precompiles", - "slug": "develop-smart-contracts-precompiles-interact-with-precompiles", + "id": "get-support-ai-ready-docs", + "title": "AI Ready Docs", + "slug": "get-support-ai-ready-docs", "categories": [ - "Smart Contracts" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-precompiles-interact-with-precompiles.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/precompiles/interact-with-precompiles/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-ai-ready-docs.md", + "html_url": "https://docs.polkadot.com/get-support/ai-ready-docs/", + "preview": "Polkadot provides files to make documentation content available in a structure optimized for use with large language models (LLMs) and AI tools. These resources help build AI assistants, power code search, or enable custom tooling trained on Polkadot’s documentation.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "How to Use These Files", + "anchor": "how-to-use-these-files" }, { "depth": 2, - "title": "Basic Precompile Interaction Pattern", - "anchor": "basic-precompile-interaction-pattern" - }, + "title": "Download LLM Files", + "anchor": "download-llm-files" + } + ], + "stats": { + "chars": 7998, + "words": 825, + "headings": 2, + "estimated_token_count_total": 2232 + }, + "hash": "sha256:5a8da69a5cea8bd598ee4d102b9abed5d1a29153802a567e22bb4ee720410b32", + "token_estimator": "heuristic-v1" + }, + { + "id": "get-support-explore-resources", + "title": "Subscribe to Updates", + "slug": "get-support-explore-resources", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md", + "html_url": "https://docs.polkadot.com/get-support/explore-resources/", + "preview": "Looking for answers beyond the documentation? These platforms are full of useful content and experienced developers sharing insights.", + "outline": [ { "depth": 2, - "title": "ECRecover (0x01)", - "anchor": "ecrecover-0x01" + "title": "🧠 Stack Exchange", + "anchor": "stack-exchange" }, { "depth": 2, - "title": "SHA-256 (0x02)", - "anchor": "sha-256-0x02" + "title": "🧵 Reddit: r/Polkadot", + "anchor": "reddit-rpolkadot" }, { "depth": 2, - "title": "RIPEMD-160 (0x03)", - "anchor": "ripemd-160-0x03" + "title": "💬 Discord (Community Threads Only)", + "anchor": "discord-community-threads-only" }, { "depth": 2, - "title": "Identity (Data Copy) (0x04)", - "anchor": "identity-data-copy-0x04" + "title": "🎥 YouTube: @PolkadotNetwork", + "anchor": "youtube-polkadotnetwork" }, { "depth": 2, - "title": "Modular Exponentiation (0x05)", - "anchor": "modular-exponentiation-0x05" + "title": "Community-Led Platforms and Ecosystem Updates", + "anchor": "community-led-platforms-and-ecosystem-updates" }, { - "depth": 2, - "title": "BN128 Addition (0x06)", - "anchor": "bn128-addition-0x06" + "depth": 3, + "title": "🔷 X (Twitter): Official Accounts", + "anchor": "x-twitter-official-accounts" }, { - "depth": 2, - "title": "BN128 Scalar Multiplication (0x07)", - "anchor": "bn128-scalar-multiplication-0x07" + "depth": 3, + "title": "🔁 X (Twitter): Community Accounts", + "anchor": "x-twitter-community-accounts" }, { - "depth": 2, - "title": "BN128 Pairing Check (0x08)", - "anchor": "bn128-pairing-check-0x08" + "depth": 3, + "title": "🗣️ Polkadot Forum", + "anchor": "polkadot-forum" }, { - "depth": 2, - "title": "Blake2F (0x09)", - "anchor": "blake2f-0x09" + "depth": 3, + "title": "🧑‍⚖️ Polkassembly: OpenGov", + "anchor": "polkassembly-opengov" }, { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "depth": 3, + "title": "📸 Instagram", + "anchor": "instagram" } ], "stats": { - "chars": 18054, - "words": 2190, - "headings": 12, - "estimated_token_count_total": 3847 + "chars": 2456, + "words": 295, + "headings": 10, + "estimated_token_count_total": 579 }, - "hash": "sha256:4b705b8dbe9b0ad8d19a897d91f3c64dbc4541297dadacbea2a31b4778e50a46", - "last_modified": "2025-10-28T14:42:13+00:00", + "hash": "sha256:4c33d0ec5026128b3bfdb1dfc1f4b29487404eaa8043071d536e8638356c6e1f", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts", - "title": "Smart Contracts", - "slug": "develop-smart-contracts", + "id": "get-support-get-in-touch", + "title": "Get in Touch", + "slug": "get-support-get-in-touch", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Polkadot allows scalable execution of smart contracts, offering cross-chain compatibility and lower fees than legacy L1 platforms. Polkadot provides developers with flexibility in building smart contracts, supporting both Solidity contracts executed by the [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\\_blank} (a Polkadot", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-get-in-touch.md", + "html_url": "https://docs.polkadot.com/get-support/get-in-touch/", + "preview": "Use one of the channels below to get live technical support or ask questions.", "outline": [ { "depth": 2, - "title": "Smart Contract Development Process", - "anchor": "smart-contract-development-process" + "title": "Need Help Fast?", + "anchor": "need-help-fast" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "📱 Telegram: Polkadot Developer Support", + "anchor": "telegram-polkadot-developer-support" + }, + { + "depth": 2, + "title": "🔌 Discord: Polkadot Official Server", + "anchor": "discord-polkadot-official-server" + }, + { + "depth": 2, + "title": "🧬 Matrix: Polkadot Developer Support", + "anchor": "matrix-polkadot-developer-support" } ], "stats": { - "chars": 1867, - "words": 247, - "headings": 2, - "estimated_token_count_total": 189 + "chars": 1949, + "words": 258, + "headings": 4, + "estimated_token_count_total": 557 }, - "hash": "sha256:605d2cbb7eabb2ea0fd928bc3ecdf9ee8b095e3dd9643f2b0918fef7b5a3f4a8", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:993e93b05c8fbdfc2f7510c61ac86bc4c2ff0f03e573695b2f260933c8b62f78", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-api-libraries", - "title": "API Libraries", - "slug": "develop-toolkit-api-libraries", + "id": "get-support", + "title": "Support", + "slug": "get-support", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/", - "preview": "Explore the powerful API libraries designed for interacting with the Polkadot network. These libraries offer developers versatile tools to build, query, and manage blockchain interactions. Whether you’re working with JavaScript, TypeScript, Python, or RESTful services, they provide the flexibility to efficiently interact with and retrieve data from Polkadot-based chains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support.md", + "html_url": "https://docs.polkadot.com/get-support/", + "preview": "Use one of the channels below to get live technical support or ask questions.", "outline": [ { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Need More than Just Documentation?", + "anchor": "need-more-than-just-documentation" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "What You Can Do Here", + "anchor": "what-you-can-do-here" + }, + { + "depth": 2, + "title": "Help Us Improve", + "anchor": "help-us-improve" } ], "stats": { - "chars": 7299, - "words": 1047, - "headings": 6, - "estimated_token_count_total": 1638 + "chars": 1658, + "words": 244, + "headings": 3, + "estimated_token_count_total": 280 }, - "hash": "sha256:807cee6869059dd933905d1cf6c76e3b86e02baee3de3113f7e5b4c8697fbd22", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:5bdc575ac798a971867a15651c2b4d5139bf0b1fe6854d1865deff280ae6d7f6", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-api-libraries-dedot", - "title": "Dedot", - "slug": "develop-toolkit-api-libraries-dedot", + "id": "index", + "title": "Polkadot Developer Docs", + "slug": "index", "categories": [ - "Tooling", - "Dapps" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries-dedot.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/dedot/", - "preview": "[Dedot](https://github.com/dedotdev/dedot){target=\\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\\_blank}.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/index.md", + "html_url": "https://docs.polkadot.com/index/", + "preview": "Explore everything you need to start building on top of Polkadot, a protocol that provides parachains with shared security and interoperability using XCM.", + "outline": [], + "stats": { + "chars": 0, + "words": 0, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-node-bootnode", + "title": "Set Up a Bootnode", + "slug": "nodes-and-validators-run-a-node-bootnode", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-bootnode.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/bootnode/", + "preview": "Bootnodes are essential for helping blockchain nodes discover peers and join the network. When a node starts, it needs to find other nodes, and bootnodes provide an initial point of contact. Once connected, a node can expand its peer connections and play its role in the network, like participating as a validator.", "outline": [ { "depth": 2, @@ -3862,68 +3679,65 @@ "anchor": "introduction" }, { - "depth": 3, - "title": "Key Features", - "anchor": "key-features" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Accessing the Bootnode", + "anchor": "accessing-the-bootnode" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Node Key", + "anchor": "node-key" }, { - "depth": 3, - "title": "Initialize a Client Instance", - "anchor": "initialize-a-client-instance" + "depth": 2, + "title": "Running the Bootnode", + "anchor": "running-the-bootnode" }, { - "depth": 3, - "title": "Enable Type and API Suggestions", - "anchor": "enable-type-and-api-suggestions" + "depth": 2, + "title": "Testing Bootnode Connection", + "anchor": "testing-bootnode-connection" }, { "depth": 3, - "title": "Read On-Chain Data", - "anchor": "read-on-chain-data" + "title": "P2P", + "anchor": "p2p" }, { "depth": 3, - "title": "Sign and Send Transactions", - "anchor": "sign-and-send-transactions" + "title": "P2P/WS", + "anchor": "p2pws" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "P2P/WSS", + "anchor": "p2pwss" } ], "stats": { - "chars": 8855, - "words": 1100, + "chars": 4538, + "words": 647, "headings": 9, - "estimated_token_count_total": 2300 + "estimated_token_count_total": 1044 }, - "hash": "sha256:ba24e31e2ad94fbf1d73f1878da92dd2e1476db00170780bbdf0e65ab18bc961", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:d84a5af1a0237a911d25a68c077f508ebbce608f673ef4f9055e8e434daa96b9", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-api-libraries-papi", - "title": "Polkadot-API", - "slug": "develop-toolkit-api-libraries-papi", + "id": "nodes-and-validators-run-a-node-full-node", + "title": "Set Up a Node", + "slug": "nodes-and-validators-run-a-node-full-node", "categories": [ - "Tooling", - "Dapps" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries-papi.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/papi/", - "preview": "[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-full-node.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/full-node/", + "preview": "Running a node on Polkadot provides direct interaction with the network, enhanced privacy, and full control over RPC requests, transactions, and data queries. As the backbone of the network, nodes ensure decentralized data propagation, transaction validation, and seamless communication across the ecosystem.", "outline": [ { "depth": 2, @@ -3932,125 +3746,120 @@ }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Set Up a Node", + "anchor": "set-up-a-node" }, { "depth": 3, - "title": "API Instantiation", - "anchor": "api-instantiation" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "title": "Install and Build the Polkadot Binary", + "anchor": "install-and-build-the-polkadot-binary" }, { "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" + "title": "Use Docker", + "anchor": "use-docker" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Configure and Run Your Node", + "anchor": "configure-and-run-your-node" + }, + { + "depth": 3, + "title": "RPC Configurations", + "anchor": "rpc-configurations" + }, + { + "depth": 2, + "title": "Sync Your Node", + "anchor": "sync-your-node" + }, + { + "depth": 3, + "title": "Connect to Your Node", + "anchor": "connect-to-your-node" } ], "stats": { - "chars": 8957, - "words": 1156, - "headings": 6, - "estimated_token_count_total": 1987 + "chars": 15947, + "words": 2482, + "headings": 9, + "estimated_token_count_total": 4197 }, - "hash": "sha256:2ca93b09d3bb9159bbf53816886a9b242bb3c13b996c51fd52962e049e2d5477", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:b83e3f77bd30ac8c8fb00a193bbec33cd641d94f1a37ac611dea32326c3d77b0", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-api-libraries-polkadart", - "title": "Polkadart", - "slug": "develop-toolkit-api-libraries-polkadart", + "id": "nodes-and-validators-run-a-node-secure-wss", + "title": "Set Up Secure WebSocket", + "slug": "nodes-and-validators-run-a-node-secure-wss", "categories": [ - "Tooling", - "Dapps" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries-polkadart.md", - "html_url": "https://docs.polkadot.com/reference/tools/polkadart/", - "preview": "Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-secure-wss.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/secure-wss/", + "preview": "Ensuring secure WebSocket communication is crucial for maintaining the integrity and security of a Polkadot or Kusama node when interacting with remote clients. This guide walks you through setting up a secure WebSocket (WSS) connection for your node by leveraging SSL encryption with popular web server proxies like nginx or Apache.", "outline": [ { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Type Generation", - "anchor": "type-generation" - }, - { - "depth": 3, - "title": "Run Generator", - "anchor": "run-generator" - }, - { - "depth": 3, - "title": "Use Generated Types", - "anchor": "use-generated-types" + "title": "Secure a WebSocket Port", + "anchor": "secure-a-websocket-port" }, { "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" + "title": "Obtain an SSL Certificate", + "anchor": "obtain-an-ssl-certificate" }, { - "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "depth": 2, + "title": "Install a Proxy Server", + "anchor": "install-a-proxy-server" }, { "depth": 3, - "title": "Subscribe to New Blocks", - "anchor": "subscribe-to-new-blocks" + "title": "Use nginx", + "anchor": "use-nginx" }, { "depth": 3, - "title": "Send a Transaction", - "anchor": "send-a-transaction" + "title": "Use Apache2", + "anchor": "use-apache2" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Connect to the Node", + "anchor": "connect-to-the-node" } ], "stats": { - "chars": 5178, - "words": 624, - "headings": 10, - "estimated_token_count_total": 1084 + "chars": 5568, + "words": 774, + "headings": 7, + "estimated_token_count_total": 1280 }, - "hash": "sha256:7f533abe61586af8438e350c41b741d74a8edb839f9dc4139bc4619ba3748258", - "last_modified": "2025-10-28T14:15:59+00:00", + "hash": "sha256:992082e4ad87348b283f6c37ea886ae0e7bf016852b6470000876f3d169c65a4", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-api-libraries-polkadot-js-api", - "title": "Polkadot.js API", - "slug": "develop-toolkit-api-libraries-polkadot-js-api", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", + "title": "Validator Key Management", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", "categories": [ - "Tooling", - "Dapps" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries-polkadot-js-api.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/polkadot-js-api/", - "preview": "!!! warning \"Maintenance Mode Only\" The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank} (modern, type-safe API) as actively maintained alternatives.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/", + "preview": "After setting up your node environment as shown in the [Setup](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/){target=\\_blank} section, you'll need to configure multiple keys for your validator to operate properly. This includes setting up session keys, which are essential for participating in the consensus process, and configuring a node key that maintains a stable network identity. This guide walks you through the key management process, showing you how to g", "outline": [ { "depth": 2, @@ -4058,68 +3867,60 @@ "anchor": "introduction" }, { - "depth": 3, - "title": "Dynamic API Generation", - "anchor": "dynamic-api-generation" + "depth": 2, + "title": "Set Session Keys", + "anchor": "set-session-keys" }, { "depth": 3, - "title": "Available API Categories", - "anchor": "available-api-categories" - }, - { - "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Generate Session Keys", + "anchor": "generate-session-keys" }, { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "depth": 3, + "title": "Submit Transaction to Set Keys", + "anchor": "submit-transaction-to-set-keys" }, { "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" + "title": "Verify Session Key Setup", + "anchor": "verify-session-key-setup" }, { - "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "depth": 2, + "title": "Set the Node Key", + "anchor": "set-the-node-key" }, { "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" + "title": "Generate the Node Key", + "anchor": "generate-the-node-key" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Set Node Key", + "anchor": "set-node-key" } ], "stats": { - "chars": 5042, - "words": 684, - "headings": 9, - "estimated_token_count_total": 1166 + "chars": 8227, + "words": 1183, + "headings": 8, + "estimated_token_count_total": 1840 }, - "hash": "sha256:ed3986f30880fefca5975fcdc847c68b4aca65862c63e3002b25391b0521781d", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:0fb5a83835aab263c0b9aa886028c8aa8a2d6d0897d7b9fff4b5258835d30dfe", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-api-libraries-py-substrate-interface", - "title": "Python Substrate Interface", - "slug": "develop-toolkit-api-libraries-py-substrate-interface", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", + "title": "Set Up a Validator", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", "categories": [ - "Tooling", - "Dapps" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries-py-substrate-interface.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/py-substrate-interface/", - "preview": "The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/", + "preview": "Setting up a Polkadot validator node is essential for securing the network and earning staking rewards. This guide walks you through the technical steps to set up a validator, from installing the necessary software to managing keys and synchronizing your node with the chain.", "outline": [ { "depth": 2, @@ -4128,111 +3929,79 @@ }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Establishing Connection", - "anchor": "establishing-connection" + "title": "Initial Setup", + "anchor": "initial-setup" }, { "depth": 3, - "title": "Reading Chain State", - "anchor": "reading-chain-state" + "title": "Install Network Time Protocol Client", + "anchor": "install-network-time-protocol-client" }, { "depth": 3, - "title": "Submitting Transactions", - "anchor": "submitting-transactions" + "title": "Verify Landlock is Activated", + "anchor": "verify-landlock-is-activated" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4302, - "words": 541, - "headings": 7, - "estimated_token_count_total": 942 - }, - "hash": "sha256:8987fc35cd28602054ee018031f773e2e3837425107c51d0e2ac68a94b86e9c0", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-api-libraries-sidecar", - "title": "Sidecar Rest API", - "slug": "develop-toolkit-api-libraries-sidecar", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries-sidecar.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/sidecar/", - "preview": "The [Sidecar Rest API](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more.", - "outline": [ + "title": "Install the Polkadot Binaries", + "anchor": "install-the-polkadot-binaries" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Install from Official Releases", + "anchor": "install-from-official-releases" }, { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "depth": 3, + "title": "Install with Package Managers", + "anchor": "install-with-package-managers" }, { - "depth": 2, - "title": "Installation", - "anchor": "installation" + "depth": 3, + "title": "Install with Ansible", + "anchor": "install-with-ansible" }, { - "depth": 2, - "title": "Usage", - "anchor": "usage" + "depth": 3, + "title": "Install with Docker", + "anchor": "install-with-docker" }, { "depth": 3, - "title": "Endpoints", - "anchor": "endpoints" + "title": "Build from Sources", + "anchor": "build-from-sources" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Verify Installation", + "anchor": "verify-installation" } ], "stats": { - "chars": 7309, - "words": 1033, - "headings": 6, - "estimated_token_count_total": 1945 + "chars": 11921, + "words": 1678, + "headings": 12, + "estimated_token_count_total": 2592 }, - "hash": "sha256:b8759f61ab57b636228b69d5770c74591998b912cd4596e89eb2ec011da7ef73", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:d2c1c91734bc8185057d8eeec6829ea91e0316f7ba884c5dc3922a5e5778815e", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-api-libraries-subxt", - "title": "Subxt Rust API", - "slug": "develop-toolkit-api-libraries-subxt", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", + "title": "Start Validating", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", "categories": [ - "Tooling", - "Dapps" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries-subxt.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/subxt/", - "preview": "Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/start-validating/", + "preview": "After configuring your node keys as shown in the [Key Management](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/){target=\\_blank} section and ensuring your system is set up, you're ready to begin the validator setup process. This guide will walk you through choosing a network, synchronizing your node with the blockchain, bonding your DOT tokens, and starting your validator.", "outline": [ { "depth": 2, @@ -4241,2073 +4010,118 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Choose a Network", + "anchor": "choose-a-network" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Synchronize Chain Data", + "anchor": "synchronize-chain-data" + }, + { + "depth": 3, + "title": "Database Snapshot Services", + "anchor": "database-snapshot-services" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Bond DOT", + "anchor": "bond-dot" }, { "depth": 3, - "title": "Download Chain Metadata", - "anchor": "download-chain-metadata" + "title": "Bonding DOT on Polkadot.js Apps", + "anchor": "bonding-dot-on-polkadotjs-apps" }, { - "depth": 3, - "title": "Generate Type-Safe Interfaces", - "anchor": "generate-type-safe-interfaces" + "depth": 2, + "title": "Validate", + "anchor": "validate" }, { "depth": 3, - "title": "Initialize the Subxt Client", - "anchor": "initialize-the-subxt-client" + "title": "Verify Sync via Telemetry", + "anchor": "verify-sync-via-telemetry" }, { "depth": 3, - "title": "Read Chain Data", - "anchor": "read-chain-data" + "title": "Activate using Polkadot.js Apps", + "anchor": "activate-using-polkadotjs-apps" }, { "depth": 3, - "title": "Submit Transactions", - "anchor": "submit-transactions" + "title": "Monitor Validation Status and Slots", + "anchor": "monitor-validation-status-and-slots" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Run a Validator Using Systemd", + "anchor": "run-a-validator-using-systemd" + }, + { + "depth": 3, + "title": "Create the Systemd Service File", + "anchor": "create-the-systemd-service-file" + }, + { + "depth": 3, + "title": "Run the Service", + "anchor": "run-the-service" } ], "stats": { - "chars": 9174, - "words": 1175, - "headings": 10, - "estimated_token_count_total": 2187 + "chars": 15821, + "words": 2446, + "headings": 13, + "estimated_token_count_total": 3861 }, - "hash": "sha256:56269d9ea47f5b4e92cd7d5a1e65ab06d181a9c380f90bb3ef285529b12299f7", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:c74cfa542fe7a5235b81120f0004576aea83e0d35458201689b68d87f2969749", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-integrations-indexers", - "title": "Indexers", - "slug": "develop-toolkit-integrations-indexers", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", + "title": "Stop Validating", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", "categories": [ - "Tooling", - "Dapps" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-indexers.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/indexers/", - "preview": "Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/", + "preview": "If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability.", "outline": [ { "depth": 2, - "title": "The Challenge of Blockchain Data Access", - "anchor": "the-challenge-of-blockchain-data-access" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "What is a Blockchain Indexer?", - "anchor": "what-is-a-blockchain-indexer" + "title": "Pause Versus Stop", + "anchor": "pause-versus-stop" }, { "depth": 2, - "title": "Indexer Implementations", - "anchor": "indexer-implementations" + "title": "Chill Validator", + "anchor": "chill-validator" + }, + { + "depth": 2, + "title": "Purge Validator Session Keys", + "anchor": "purge-validator-session-keys" + }, + { + "depth": 2, + "title": "Unbond Your Tokens", + "anchor": "unbond-your-tokens" } ], "stats": { - "chars": 2230, - "words": 302, - "headings": 3, - "estimated_token_count_total": 428 + "chars": 3230, + "words": 500, + "headings": 5, + "estimated_token_count_total": 629 }, - "hash": "sha256:cfcc76bb24779c9b613f2c046b6f99a0f2529c25fd82287d804f6b945b936227", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-integrations-oracles", - "title": "Oracles", - "slug": "develop-toolkit-integrations-oracles", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-oracles.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/oracles/", - "preview": "Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the \"blockchain oracle problem.\" Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain.", - "outline": [ - { - "depth": 2, - "title": "What is a Blockchain Oracle?", - "anchor": "what-is-a-blockchain-oracle" - }, - { - "depth": 2, - "title": "Oracle Implementations", - "anchor": "oracle-implementations" - } - ], - "stats": { - "chars": 1343, - "words": 181, - "headings": 2, - "estimated_token_count_total": 187 - }, - "hash": "sha256:6d8e01281a5895fd2bc4438b24c170c72a496de0b838626a53e87685aea4aa25", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-integrations-storage", - "title": "Storage", - "slug": "develop-toolkit-integrations-storage", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-storage.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/storage/", - "preview": "Polkadot offers developers a range of decentralized storage solutions to manage dApp data, host front ends, and store large files in a censorship-resistant and resilient manner. These integrations are essential for building fully decentralized applications, ensuring that all components of your dApp, from the front end to the data, are not reliant on centralized servers.", - "outline": [ - { - "depth": 2, - "title": "Key Storage Solutions", - "anchor": "key-storage-solutions" - }, - { - "depth": 2, - "title": "Crust Network", - "anchor": "crust-network" - }, - { - "depth": 3, - "title": "Key Features of Crust", - "anchor": "key-features-of-crust" - }, - { - "depth": 3, - "title": "Use Cases", - "anchor": "use-cases" - }, - { - "depth": 2, - "title": "IPFS", - "anchor": "ipfs" - }, - { - "depth": 3, - "title": "Using IPFS with Polkadot", - "anchor": "using-ipfs-with-polkadot" - }, - { - "depth": 2, - "title": "Other Solutions", - "anchor": "other-solutions" - } - ], - "stats": { - "chars": 4369, - "words": 642, - "headings": 7, - "estimated_token_count_total": 847 - }, - "hash": "sha256:a206dd86fc3d80aed22384000839ca0c9c75c69ad461abd9810d96c03cf6a3bd", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-integrations-transaction-construction", - "title": "Transaction Construction", - "slug": "develop-toolkit-integrations-transaction-construction", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-transaction-construction.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/transaction-construction/", - "preview": "This page will discuss the transaction format in Polkadot and how to create, sign, and broadcast transactions, as well as highlight some of the commands and tools available for integrators.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Transaction Format", - "anchor": "transaction-format" - }, - { - "depth": 3, - "title": "Mode and Metadata Hash", - "anchor": "mode-and-metadata-hash" - }, - { - "depth": 3, - "title": "Serialized Transactions and Metadata", - "anchor": "serialized-transactions-and-metadata" - }, - { - "depth": 3, - "title": "Transaction Flow", - "anchor": "transaction-flow" - }, - { - "depth": 2, - "title": "Polkadot-JS Tools", - "anchor": "polkadot-js-tools" - }, - { - "depth": 3, - "title": "Creating a Transaction, Signing, and Submitting", - "anchor": "creating-a-transaction-signing-and-submitting" - }, - { - "depth": 2, - "title": "Txwrapper", - "anchor": "txwrapper" - }, - { - "depth": 3, - "title": "Creating a Transaction, Signing, and Submitting", - "anchor": "creating-a-transaction-signing-and-submitting-2" - }, - { - "depth": 2, - "title": "Additional Libraries for Submitting a Transaction", - "anchor": "additional-libraries-for-submitting-a-transaction" - } - ], - "stats": { - "chars": 27671, - "words": 2949, - "headings": 10, - "estimated_token_count_total": 6280 - }, - "hash": "sha256:9b03477d13a285fced6bf845c3827084f790a626989dc2c09ef9ff53643045f4", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-integrations", - "title": "Integrations", - "slug": "develop-toolkit-integrations", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/", - "preview": "Polkadot offers a wide range of integrations that allow developers to enhance their decentralized applications (dApps) and leverage the full capabilities of the ecosystem. Whether you’re looking to extend your application’s functionality, integrate with other chains, or access specialized services, these integrations provide the tools and resources you need to build efficiently and effectively. Explore the available options to find the solutions that best suit your development needs.", - "outline": [ - { - "depth": 2, - "title": "Key Integration Solutions", - "anchor": "key-integration-solutions" - }, - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 988, - "words": 135, - "headings": 2, - "estimated_token_count_total": 92 - }, - "hash": "sha256:62c5ad101282227f79eac0e30a3ba9ce3ae1bf9e358bd58c0b17ef45db29c2ff", - "last_modified": "2025-10-28T14:15:59+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-interoperability", - "title": "Interoperability", - "slug": "develop-toolkit-interoperability", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-interoperability.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/interoperability/", - "preview": "Polkadot's XCM tooling ecosystem redefines the boundaries of cross-chain communication and asset movement. With unparalleled flexibility and scalability, these advanced tools empower developers to build decentralized applications that connect parachains, relay chains, and external networks. By bridging siloed blockchains, Polkadot paves the way for a unified, interoperable ecosystem that accelerates innovation and collaboration.", - "outline": [ - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 1010, - "words": 128, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:966ec1bcc014a454f6b837b503025d9fb89c30f6a65d0aaec82ea5ff976e53a9", - "last_modified": "2025-10-28T14:15:59+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-e2e-testing", - "title": "E2E Testing on Polkadot SDK Chains", - "slug": "develop-toolkit-parachains-e2e-testing", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-e2e-testing.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/e2e-testing/", - "preview": ":::INSERT_IN_THIS_SECTION:::", - "outline": [ - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 64, - "words": 6, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:47328231d6ff4dc52cd93aaf1baf5d0bc2d9fc372f3d79339d87aafa0dabd1b8", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-fork-chains-chopsticks", - "title": "Chopsticks", - "slug": "develop-toolkit-parachains-fork-chains-chopsticks", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-fork-chains-chopsticks.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/fork-chains/chopsticks/", - "preview": "Chopsticks is a powerful tool that lets you create local copies of running Polkadot SDK-based networks. By forking live chains locally, you can safely test features, analyze network behavior, and simulate complex scenarios without affecting production networks.", - "outline": [ - { - "depth": 2, - "title": "What Can I Do with Chopsticks?", - "anchor": "what-can-i-do-with-chopsticks" - }, - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - }, - { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1495, - "words": 201, - "headings": 3, - "estimated_token_count_total": 291 - }, - "hash": "sha256:2c77cfb38bb2e466a8f56dabbb706fcd2e90cf1634fc9beb7f0ee95a75735653", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-fork-chains-chopsticks-get-started", - "title": "Get Started", - "slug": "develop-toolkit-parachains-fork-chains-chopsticks-get-started", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-fork-chains-chopsticks-get-started.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/fork-chains/chopsticks/get-started/", - "preview": "[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Install Chopsticks", - "anchor": "install-chopsticks" - }, - { - "depth": 3, - "title": "Global Installation", - "anchor": "global-installation" - }, - { - "depth": 3, - "title": "Local Installation", - "anchor": "local-installation" - }, - { - "depth": 2, - "title": "Configure Chopsticks", - "anchor": "configure-chopsticks" - }, - { - "depth": 3, - "title": "Configuration File", - "anchor": "configuration-file" - }, - { - "depth": 3, - "title": "CLI Flags", - "anchor": "cli-flags" - }, - { - "depth": 2, - "title": "WebSocket Commands", - "anchor": "websocket-commands" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 10894, - "words": 1330, - "headings": 10, - "estimated_token_count_total": 2614 - }, - "hash": "sha256:4325cdd697814b8043db808da3dee86d3d9c6fc7dd523aae7fe8914d59d1b39c", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-light-clients", - "title": "develop-toolkit-parachains-light-clients", - "slug": "develop-toolkit-parachains-light-clients", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-fork-chains.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/fork-chains/", - "preview": "Explore tools for forking live blockchain networks. These tools enable you to replicate real-world conditions in a local environment for accurate testing and debugging. They also allow you to analyze network behavior, test new features, and simulate complex scenarios in a controlled environment without affecting production systems.", - "outline": [ - { - "depth": 2, - "title": "Why Fork a Live Chain?", - "anchor": "why-fork-a-live-chain" - }, - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - }, - { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1269, - "words": 173, - "headings": 3, - "estimated_token_count_total": 183 - }, - "hash": "sha256:1284c42be692167e01bcc44e2e134ec20615402675fac26df246c00aa1588d80", - "last_modified": "2025-10-28T14:15:59+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-polkadot-omni-node", - "title": "Polkadot Omni Node", - "slug": "develop-toolkit-parachains-polkadot-omni-node", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-polkadot-omni-node.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/polkadot-omni-node/", - "preview": "The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\\_blank} file, allowing it to adapt dynamically to different parachains.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Install Polkadot Omni Node", - "anchor": "install-polkadot-omni-node" - }, - { - "depth": 2, - "title": "Obtain Chain Specifications", - "anchor": "obtain-chain-specifications" - }, - { - "depth": 2, - "title": "Run a Parachain Full Node", - "anchor": "run-a-parachain-full-node" - }, - { - "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" - }, - { - "depth": 2, - "title": "Parachain Compatibility", - "anchor": "parachain-compatibility" - }, - { - "depth": 3, - "title": "Required Runtime APIs", - "anchor": "required-runtime-apis" - }, - { - "depth": 3, - "title": "Required Pallets", - "anchor": "required-pallets" - } - ], - "stats": { - "chars": 8916, - "words": 1165, - "headings": 9, - "estimated_token_count_total": 2018 - }, - "hash": "sha256:49866761ef638dd0683bb5558f5319b9568ff136295b3359580a6f478172c73f", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-quickstart-pop-cli", - "title": "Quickstart Parachain Development with Pop CLI", - "slug": "develop-toolkit-parachains-quickstart-pop-cli", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-quickstart-pop-cli.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/quickstart/pop-cli/", - "preview": "[Pop CLI](https://onpop.io/cli/){target=\\_blank} is a powerful command-line tool designed explicitly for rapid parachain development within the Polkadot ecosystem. It addresses essential developer needs by providing streamlined commands to set up development environments, scaffold parachain templates, and manage local blockchain networks.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 3, - "title": "Install Pop CLI", - "anchor": "install-pop-cli" - }, - { - "depth": 3, - "title": "Set Up Your Development Environment", - "anchor": "set-up-your-development-environment" - }, - { - "depth": 3, - "title": "Initialize a Project", - "anchor": "initialize-a-project" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4236, - "words": 610, - "headings": 5, - "estimated_token_count_total": 999 - }, - "hash": "sha256:6d6c66430a7302f29113924c5208e64d7c244497e50c61ab2f45c4b5141620e4", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-remote-proxies", - "title": "Remote Proxies", - "slug": "develop-toolkit-parachains-remote-proxies", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-remote-proxies.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/remote-proxies/", - "preview": "!!!warning \"Kusama Implementation Only\" Remote proxies are currently only available on Kusama and its parachains (such as Kusama Asset Hub). This feature is not yet deployed on Polkadot MainNet. The examples and implementations described in this guide are specific to the Kusama ecosystem.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Remote Proxy Architecture", - "anchor": "remote-proxy-architecture" - }, - { - "depth": 2, - "title": "Implementation Workflow", - "anchor": "implementation-workflow" - }, - { - "depth": 2, - "title": "Practical Implementation", - "anchor": "practical-implementation" - }, - { - "depth": 3, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 3, - "title": "Installation and Setup", - "anchor": "installation-and-setup" - }, - { - "depth": 3, - "title": "Implementation Example", - "anchor": "implementation-example" - }, - { - "depth": 2, - "title": "Resources", - "anchor": "resources" - } - ], - "stats": { - "chars": 9063, - "words": 1113, - "headings": 8, - "estimated_token_count_total": 1863 - }, - "hash": "sha256:7086406b31e7aa9089b221ffaa548ee5540a3d147ec1e93136f481c883f2e434", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-rpc-calls", - "title": "RPC Calls to Polkadot SDK chains.", - "slug": "develop-toolkit-parachains-rpc-calls", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-rpc-calls.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/rpc-calls/", - "preview": "[Remote Procedure Call](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\\_blank} (RPC) interfaces are the primary way to interact programmatically with Polkadot SDK-based parachains and relay chains. RPC calls allow you to query chain state, submit transactions, and monitor network health from external applications or scripts.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "How Do RPC Calls Work?", - "anchor": "how-do-rpc-calls-work" - }, - { - "depth": 2, - "title": "Making RPC Calls with Curl", - "anchor": "making-rpc-calls-with-curl" - }, - { - "depth": 2, - "title": "Essential RPC Methods", - "anchor": "essential-rpc-methods" - }, - { - "depth": 3, - "title": "system_health", - "anchor": "system_health" - }, - { - "depth": 3, - "title": "chain_getBlock", - "anchor": "chain_getblock" - }, - { - "depth": 3, - "title": "state_getStorage", - "anchor": "state_getstorage" - }, - { - "depth": 3, - "title": "author_submitExtrinsic", - "anchor": "author_submitextrinsic" - }, - { - "depth": 3, - "title": "state_getMetadata", - "anchor": "state_getmetadata" - }, - { - "depth": 2, - "title": "Check Available RPC Calls", - "anchor": "check-available-rpc-calls" - }, - { - "depth": 3, - "title": "Using curl", - "anchor": "using-curl" - }, - { - "depth": 3, - "title": "Using Polkadot.js Apps", - "anchor": "using-polkadotjs-apps" - }, - { - "depth": 2, - "title": "Resources", - "anchor": "resources" - } - ], - "stats": { - "chars": 6496, - "words": 909, - "headings": 13, - "estimated_token_count_total": 1870 - }, - "hash": "sha256:3b766e00e55a224201bc6744386a6dabc7da54ed9199b16abab3b94cff449eca", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-spawn-chains-zombienet-get-started", - "title": "Get Started", - "slug": "develop-toolkit-parachains-spawn-chains-zombienet-get-started", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet-get-started.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/zombienet/get-started/", - "preview": "Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Install Zombienet", - "anchor": "install-zombienet" - }, - { - "depth": 2, - "title": "Providers", - "anchor": "providers" - }, - { - "depth": 3, - "title": "Kubernetes", - "anchor": "kubernetes" - }, - { - "depth": 3, - "title": "Podman", - "anchor": "podman" - }, - { - "depth": 3, - "title": "Local Provider", - "anchor": "local-provider" - }, - { - "depth": 2, - "title": "Configure Zombienet", - "anchor": "configure-zombienet" - }, - { - "depth": 3, - "title": "Configuration Files", - "anchor": "configuration-files" - }, - { - "depth": 3, - "title": "CLI Usage", - "anchor": "cli-usage" - }, - { - "depth": 3, - "title": "Settings", - "anchor": "settings" - }, - { - "depth": 3, - "title": "Relay Chain Configuration", - "anchor": "relay-chain-configuration" - }, - { - "depth": 3, - "title": "Parachain Configuration", - "anchor": "parachain-configuration" - }, - { - "depth": 3, - "title": "XCM Configuration", - "anchor": "xcm-configuration" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 41636, - "words": 4599, - "headings": 14, - "estimated_token_count_total": 9871 - }, - "hash": "sha256:0d7e04fd952cc9d5bd8cdbfd87cc4004c5f95e896a16bc7f89dfc4caeac8f371", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-spawn-chains-zombienet-write-tests", - "title": "Write Tests", - "slug": "develop-toolkit-parachains-spawn-chains-zombienet-write-tests", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet-write-tests.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/", - "preview": "Testing is a critical step in blockchain development, ensuring reliability, performance, and security. Zombienet simplifies this process with its intuitive Domain Specific Language (DSL), enabling developers to write natural-language test scripts tailored to their network needs.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Testing DSL", - "anchor": "testing-dsl" - }, - { - "depth": 2, - "title": "The Test File", - "anchor": "the-test-file" - }, - { - "depth": 3, - "title": "Name", - "anchor": "name" - }, - { - "depth": 3, - "title": "Assertions", - "anchor": "assertions" - }, - { - "depth": 3, - "title": "Commands", - "anchor": "commands" - }, - { - "depth": 2, - "title": "Running a Test", - "anchor": "running-a-test" - }, - { - "depth": 2, - "title": "Example Test Files", - "anchor": "example-test-files" - } - ], - "stats": { - "chars": 11297, - "words": 1491, - "headings": 8, - "estimated_token_count_total": 2661 - }, - "hash": "sha256:04e85c4cddb58252f8253d78a3924bb56952dac2a3e9a057704a91a0d1f21d75", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-spawn-chains-zombienet", - "title": "Zombienet", - "slug": "develop-toolkit-parachains-spawn-chains-zombienet", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/zombienet/", - "preview": "Zombienet is a testing framework that lets you quickly spin up ephemeral blockchain networks for development and testing. With support for multiple deployment targets, such as Kubernetes, Podman, and native environments, Zombienet makes it easy to validate your blockchain implementation in a controlled environment.", - "outline": [ - { - "depth": 2, - "title": "What Can I Do with Zombienet?", - "anchor": "what-can-i-do-with-zombienet" - }, - { - "depth": 2, - "title": "Download LLM Files", - "anchor": "download-llm-files" - } - ], - "stats": { - "chars": 7659, - "words": 777, - "headings": 2, - "estimated_token_count_total": 2073 - }, - "hash": "sha256:9836ab7da420e9ca8196da77dc3ff8198cb3b622548842d0505c0aa043a5f02e", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support-explore-resources", - "title": "Subscribe to Updates", - "slug": "get-support-explore-resources", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md", - "html_url": "https://docs.polkadot.com/get-support/explore-resources/", - "preview": "Looking for answers beyond the documentation? These platforms are full of useful content and experienced developers sharing insights.", - "outline": [ - { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1237, - "words": 164, - "headings": 3, - "estimated_token_count_total": 193 - }, - "hash": "sha256:4c33d0ec5026128b3bfdb1dfc1f4b29487404eaa8043071d536e8638356c6e1f", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-spawn-chains", - "title": "Spawn Networks for Testing", - "slug": "develop-toolkit-parachains-spawn-chains", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/", - "preview": "Testing blockchain networks in a controlled environment is essential for development and validation. The Polkadot ecosystem provides specialized tools that enable you to spawn test networks, helping you verify functionality and catch issues before deploying to production.", - "outline": [ - { - "depth": 2, - "title": "Why Spawn a Network?", - "anchor": "why-spawn-a-network" - }, - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - }, - { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1180, - "words": 155, - "headings": 3, - "estimated_token_count_total": 171 - }, - "hash": "sha256:993e93b05c8fbdfc2f7510c61ac86bc4c2ff0f03e573695b2f260933c8b62f78", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains", - "title": "Parachains", - "slug": "develop-toolkit-parachains", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/", - "preview": "Within the Polkadot ecosystem, you'll find a robust set of development tools that empower developers to build, test, and deploy blockchain applications efficiently. Whether you're designing a custom parachain, testing new features, or validating network configurations, these tools streamline the development process and ensure your blockchain setup is secure and optimized.", - "outline": [ - { - "depth": 2, - "title": "Quick Links", - "anchor": "quick-links" - }, - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 986, - "words": 136, - "headings": 2, - "estimated_token_count_total": 106 - }, - "hash": "sha256:d84a5af1a0237a911d25a68c077f508ebbce608f673ef4f9055e8e434daa96b9", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit", - "title": "Toolkit", - "slug": "develop-toolkit", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/", - "preview": "Explore Polkadot's core development toolkit, designed to support a variety of developers and use cases within the ecosystem. Whether you're building blockchain infrastructure, developing cross-chain applications, or integrating with external services, this section offers essential tools and resources to help you succeed.", - "outline": [ - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 902, - "words": 113, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:abd9f939f68b068a18567b875c9f7e11d102c54fc02ca0e6ee8041c539061ed0", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop", - "title": "Develop", - "slug": "develop", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop.md", - "html_url": "https://docs.polkadot.com/develop/", - "preview": "This guide is a starting point for developers who wish to build in the Polkadot ecosystem. To get the most from this section:", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Development Pathways", - "anchor": "development-pathways" - }, - { - "depth": 3, - "title": "Parachain Developers", - "anchor": "parachain-developers" - }, - { - "depth": 3, - "title": "Smart Contract Developers", - "anchor": "smart-contract-developers" - }, - { - "depth": 3, - "title": "Application Developers", - "anchor": "application-developers" - }, - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 6923, - "words": 882, - "headings": 6, - "estimated_token_count_total": 1843 - }, - "hash": "sha256:0b43b452e9d709cb324bf51fd88c2fed8e6249534a7c2b852e1bd36bcb9b981a", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support-ai-ready-docs", - "title": "AI Ready Docs", - "slug": "get-support-ai-ready-docs", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-ai-ready-docs.md", - "html_url": "https://docs.polkadot.com/get-support/ai-ready-docs/", - "preview": "Polkadot provides files to make documentation content available in a structure optimized for use with large language models (LLMs) and AI tools. These resources help build AI assistants, power code search, or enable custom tooling trained on Polkadot’s documentation.", - "outline": [ - { - "depth": 2, - "title": "How to Use These Files", - "anchor": "how-to-use-these-files" - }, - { - "depth": 2, - "title": "Download LLM Files", - "anchor": "download-llm-files" - } - ], - "stats": { - "chars": 7998, - "words": 825, - "headings": 2, - "estimated_token_count_total": 2232 - }, - "hash": "sha256:1090b02689df5f4c59bb83f9c81436718d06e46f3b615bc655fef3c7b6c9fb02", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support-explore-resources", - "title": "Subscribe to Updates", - "slug": "get-support-explore-resources", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md", - "html_url": "https://docs.polkadot.com/get-support/explore-resources/", - "preview": "Looking for answers beyond the documentation? These platforms are full of useful content and experienced developers sharing insights.", - "outline": [ - { - "depth": 2, - "title": "🧠 Stack Exchange", - "anchor": "stack-exchange" - }, - { - "depth": 2, - "title": "🧵 Reddit: r/Polkadot", - "anchor": "reddit-rpolkadot" - }, - { - "depth": 2, - "title": "💬 Discord (Community Threads Only)", - "anchor": "discord-community-threads-only" - }, - { - "depth": 2, - "title": "🎥 YouTube: @PolkadotNetwork", - "anchor": "youtube-polkadotnetwork" - }, - { - "depth": 2, - "title": "Verify Installation", - "anchor": "verify-installation" - } - ], - "stats": { - "chars": 11883, - "words": 1662, - "headings": 12, - "estimated_token_count_total": 2559 - }, - "hash": "sha256:0857a9e83aefc6d3f04e8cb320ab82d35211bbd73d2eb2614cf7b97f8e6d36b9", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "infrastructure-running-a-validator-onboarding-and-offboarding-start-validating", - "title": "Start Validating", - "slug": "infrastructure-running-a-validator-onboarding-and-offboarding-start-validating", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/infrastructure-running-a-validator-onboarding-and-offboarding-start-validating.md", - "html_url": "https://docs.polkadot.com/infrastructure/running-a-validator/onboarding-and-offboarding/start-validating/", - "preview": "After configuring your node keys as shown in the [Key Management](/infrastructure/running-a-validator/onboarding-and-offboarding/key-management){target=\\_blank} section and ensuring your system is set up, you're ready to begin the validator setup process. This guide will walk you through choosing a network, synchronizing your node with the blockchain, bonding your DOT tokens, and starting your validator.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Choose a Network", - "anchor": "choose-a-network" - }, - { - "depth": 2, - "title": "Synchronize Chain Data", - "anchor": "synchronize-chain-data" - }, - { - "depth": 3, - "title": "🔷 X (Twitter): Official Accounts", - "anchor": "x-twitter-official-accounts" - }, - { - "depth": 3, - "title": "🔁 X (Twitter): Community Accounts", - "anchor": "x-twitter-community-accounts" - }, - { - "depth": 3, - "title": "🗣️ Polkadot Forum", - "anchor": "polkadot-forum" - }, - { - "depth": 3, - "title": "🧑‍⚖️ Polkassembly: OpenGov", - "anchor": "polkassembly-opengov" - }, - { - "depth": 3, - "title": "📸 Instagram", - "anchor": "instagram" - } - ], - "stats": { - "chars": 2456, - "words": 295, - "headings": 10, - "estimated_token_count_total": 579 - }, - "hash": "sha256:e2567b7d5377c87984622cf93afe4bd8cedf46b80597736cf53f26b5f31c5065", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support-get-in-touch", - "title": "Get in Touch", - "slug": "get-support-get-in-touch", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-get-in-touch.md", - "html_url": "https://docs.polkadot.com/get-support/get-in-touch/", - "preview": "Use one of the channels below to get live technical support or ask questions.", - "outline": [ - { - "depth": 2, - "title": "Need Help Fast?", - "anchor": "need-help-fast" - }, - { - "depth": 2, - "title": "📱 Telegram: Polkadot Developer Support", - "anchor": "telegram-polkadot-developer-support" - }, - { - "depth": 2, - "title": "🔌 Discord: Polkadot Official Server", - "anchor": "discord-polkadot-official-server" - }, - { - "depth": 2, - "title": "🧬 Matrix: Polkadot Developer Support", - "anchor": "matrix-polkadot-developer-support" - } - ], - "stats": { - "chars": 1949, - "words": 258, - "headings": 4, - "estimated_token_count_total": 557 - }, - "hash": "sha256:9ab570299106336e5d75923b876247e8eb4a71851a77e84d68e0335e9da5e0a8", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support", - "title": "Support", - "slug": "get-support", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support.md", - "html_url": "https://docs.polkadot.com/get-support/", - "preview": "Use one of the channels below to get live technical support or ask questions.", - "outline": [ - { - "depth": 2, - "title": "Need More than Just Documentation?", - "anchor": "need-more-than-just-documentation" - }, - { - "depth": 2, - "title": "What You Can Do Here", - "anchor": "what-you-can-do-here" - }, - { - "depth": 2, - "title": "Help Us Improve", - "anchor": "help-us-improve" - } - ], - "stats": { - "chars": 1658, - "words": 244, - "headings": 3, - "estimated_token_count_total": 280 - }, - "hash": "sha256:a7b5239c3be0341ced8f28146e240ff6061fded2e71094bd586beeb024684a50", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "index", - "title": "Polkadot Developer Docs", - "slug": "index", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/index.md", - "html_url": "https://docs.polkadot.com/index/", - "preview": "Explore everything you need to start building on top of Polkadot, a protocol that provides parachains with shared security and interoperability using XCM.", - "outline": [], - "stats": { - "chars": 0, - "words": 0, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:97655248c65e816fdf3d85dab4ace7ca0c145c50f671c25c24627cfd7660c7a6", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "infrastructure-running-a-validator-operational-tasks-upgrade-your-node", - "title": "Upgrade a Validator Node", - "slug": "infrastructure-running-a-validator-operational-tasks-upgrade-your-node", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/infrastructure-running-a-validator-operational-tasks-upgrade-your-node.md", - "html_url": "https://docs.polkadot.com/infrastructure/running-a-validator/operational-tasks/upgrade-your-node/", - "preview": "Upgrading a Polkadot validator node is essential for staying current with network updates and maintaining optimal performance. This guide covers routine and extended maintenance scenarios, including software upgrades and major server changes. Following these steps, you can manage session keys and transition smoothly between servers without risking downtime, slashing, or network disruptions. The process requires strategic planning, especially if you need to perform long-lead maintenance, ensuring", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Session Keys", - "anchor": "session-keys" - }, - { - "depth": 2, - "title": "Keystore", - "anchor": "keystore" - }, - { - "depth": 2, - "title": "Upgrade Using Backup Validator", - "anchor": "upgrade-using-backup-validator" - }, - { - "depth": 3, - "title": "Session `N`", - "anchor": "session-n" - }, - { - "depth": 3, - "title": "Session `N+3`", - "anchor": "session-n3" - } - ], - "stats": { - "chars": 5624, - "words": 842, - "headings": 7, - "estimated_token_count_total": 1167 - }, - "hash": "sha256:b2e8abce15fc9df106a5e972f28c64f606f9dd50ba3a256093eb53bdd5126224", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "infrastructure-running-a-validator-requirements", - "title": "Validator Requirements", - "slug": "infrastructure-running-a-validator-requirements", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/infrastructure-running-a-validator-requirements.md", - "html_url": "https://docs.polkadot.com/infrastructure/running-a-validator/requirements/", - "preview": "Running a validator in the Polkadot ecosystem is essential for maintaining network security and decentralization. Validators are responsible for validating transactions and adding new blocks to the chain, ensuring the system operates smoothly. In return for their services, validators earn rewards. However, the role comes with inherent risks, such as slashing penalties for misbehavior or technical failures. If you’re new to validation, starting on Kusama provides a lower-stakes environment to gai", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Minimum Hardware Requirements", - "anchor": "minimum-hardware-requirements" - }, - { - "depth": 2, - "title": "VPS Provider List", - "anchor": "vps-provider-list" - }, - { - "depth": 2, - "title": "Minimum Bond Requirement", - "anchor": "minimum-bond-requirement" - } - ], - "stats": { - "chars": 6838, - "words": 940, - "headings": 5, - "estimated_token_count_total": 1477 - }, - "hash": "sha256:76500d1d63f4205a84f0bc5b7f9aec945781127d41c32927280ac74bc14f0296", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "infrastructure-staking-mechanics-offenses-and-slashes", - "title": "Offenses and Slashes", - "slug": "infrastructure-staking-mechanics-offenses-and-slashes", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/infrastructure-staking-mechanics-offenses-and-slashes.md", - "html_url": "https://docs.polkadot.com/infrastructure/staking-mechanics/offenses-and-slashes/", - "preview": "In Polkadot's Nominated Proof of Stake (NPoS) system, validator misconduct is deterred through a combination of slashing, disabling, and reputation penalties. Validators and nominators who stake tokens face consequences for validator misbehavior, which range from token slashes to restrictions on network participation.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Offenses", - "anchor": "offenses" - }, - { - "depth": 3, - "title": "Invalid Votes", - "anchor": "invalid-votes" - }, - { - "depth": 3, - "title": "Equivocations", - "anchor": "equivocations" - }, - { - "depth": 2, - "title": "Penalties", - "anchor": "penalties" - }, - { - "depth": 3, - "title": "Slashing", - "anchor": "slashing" - }, - { - "depth": 3, - "title": "Disabling", - "anchor": "disabling" - }, - { - "depth": 3, - "title": "Reputation Changes", - "anchor": "reputation-changes" - }, - { - "depth": 3, - "title": "Penalties by Offense", - "anchor": "penalties-by-offense" - } - ], - "stats": { - "chars": 15427, - "words": 2103, - "headings": 9, - "estimated_token_count_total": 3409 - }, - "hash": "sha256:abe6bedab04f463ec07f554977b8d6355a5d2fad9bcda01cbe58568152295daa", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "infrastructure-staking-mechanics-rewards-payout", - "title": "Rewards Payout", - "slug": "infrastructure-staking-mechanics-rewards-payout", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/infrastructure-staking-mechanics-rewards-payout.md", - "html_url": "https://docs.polkadot.com/infrastructure/staking-mechanics/rewards-payout/", - "preview": "Understanding how rewards are distributed to validators and nominators is essential for network participants. In Polkadot and Kusama, validators earn rewards based on their era points, which are accrued through actions like block production and parachain validation.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Era Points", - "anchor": "era-points" - }, - { - "depth": 2, - "title": "Reward Variance", - "anchor": "reward-variance" - }, - { - "depth": 2, - "title": "Payout Scheme", - "anchor": "payout-scheme" - }, - { - "depth": 2, - "title": "Running Multiple Validators", - "anchor": "running-multiple-validators" - }, - { - "depth": 2, - "title": "Nominators and Validator Payments", - "anchor": "nominators-and-validator-payments" - } - ], - "stats": { - "chars": 11070, - "words": 1764, - "headings": 6, - "estimated_token_count_total": 2617 - }, - "hash": "sha256:7d43408276d811c96b7b081a7b9f4d884893282a230b564c9eb3be2fc7857565", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-node-bootnode", - "title": "Set Up a Bootnode", - "slug": "nodes-and-validators-run-a-node-bootnode", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-bootnode.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/bootnode/", - "preview": "Bootnodes are essential for helping blockchain nodes discover peers and join the network. When a node starts, it needs to find other nodes, and bootnodes provide an initial point of contact. Once connected, a node can expand its peer connections and play its role in the network, like participating as a validator.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Accessing the Bootnode", - "anchor": "accessing-the-bootnode" - }, - { - "depth": 2, - "title": "Node Key", - "anchor": "node-key" - }, - { - "depth": 2, - "title": "Running the Bootnode", - "anchor": "running-the-bootnode" - }, - { - "depth": 2, - "title": "Testing Bootnode Connection", - "anchor": "testing-bootnode-connection" - }, - { - "depth": 3, - "title": "P2P", - "anchor": "p2p" - }, - { - "depth": 3, - "title": "P2P/WS", - "anchor": "p2pws" - }, - { - "depth": 3, - "title": "P2P/WSS", - "anchor": "p2pwss" - } - ], - "stats": { - "chars": 4538, - "words": 647, - "headings": 9, - "estimated_token_count_total": 1044 - }, - "hash": "sha256:d84a5af1a0237a911d25a68c077f508ebbce608f673ef4f9055e8e434daa96b9", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-node-full-node", - "title": "Set Up a Node", - "slug": "nodes-and-validators-run-a-node-full-node", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-full-node.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/full-node/", - "preview": "Running a node on Polkadot provides direct interaction with the network, enhanced privacy, and full control over RPC requests, transactions, and data queries. As the backbone of the network, nodes ensure decentralized data propagation, transaction validation, and seamless communication across the ecosystem.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Set Up a Node", - "anchor": "set-up-a-node" - }, - { - "depth": 3, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 3, - "title": "Install and Build the Polkadot Binary", - "anchor": "install-and-build-the-polkadot-binary" - }, - { - "depth": 3, - "title": "Use Docker", - "anchor": "use-docker" - }, - { - "depth": 2, - "title": "Configure and Run Your Node", - "anchor": "configure-and-run-your-node" - }, - { - "depth": 3, - "title": "RPC Configurations", - "anchor": "rpc-configurations" - }, - { - "depth": 2, - "title": "Sync Your Node", - "anchor": "sync-your-node" - }, - { - "depth": 3, - "title": "Connect to Your Node", - "anchor": "connect-to-your-node" - } - ], - "stats": { - "chars": 15947, - "words": 2482, - "headings": 9, - "estimated_token_count_total": 4197 - }, - "hash": "sha256:b83e3f77bd30ac8c8fb00a193bbec33cd641d94f1a37ac611dea32326c3d77b0", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-node-secure-wss", - "title": "Set Up Secure WebSocket", - "slug": "nodes-and-validators-run-a-node-secure-wss", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-secure-wss.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/secure-wss/", - "preview": "Ensuring secure WebSocket communication is crucial for maintaining the integrity and security of a Polkadot or Kusama node when interacting with remote clients. This guide walks you through setting up a secure WebSocket (WSS) connection for your node by leveraging SSL encryption with popular web server proxies like nginx or Apache.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Secure a WebSocket Port", - "anchor": "secure-a-websocket-port" - }, - { - "depth": 3, - "title": "Obtain an SSL Certificate", - "anchor": "obtain-an-ssl-certificate" - }, - { - "depth": 2, - "title": "Install a Proxy Server", - "anchor": "install-a-proxy-server" - }, - { - "depth": 3, - "title": "Use nginx", - "anchor": "use-nginx" - }, - { - "depth": 3, - "title": "Use Apache2", - "anchor": "use-apache2" - }, - { - "depth": 2, - "title": "Connect to the Node", - "anchor": "connect-to-the-node" - } - ], - "stats": { - "chars": 5568, - "words": 774, - "headings": 7, - "estimated_token_count_total": 1280 - }, - "hash": "sha256:992082e4ad87348b283f6c37ea886ae0e7bf016852b6470000876f3d169c65a4", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", - "title": "Validator Key Management", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/", - "preview": "After setting up your node environment as shown in the [Setup](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/){target=\\_blank} section, you'll need to configure multiple keys for your validator to operate properly. This includes setting up session keys, which are essential for participating in the consensus process, and configuring a node key that maintains a stable network identity. This guide walks you through the key management process, showing you how to g", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Set Session Keys", - "anchor": "set-session-keys" - }, - { - "depth": 3, - "title": "Generate Session Keys", - "anchor": "generate-session-keys" - }, - { - "depth": 3, - "title": "Submit Transaction to Set Keys", - "anchor": "submit-transaction-to-set-keys" - }, - { - "depth": 3, - "title": "Verify Session Key Setup", - "anchor": "verify-session-key-setup" - }, - { - "depth": 2, - "title": "Set the Node Key", - "anchor": "set-the-node-key" - }, - { - "depth": 3, - "title": "Generate the Node Key", - "anchor": "generate-the-node-key" - }, - { - "depth": 3, - "title": "Set Node Key", - "anchor": "set-node-key" - } - ], - "stats": { - "chars": 8227, - "words": 1183, - "headings": 8, - "estimated_token_count_total": 1840 - }, - "hash": "sha256:0fb5a83835aab263c0b9aa886028c8aa8a2d6d0897d7b9fff4b5258835d30dfe", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", - "title": "Set Up a Validator", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/", - "preview": "Setting up a Polkadot validator node is essential for securing the network and earning staking rewards. This guide walks you through the technical steps to set up a validator, from installing the necessary software to managing keys and synchronizing your node with the chain.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Initial Setup", - "anchor": "initial-setup" - }, - { - "depth": 3, - "title": "Install Network Time Protocol Client", - "anchor": "install-network-time-protocol-client" - }, - { - "depth": 3, - "title": "Verify Landlock is Activated", - "anchor": "verify-landlock-is-activated" - }, - { - "depth": 2, - "title": "Install the Polkadot Binaries", - "anchor": "install-the-polkadot-binaries" - }, - { - "depth": 3, - "title": "Install from Official Releases", - "anchor": "install-from-official-releases" - }, - { - "depth": 3, - "title": "Install with Package Managers", - "anchor": "install-with-package-managers" - }, - { - "depth": 3, - "title": "Install with Ansible", - "anchor": "install-with-ansible" - }, - { - "depth": 3, - "title": "Install with Docker", - "anchor": "install-with-docker" - }, - { - "depth": 3, - "title": "Build from Sources", - "anchor": "build-from-sources" - }, - { - "depth": 2, - "title": "Verify Installation", - "anchor": "verify-installation" - } - ], - "stats": { - "chars": 11921, - "words": 1678, - "headings": 12, - "estimated_token_count_total": 2592 - }, - "hash": "sha256:d2c1c91734bc8185057d8eeec6829ea91e0316f7ba884c5dc3922a5e5778815e", - "last_modified": "2025-10-28T14:42:13+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", - "title": "Start Validating", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/start-validating/", - "preview": "After configuring your node keys as shown in the [Key Management](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/){target=\\_blank} section and ensuring your system is set up, you're ready to begin the validator setup process. This guide will walk you through choosing a network, synchronizing your node with the blockchain, bonding your DOT tokens, and starting your validator.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Choose a Network", - "anchor": "choose-a-network" - }, - { - "depth": 2, - "title": "Synchronize Chain Data", - "anchor": "synchronize-chain-data" - }, - { - "depth": 3, - "title": "Database Snapshot Services", - "anchor": "database-snapshot-services" - }, - { - "depth": 2, - "title": "Bond DOT", - "anchor": "bond-dot" - }, - { - "depth": 3, - "title": "Bonding DOT on Polkadot.js Apps", - "anchor": "bonding-dot-on-polkadotjs-apps" - }, - { - "depth": 2, - "title": "Validate", - "anchor": "validate" - }, - { - "depth": 3, - "title": "Verify Sync via Telemetry", - "anchor": "verify-sync-via-telemetry" - }, - { - "depth": 3, - "title": "Activate using Polkadot.js Apps", - "anchor": "activate-using-polkadotjs-apps" - }, - { - "depth": 3, - "title": "Monitor Validation Status and Slots", - "anchor": "monitor-validation-status-and-slots" - }, - { - "depth": 2, - "title": "Run a Validator Using Systemd", - "anchor": "run-a-validator-using-systemd" - }, - { - "depth": 3, - "title": "Create the Systemd Service File", - "anchor": "create-the-systemd-service-file" - }, - { - "depth": 3, - "title": "Run the Service", - "anchor": "run-the-service" - } - ], - "stats": { - "chars": 15821, - "words": 2446, - "headings": 13, - "estimated_token_count_total": 3861 - }, - "hash": "sha256:a4235e8d590033d5d54434143e0a5e23603c53ae70d4f0a9ebfe4ca9442baa8d", - "last_modified": "2025-10-28T14:42:14+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", - "title": "Stop Validating", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/", - "preview": "If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Pause Versus Stop", - "anchor": "pause-versus-stop" - }, - { - "depth": 2, - "title": "Chill Validator", - "anchor": "chill-validator" - }, - { - "depth": 2, - "title": "Purge Validator Session Keys", - "anchor": "purge-validator-session-keys" - }, - { - "depth": 2, - "title": "Unbond Your Tokens", - "anchor": "unbond-your-tokens" - } - ], - "stats": { - "chars": 3230, - "words": 500, - "headings": 5, - "estimated_token_count_total": 629 - }, - "hash": "sha256:0d6db361bfa7a3022849bbe39989bfdac0429537498d7f534adadec131afca98", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:0d6db361bfa7a3022849bbe39989bfdac0429537498d7f534adadec131afca98", "token_estimator": "heuristic-v1" }, { @@ -6419,7 +4233,6 @@ "estimated_token_count_total": 5866 }, "hash": "sha256:81eb0fe77f05155f1ec0511cd066120fc9994961e9d91e21b6666377e65b4586", - "last_modified": "2025-10-28T14:42:14+00:00", "token_estimator": "heuristic-v1" }, { @@ -6471,7 +4284,6 @@ "estimated_token_count_total": 861 }, "hash": "sha256:1af153570ce57bd5b52d08493a300996765686f2a6d04519a2e0aa91191612c1", - "last_modified": "2025-10-28T14:42:14+00:00", "token_estimator": "heuristic-v1" }, { @@ -6528,7 +4340,6 @@ "estimated_token_count_total": 1185 }, "hash": "sha256:888230b128d8c648c4f06a18d3b1d1b06dd1bf22a0de4add1f28210ffccb2549", - "last_modified": "2025-10-28T14:42:14+00:00", "token_estimator": "heuristic-v1" }, { @@ -6575,7 +4386,6 @@ "estimated_token_count_total": 1485 }, "hash": "sha256:46435b97c37ef6798d2c75c69df31c5e5f07e04b218c370ec5af6b1838d43aac", - "last_modified": "2025-10-28T14:42:14+00:00", "token_estimator": "heuristic-v1" }, { @@ -6642,7 +4452,6 @@ "estimated_token_count_total": 3409 }, "hash": "sha256:abe6bedab04f463ec07f554977b8d6355a5d2fad9bcda01cbe58568152295daa", - "last_modified": "2025-10-28T14:42:14+00:00", "token_estimator": "heuristic-v1" }, { @@ -6694,7 +4503,6 @@ "estimated_token_count_total": 2588 }, "hash": "sha256:d5d6d72eb2cf10f624d84c65f2274f7df90acb5d071bf170bc8eae8d98a810a5", - "last_modified": "2025-10-28T14:42:14+00:00", "token_estimator": "heuristic-v1" }, { @@ -6786,7 +4594,6 @@ "estimated_token_count_total": 2724 }, "hash": "sha256:93d123cbaaccc2515b4a70be8e1327b4f75b1051d16c5e3daf5a2035af7b7ca3", - "last_modified": "2025-10-28T14:42:14+00:00", "token_estimator": "heuristic-v1" }, { @@ -6913,7 +4720,6 @@ "estimated_token_count_total": 3811 }, "hash": "sha256:d83e574726c524fa017236eb5e3b8a0676d598be4da1ce4fe25a60141baeee49", - "last_modified": "2025-10-28T14:42:14+00:00", "token_estimator": "heuristic-v1" }, { @@ -6925,7 +4731,7 @@ ], "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md", "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-smart-contract-functionality/", - "preview": "When building your custom blockchain with the Polkadot SDK, you have the flexibility to add smart contract capabilities through specialized pallets. These pallets allow blockchain users to deploy and execute smart contracts, enhancing your chain's functionality and programmability.", + "preview": "When building your custom blockchain with the Polkadot SDK, you can add smart contract capabilities through specialized pallets. These pallets enable users to deploy and execute smart contracts, enhancing your chain's programmability and allowing developers to build decentralized applications on your network.", "outline": [ { "depth": 2, @@ -6934,13 +4740,73 @@ }, { "depth": 2, - "title": "EVM Smart Contracts", - "anchor": "evm-smart-contracts" + "title": "pallet-revive", + "anchor": "pallet-revive" + }, + { + "depth": 3, + "title": "Core Components", + "anchor": "core-components" + }, + { + "depth": 3, + "title": "Supported Languages and Compilers", + "anchor": "supported-languages-and-compilers" + }, + { + "depth": 3, + "title": "How It Works", + "anchor": "how-it-works" + }, + { + "depth": 3, + "title": "Key Benefits", + "anchor": "key-benefits" + }, + { + "depth": 3, + "title": "Implementation Examples", + "anchor": "implementation-examples" + }, + { + "depth": 2, + "title": "Frontier", + "anchor": "frontier" + }, + { + "depth": 3, + "title": "Integration Options", + "anchor": "integration-options" + }, + { + "depth": 3, + "title": "EVM Execution Only", + "anchor": "evm-execution-only" + }, + { + "depth": 3, + "title": "Full Ethereum Compatibility", + "anchor": "full-ethereum-compatibility" + }, + { + "depth": 3, + "title": "Key Benefits", + "anchor": "key-benefits-2" + }, + { + "depth": 3, + "title": "Implementation Examples", + "anchor": "implementation-examples-2" }, { "depth": 2, - "title": "Wasm Smart Contracts", - "anchor": "wasm-smart-contracts" + "title": "pallet-contracts (Legacy)", + "anchor": "pallet-contracts-legacy" + }, + { + "depth": 3, + "title": "Implementation Example", + "anchor": "implementation-example" }, { "depth": 2, @@ -6949,13 +4815,12 @@ } ], "stats": { - "chars": 3865, - "words": 521, - "headings": 4, - "estimated_token_count_total": 901 + "chars": 6655, + "words": 833, + "headings": 16, + "estimated_token_count_total": 1631 }, - "hash": "sha256:f56a32d5323c371f084833b4e647f21e1d76ad242d8c4e4826bcaed467acc7cf", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:6297bb5e0809fdd0585d6170054599f7ab4a3ce7c687ad03ae43092057c493b7", "token_estimator": "heuristic-v1" }, { @@ -7008,86 +4873,18 @@ "estimated_token_count_total": 3091 }, "hash": "sha256:87add0ae178e4970601a27efccadb58eff1375d19819201034ba2829914f1cd5", - "last_modified": "2025-10-28T14:42:14+00:00", "token_estimator": "heuristic-v1" }, { "id": "parachains-customize-runtime-pallet-development-benchmark-pallet", - "title": "Benchmarking FRAME Pallets", + "title": "Benchmark Your Pallet", "slug": "parachains-customize-runtime-pallet-development-benchmark-pallet", "categories": [ "Parachains" ], "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md", "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/benchmark-pallet/", - "preview": "Benchmarking is a critical component of developing efficient and secure blockchain runtimes. In the Polkadot ecosystem, accurately benchmarking your custom pallets ensures that each extrinsic has a precise [weight](/reference/glossary/#weight){target=\\_blank}, representing its computational and storage demands. This process is vital for maintaining the blockchain's performance and preventing potential vulnerabilities, such as Denial of Service (DoS) attacks.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "The Case for Benchmarking", - "anchor": "the-case-for-benchmarking" - }, - { - "depth": 3, - "title": "Benchmarking and Weight", - "anchor": "benchmarking-and-weight" - }, - { - "depth": 2, - "title": "Benchmarking Process", - "anchor": "benchmarking-process" - }, - { - "depth": 3, - "title": "Prepare Your Environment", - "anchor": "prepare-your-environment" - }, - { - "depth": 3, - "title": "Write Benchmark Tests", - "anchor": "write-benchmark-tests" - }, - { - "depth": 3, - "title": "Add Benchmarks to Runtime", - "anchor": "add-benchmarks-to-runtime" - }, - { - "depth": 3, - "title": "Run Benchmarks", - "anchor": "run-benchmarks" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 14715, - "words": 1879, - "headings": 9, - "estimated_token_count_total": 3338 - }, - "hash": "sha256:915bc91edd56cdedd516e871dbe450d70c9f99fb467cc00ff231ea3a74f61d96", - "last_modified": "2025-10-28T14:42:14+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-pallet-development-create-a-pallet", - "title": "Create a Custom Pallet", - "slug": "parachains-customize-runtime-pallet-development-create-a-pallet", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/create-a-pallet/", - "preview": "[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functional", + "preview": "Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.", "outline": [ { "depth": 2, @@ -7101,547 +4898,355 @@ }, { "depth": 2, - "title": "Core Pallet Components", - "anchor": "core-pallet-components" - }, - { - "depth": 2, - "title": "Create the Pallet Project", - "anchor": "create-the-pallet-project" - }, - { - "depth": 2, - "title": "Configure Dependencies", - "anchor": "configure-dependencies" + "title": "Why Benchmark?", + "anchor": "why-benchmark" }, { "depth": 2, - "title": "Initialize the Pallet Structure", - "anchor": "initialize-the-pallet-structure" + "title": "Understanding Weights", + "anchor": "understanding-weights" }, { "depth": 2, - "title": "Configure the Pallet", - "anchor": "configure-the-pallet" + "title": "Step 1: Create the Benchmarking Module", + "anchor": "step-1-create-the-benchmarking-module" }, { "depth": 2, - "title": "Define Events", - "anchor": "define-events" + "title": "Step 2: Define the Weight Trait", + "anchor": "step-2-define-the-weight-trait" }, { "depth": 2, - "title": "Define Errors", - "anchor": "define-errors" + "title": "Step 3: Add WeightInfo to Config", + "anchor": "step-3-add-weightinfo-to-config" }, { "depth": 2, - "title": "Add Storage Items", - "anchor": "add-storage-items" + "title": "Step 4: Update Extrinsic Weight Annotations", + "anchor": "step-4-update-extrinsic-weight-annotations" }, { "depth": 2, - "title": "Configure Genesis State", - "anchor": "configure-genesis-state" + "title": "Step 5: Include the Benchmarking Module", + "anchor": "step-5-include-the-benchmarking-module" }, { "depth": 2, - "title": "Implement Dispatchable Functions", - "anchor": "implement-dispatchable-functions" - }, - { - "depth": 3, - "title": "Dispatchable Function Details", - "anchor": "dispatchable-function-details" + "title": "Step 6: Configure Pallet Dependencies", + "anchor": "step-6-configure-pallet-dependencies" }, { "depth": 2, - "title": "Verify Pallet Compilation", - "anchor": "verify-pallet-compilation" + "title": "Step 7: Update Mock Runtime", + "anchor": "step-7-update-mock-runtime" }, { "depth": 2, - "title": "Add the Pallet to Your Runtime", - "anchor": "add-the-pallet-to-your-runtime" - }, - { - "depth": 3, - "title": "Add Runtime Dependency", - "anchor": "add-runtime-dependency" - }, - { - "depth": 3, - "title": "Implement the Config Trait", - "anchor": "implement-the-config-trait" + "title": "Step 8: Configure Runtime Benchmarking", + "anchor": "step-8-configure-runtime-benchmarking" }, { "depth": 3, - "title": "Add to Runtime Construct", - "anchor": "add-to-runtime-construct" + "title": "Update Runtime Cargo.toml", + "anchor": "update-runtime-cargotoml" }, { "depth": 3, - "title": "Configure Genesis for Your Runtime", - "anchor": "configure-genesis-for-your-runtime" + "title": "Update Runtime Configuration", + "anchor": "update-runtime-configuration" }, { "depth": 3, - "title": "Verify Runtime Compilation", - "anchor": "verify-runtime-compilation" + "title": "Register Benchmarks", + "anchor": "register-benchmarks" }, { "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" - }, - { - "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" + "title": "Step 9: Run Benchmarks", + "anchor": "step-9-run-benchmarks" }, { "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" + "title": "Test Benchmark Compilation", + "anchor": "test-benchmark-compilation" }, { - "depth": 2, - "title": "Interact with Your Pallet", - "anchor": "interact-with-your-pallet" - }, - { - "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 26671, - "words": 3041, - "headings": 26, - "estimated_token_count_total": 6113 - }, - "hash": "sha256:607e283aaa1295de0af191d97de7f6f87afb722c601a447821fde6a09b97f1af", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-pallet-development-mock-runtime", - "title": "Mock Your Runtime", - "slug": "parachains-customize-runtime-pallet-development-mock-runtime", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/", - "preview": "Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Build the Runtime with Benchmarks", + "anchor": "build-the-runtime-with-benchmarks" }, { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "depth": 3, + "title": "Install the Benchmarking Tool", + "anchor": "install-the-benchmarking-tool" }, { - "depth": 2, - "title": "Understand Mock Runtimes", - "anchor": "understand-mock-runtimes" + "depth": 3, + "title": "Download the Weight Template", + "anchor": "download-the-weight-template" }, { - "depth": 2, - "title": "Create the Mock Runtime Module", - "anchor": "create-the-mock-runtime-module" + "depth": 3, + "title": "Hardware Requirements for Benchmarking", + "anchor": "hardware-requirements-for-benchmarking" }, { - "depth": 2, - "title": "Set Up Basic Mock", - "anchor": "set-up-basic-mock" + "depth": 3, + "title": "Execute Benchmarks", + "anchor": "execute-benchmarks" }, { - "depth": 2, - "title": "Implement Essential Configuration", - "anchor": "implement-essential-configuration" + "depth": 3, + "title": "Advanced Options", + "anchor": "advanced-options" }, { "depth": 2, - "title": "Implement Your Pallet's Configuration", - "anchor": "implement-your-pallets-configuration" + "title": "Step 10: Use Generated Weights", + "anchor": "step-10-use-generated-weights" }, { - "depth": 2, - "title": "Configure Genesis Storage", - "anchor": "configure-genesis-storage" + "depth": 3, + "title": "Integrate the Generated Weights", + "anchor": "integrate-the-generated-weights" }, { "depth": 3, - "title": "Basic Test Environment", - "anchor": "basic-test-environment" + "title": "Update Runtime Configuration", + "anchor": "update-runtime-configuration-2" }, { "depth": 3, - "title": "Custom Genesis Configurations", - "anchor": "custom-genesis-configurations" + "title": "Example Generated Weight File", + "anchor": "example-generated-weight-file" }, { "depth": 2, - "title": "Verify Mock Compilation", - "anchor": "verify-mock-compilation" + "title": "Benchmarking Best Practices", + "anchor": "benchmarking-best-practices" }, { - "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" + "depth": 3, + "title": "1. Test Worst-Case Scenarios", + "anchor": "1-test-worst-case-scenarios" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 11766, - "words": 1369, - "headings": 13, - "estimated_token_count_total": 2514 - }, - "hash": "sha256:dd784a5d2daebb9a885fe09f6a967e6c84958d96ddb38d8366eabe9d860fa539", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-pallet-development-pallet-testing", - "title": "Pallet Testing", - "slug": "parachains-customize-runtime-pallet-development-pallet-testing", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/", - "preview": "Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.", - "outline": [ + "depth": 3, + "title": "2. Use Linear Components for Variable Complexity", + "anchor": "2-use-linear-components-for-variable-complexity" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "3. Verify Results", + "anchor": "3-verify-results" + }, + { + "depth": 3, + "title": "4. Minimize Setup Code", + "anchor": "4-minimize-setup-code" }, { "depth": 2, - "title": "Writing Unit Tests", - "anchor": "writing-unit-tests" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { "depth": 3, - "title": "Test Initialization", - "anchor": "test-initialization" + "title": "Build the Production Runtime", + "anchor": "build-the-production-runtime" }, { "depth": 3, - "title": "Function Call Testing", - "anchor": "function-call-testing" + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" }, { "depth": 3, - "title": "Storage Testing", - "anchor": "storage-testing" + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" }, { "depth": 3, - "title": "Event Testing", - "anchor": "event-testing" + "title": "Verify Block Production", + "anchor": "verify-block-production" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Related Resources", + "anchor": "related-resources" } ], "stats": { - "chars": 6892, - "words": 911, - "headings": 7, - "estimated_token_count_total": 1563 + "chars": 31318, + "words": 3912, + "headings": 38, + "estimated_token_count_total": 6933 }, - "hash": "sha256:8568dfa238b9a649a4e6e60510625c2e7879b76a93187b0b8b8dccf6bc467ae6", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:14b1f18a3ed81ff2fa96ae45661122502d3edcda704796ed08a77604ca1f4993", "token_estimator": "heuristic-v1" }, { - "id": "parachains-get-started", - "title": "Get Started with Parachain Development", - "slug": "parachains-get-started", + "id": "parachains-customize-runtime-pallet-development-create-a-pallet", + "title": "Create a Custom Pallet", + "slug": "parachains-customize-runtime-pallet-development-create-a-pallet", "categories": [ - "Basics", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md", - "html_url": "https://docs.polkadot.com/parachains/get-started/", - "preview": "The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/create-a-pallet/", + "preview": "[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functional", "outline": [ { "depth": 2, - "title": "Quick Start Guides", - "anchor": "quick-start-guides" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Launch a Simple Parachain", - "anchor": "launch-a-simple-parachain" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Customize Your Runtime", - "anchor": "customize-your-runtime" - }, - { - "depth": 3, - "title": "Pallet Development", - "anchor": "pallet-development" + "title": "Core Pallet Components", + "anchor": "core-pallet-components" }, { "depth": 2, - "title": "Testing", - "anchor": "testing" + "title": "Create the Pallet Project", + "anchor": "create-the-pallet-project" }, { "depth": 2, - "title": "Runtime Upgrades and Maintenance", - "anchor": "runtime-upgrades-and-maintenance" + "title": "Configure Dependencies", + "anchor": "configure-dependencies" }, { "depth": 2, - "title": "Interoperability", - "anchor": "interoperability" + "title": "Initialize the Pallet Structure", + "anchor": "initialize-the-pallet-structure" }, { "depth": 2, - "title": "Integrations", - "anchor": "integrations" + "title": "Configure the Pallet", + "anchor": "configure-the-pallet" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 7941, - "words": 631, - "headings": 9, - "estimated_token_count_total": 2292 - }, - "hash": "sha256:759ed27cf3d473445e33141089b652082c42a2c59eb822d6b506146fd9555e13", - "last_modified": "2025-10-28T14:42:14+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-install-polkadot-sdk", - "title": "Install Polkadot SDK Dependencies", - "slug": "parachains-install-polkadot-sdk", - "categories": [ - "Basics", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md", - "html_url": "https://docs.polkadot.com/parachains/install-polkadot-sdk/", - "preview": "This guide provides step-by-step instructions for installing the dependencies you need to work with the Polkadot SDK-based chains on macOS, Linux, and Windows. Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly.", - "outline": [ + "title": "Define Events", + "anchor": "define-events" + }, { "depth": 2, - "title": "macOS", - "anchor": "macos" + "title": "Define Errors", + "anchor": "define-errors" }, { - "depth": 3, - "title": "Before You Begin", - "anchor": "before-you-begin" + "depth": 2, + "title": "Add Storage Items", + "anchor": "add-storage-items" }, { - "depth": 3, - "title": "Install Required Packages and Rust", - "anchor": "install-required-packages-and-rust" + "depth": 2, + "title": "Configure Genesis State", + "anchor": "configure-genesis-state" }, { "depth": 2, - "title": "Linux", - "anchor": "linux" + "title": "Implement Dispatchable Functions", + "anchor": "implement-dispatchable-functions" }, { "depth": 3, - "title": "Before You Begin {: #before-you-begin-linux }", - "anchor": "before-you-begin-before-you-begin-linux" + "title": "Dispatchable Function Details", + "anchor": "dispatchable-function-details" }, { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-linux }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-linux" + "depth": 2, + "title": "Verify Pallet Compilation", + "anchor": "verify-pallet-compilation" }, { "depth": 2, - "title": "Windows (WSL)", - "anchor": "windows-wsl" + "title": "Add the Pallet to Your Runtime", + "anchor": "add-the-pallet-to-your-runtime" }, { "depth": 3, - "title": "Before You Begin {: #before-you-begin-windows }", - "anchor": "before-you-begin-before-you-begin-windows" + "title": "Add Runtime Dependency", + "anchor": "add-runtime-dependency" }, { "depth": 3, - "title": "Set Up Windows Subsystem for Linux", - "anchor": "set-up-windows-subsystem-for-linux" + "title": "Implement the Config Trait", + "anchor": "implement-the-config-trait" }, { "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-windows }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-windows" - }, - { - "depth": 2, - "title": "Verifying Installation", - "anchor": "verifying-installation" + "title": "Add to Runtime Construct", + "anchor": "add-to-runtime-construct" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 12756, - "words": 1840, - "headings": 12, - "estimated_token_count_total": 2709 - }, - "hash": "sha256:2ee5656f749b4bca445172f2bc66c7fc39af40ff173626662ae4c399f49cf909", - "last_modified": "2025-10-28T14:42:14+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-integrations-indexers", - "title": "Indexers", - "slug": "parachains-integrations-indexers", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/indexers/", - "preview": "Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges:", - "outline": [ - { - "depth": 2, - "title": "The Challenge of Blockchain Data Access", - "anchor": "the-challenge-of-blockchain-data-access" + "depth": 3, + "title": "Configure Genesis for Your Runtime", + "anchor": "configure-genesis-for-your-runtime" }, { - "depth": 2, - "title": "What is a Blockchain Indexer?", - "anchor": "what-is-a-blockchain-indexer" + "depth": 3, + "title": "Verify Runtime Compilation", + "anchor": "verify-runtime-compilation" }, { "depth": 2, - "title": "Indexer Implementations", - "anchor": "indexer-implementations" - } - ], - "stats": { - "chars": 2230, - "words": 302, - "headings": 3, - "estimated_token_count_total": 428 - }, - "hash": "sha256:cfcc76bb24779c9b613f2c046b6f99a0f2529c25fd82287d804f6b945b936227", - "last_modified": "2025-10-28T14:42:14+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-integrations-oracles", - "title": "Oracles", - "slug": "parachains-integrations-oracles", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/oracles/", - "preview": "Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the \"blockchain oracle problem.\" Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain.", - "outline": [ + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" + }, { - "depth": 2, - "title": "What is a Blockchain Oracle?", - "anchor": "what-is-a-blockchain-oracle" + "depth": 3, + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" }, { - "depth": 2, - "title": "Oracle Implementations", - "anchor": "oracle-implementations" - } - ], - "stats": { - "chars": 1343, - "words": 181, - "headings": 2, - "estimated_token_count_total": 245 - }, - "hash": "sha256:6d8e01281a5895fd2bc4438b24c170c72a496de0b838626a53e87685aea4aa25", - "last_modified": "2025-10-28T14:42:14+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-integrations-wallets", - "title": "Wallets", - "slug": "parachains-integrations-wallets", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/wallets/", - "preview": "A wallet serves as your gateway to interacting with blockchain networks. Rather than storing funds, wallets secure your private keys, controlling access to your blockchain assets. Your private key provides complete control over all permitted transactions on your blockchain account, making it essential to keep it secure.", - "outline": [ + "depth": 3, + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" + }, { "depth": 2, - "title": "What is a Blockchain Wallet?", - "anchor": "what-is-a-blockchain-wallet" + "title": "Interact with Your Pallet", + "anchor": "interact-with-your-pallet" }, { "depth": 2, - "title": "Hot Wallets", - "anchor": "hot-wallets" + "title": "Key Takeaways", + "anchor": "key-takeaways" }, { "depth": 2, - "title": "Cold Wallets", - "anchor": "cold-wallets" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 2921, - "words": 401, - "headings": 3, - "estimated_token_count_total": 633 + "chars": 26958, + "words": 3085, + "headings": 26, + "estimated_token_count_total": 6194 }, - "hash": "sha256:62c5ad101282227f79eac0e30a3ba9ce3ae1bf9e358bd58c0b17ef45db29c2ff", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:dad68ea59fd05fd60dc8890c4cf5615243c7ea879830b0dcf3a5e5e53c3ccec7", "token_estimator": "heuristic-v1" }, { - "id": "parachains-interoperability-channels-between-parachains", - "title": "Opening HRMP Channels Between Parachains", - "slug": "parachains-interoperability-channels-between-parachains", + "id": "parachains-customize-runtime-pallet-development-mock-runtime", + "title": "Mock Your Runtime", + "slug": "parachains-customize-runtime-pallet-development-mock-runtime", "categories": [ "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/", - "preview": "For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/", + "preview": "Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node.", "outline": [ { "depth": 2, @@ -7655,65 +5260,79 @@ }, { "depth": 2, - "title": "Procedure to Initiate an HRMP Channel", - "anchor": "procedure-to-initiate-an-hrmp-channel" + "title": "Understand Mock Runtimes", + "anchor": "understand-mock-runtimes" }, { - "depth": 3, - "title": "Fund Sender Sovereign Account", - "anchor": "fund-sender-sovereign-account" + "depth": 2, + "title": "Create the Mock Runtime Module", + "anchor": "create-the-mock-runtime-module" }, { - "depth": 3, - "title": "Create Channel Opening Extrinsic", - "anchor": "create-channel-opening-extrinsic" + "depth": 2, + "title": "Set Up Basic Mock", + "anchor": "set-up-basic-mock" }, { - "depth": 3, - "title": "Craft and Submit the XCM Message from the Sender", - "anchor": "craft-and-submit-the-xcm-message-from-the-sender" + "depth": 2, + "title": "Implement Essential Configuration", + "anchor": "implement-essential-configuration" }, { "depth": 2, - "title": "Procedure to Accept an HRMP Channel", - "anchor": "procedure-to-accept-an-hrmp-channel" + "title": "Implement Your Pallet's Configuration", + "anchor": "implement-your-pallets-configuration" }, { - "depth": 3, - "title": "Fund Receiver Sovereign Account", - "anchor": "fund-receiver-sovereign-account" + "depth": 2, + "title": "Configure Genesis Storage", + "anchor": "configure-genesis-storage" }, { "depth": 3, - "title": "Create Channel Accepting Extrinsic", - "anchor": "create-channel-accepting-extrinsic" + "title": "Basic Test Environment", + "anchor": "basic-test-environment" }, { "depth": 3, - "title": "Craft and Submit the XCM Message from the Receiver", - "anchor": "craft-and-submit-the-xcm-message-from-the-receiver" + "title": "Custom Genesis Configurations", + "anchor": "custom-genesis-configurations" + }, + { + "depth": 2, + "title": "Verify Mock Compilation", + "anchor": "verify-mock-compilation" + }, + { + "depth": 2, + "title": "Key Takeaways", + "anchor": "key-takeaways" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 10934, - "words": 1549, - "headings": 10, - "estimated_token_count_total": 2285 + "chars": 11766, + "words": 1369, + "headings": 13, + "estimated_token_count_total": 2514 }, - "hash": "sha256:b8de1228b9976765accd18ff724038bed6f2449367f500bc3177ab2a053abe63", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:dd784a5d2daebb9a885fe09f6a967e6c84958d96ddb38d8366eabe9d860fa539", "token_estimator": "heuristic-v1" }, { - "id": "parachains-interoperability-channels-with-system-parachains", - "title": "Opening HRMP Channels with System Parachains", - "slug": "parachains-interoperability-channels-with-system-parachains", + "id": "parachains-customize-runtime-pallet-development-pallet-testing", + "title": "Pallet Testing", + "slug": "parachains-customize-runtime-pallet-development-pallet-testing", "categories": [ "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/", - "preview": "While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/", + "preview": "Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.", "outline": [ { "depth": 2, @@ -7722,51 +5341,55 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Writing Unit Tests", + "anchor": "writing-unit-tests" }, { - "depth": 2, - "title": "Procedure to Establish an HRMP Channel", - "anchor": "procedure-to-establish-an-hrmp-channel" + "depth": 3, + "title": "Test Initialization", + "anchor": "test-initialization" }, { "depth": 3, - "title": "Fund Parachain Sovereign Account", - "anchor": "fund-parachain-sovereign-account" + "title": "Function Call Testing", + "anchor": "function-call-testing" }, { "depth": 3, - "title": "Create Establish Channel with System Extrinsic", - "anchor": "create-establish-channel-with-system-extrinsic" + "title": "Storage Testing", + "anchor": "storage-testing" }, { "depth": 3, - "title": "Craft and Submit the XCM Message", - "anchor": "craft-and-submit-the-xcm-message" + "title": "Event Testing", + "anchor": "event-testing" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 7203, - "words": 889, - "headings": 6, - "estimated_token_count_total": 1427 + "chars": 6892, + "words": 911, + "headings": 7, + "estimated_token_count_total": 1563 }, - "hash": "sha256:b501d99c464fb049d46676827b6a325a195c90617becc4a7db305441c115350a", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:8568dfa238b9a649a4e6e60510625c2e7879b76a93187b0b8b8dccf6bc467ae6", "token_estimator": "heuristic-v1" }, { - "id": "parachains-interoperability-get-started", - "title": "Introduction to XCM", - "slug": "parachains-interoperability-get-started", + "id": "parachains-customize-runtime", + "title": "Overview of FRAME", + "slug": "parachains-customize-runtime", "categories": [ "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/get-started/", - "preview": "Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/", + "preview": "A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a run", "outline": [ { "depth": 2, @@ -7775,304 +5398,319 @@ }, { "depth": 2, - "title": "Messaging Format", - "anchor": "messaging-format" + "title": "Understanding Your Runtime", + "anchor": "understanding-your-runtime" }, { "depth": 2, - "title": "The Four Principles of XCM", - "anchor": "the-four-principles-of-xcm" + "title": "Runtime Architecture", + "anchor": "runtime-architecture" }, { "depth": 2, - "title": "The XCM Tech Stack", - "anchor": "the-xcm-tech-stack" + "title": "Building Blocks: Pallets", + "anchor": "building-blocks-pallets" + }, + { + "depth": 3, + "title": "Pre-Built Pallets vs. Custom Pallets", + "anchor": "pre-built-pallets-vs-custom-pallets" + }, + { + "depth": 3, + "title": "Pallet Structure", + "anchor": "pallet-structure" }, { "depth": 2, - "title": "Core Functionalities of XCM", - "anchor": "core-functionalities-of-xcm" + "title": "How Runtime Customization Works", + "anchor": "how-runtime-customization-works" }, { "depth": 2, - "title": "XCM Example", - "anchor": "xcm-example" + "title": "Starting Templates", + "anchor": "starting-templates" }, { "depth": 2, - "title": "Overview", - "anchor": "overview" + "title": "Key Customization Scenarios", + "anchor": "key-customization-scenarios" } ], "stats": { - "chars": 7450, - "words": 974, - "headings": 7, - "estimated_token_count_total": 1501 - }, - "hash": "sha256:3b26606dd5310c4b8ade5d05270ebf1e06f59afcda4ca2b985e07948215a197e", - "last_modified": "2025-10-28T14:42:14+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-launch-a-parachain-choose-a-template", - "title": "parachains-launch-a-parachain-choose-a-template", - "slug": "parachains-launch-a-parachain-choose-a-template", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-choose-a-template.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/choose-a-template/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 8236, + "words": 1101, + "headings": 9, + "estimated_token_count_total": 1828 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:15:59+00:00", + "hash": "sha256:ad58d1c942b567acc4519abc35c0a049ab3e04711c2a49089ceba6324a5aa7ea", "token_estimator": "heuristic-v1" }, { - "id": "parachains-launch-a-parachain-deploy-to-polkadot", - "title": "Deploy on Polkadot", - "slug": "parachains-launch-a-parachain-deploy-to-polkadot", + "id": "parachains-get-started", + "title": "Get Started with Parachain Development", + "slug": "parachains-get-started", "categories": [ + "Basics", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-deploy-to-polkadot.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/deploy-to-polkadot/", - "preview": "Previously, you learned how to [choose and set up a parachain template](/parachains/launch-a-parachain/choose-a-template/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to the Polkadot TestNet. Deploying to a TestNet is a crucial step for validating your parachain's functionality and preparing it for eventual MainNet deployment.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md", + "html_url": "https://docs.polkadot.com/parachains/get-started/", + "preview": "The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Quick Start Guides", + "anchor": "quick-start-guides" }, { "depth": 2, - "title": "Get Started with an Account and Tokens", - "anchor": "get-started-with-an-account-and-tokens" + "title": "Launch a Simple Parachain", + "anchor": "launch-a-simple-parachain" }, { "depth": 2, - "title": "Reserve a Parachain Identifier", - "anchor": "reserve-a-parachain-identifier" + "title": "Customize Your Runtime", + "anchor": "customize-your-runtime" }, { - "depth": 2, - "title": "Generate Custom Keys for Your Collators", - "anchor": "generate-custom-keys-for-your-collators" + "depth": 3, + "title": "Pallet Development", + "anchor": "pallet-development" }, { "depth": 2, - "title": "Generate the Chain Specification", - "anchor": "generate-the-chain-specification" + "title": "Testing", + "anchor": "testing" }, { "depth": 2, - "title": "Export Required Files", - "anchor": "export-required-files" + "title": "Runtime Upgrades and Maintenance", + "anchor": "runtime-upgrades-and-maintenance" }, { "depth": 2, - "title": "Register a Parathread", - "anchor": "register-a-parathread" + "title": "Interoperability", + "anchor": "interoperability" }, { "depth": 2, - "title": "Start the Collator Node", - "anchor": "start-the-collator-node" + "title": "Integrations", + "anchor": "integrations" }, { "depth": 2, - "title": "Producing Blocks", - "anchor": "producing-blocks" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 14404, - "words": 2116, + "chars": 7941, + "words": 631, "headings": 9, - "estimated_token_count_total": 3296 + "estimated_token_count_total": 2292 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:759ed27cf3d473445e33141089b652082c42a2c59eb822d6b506146fd9555e13", "token_estimator": "heuristic-v1" }, { - "id": "parachains-launch-a-parachain-obtain-coretime", - "title": "Obtain Coretime", - "slug": "parachains-launch-a-parachain-obtain-coretime", + "id": "parachains-install-polkadot-sdk", + "title": "Install Polkadot SDK Dependencies", + "slug": "parachains-install-polkadot-sdk", "categories": [ - "Parachains" + "Basics", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/", - "preview": "After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md", + "html_url": "https://docs.polkadot.com/parachains/install-polkadot-sdk/", + "preview": "This guide provides step-by-step instructions for installing the dependencies you need to work with the Polkadot SDK-based chains on macOS, Linux, and Windows. Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "macOS", + "anchor": "macos" }, { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "depth": 3, + "title": "Before You Begin", + "anchor": "before-you-begin" + }, + { + "depth": 3, + "title": "Install Required Packages and Rust", + "anchor": "install-required-packages-and-rust" }, { "depth": 2, - "title": "Order On-Demand Coretime", - "anchor": "order-on-demand-coretime" + "title": "Linux", + "anchor": "linux" }, { "depth": 3, - "title": "On-Demand Extrinsics", - "anchor": "on-demand-extrinsics" + "title": "Before You Begin {: #before-you-begin-linux }", + "anchor": "before-you-begin-before-you-begin-linux" }, { "depth": 3, - "title": "Place an On-Demand Order", - "anchor": "place-an-on-demand-order" + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-linux }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-linux" }, { "depth": 2, - "title": "Purchase Bulk Coretime", - "anchor": "purchase-bulk-coretime" - }, - { - "depth": 3, - "title": "Connect Your Wallet to RegionX", - "anchor": "connect-your-wallet-to-regionx" + "title": "Windows (WSL)", + "anchor": "windows-wsl" }, { "depth": 3, - "title": "Obtain Coretime Chain Funds", - "anchor": "obtain-coretime-chain-funds" + "title": "Before You Begin {: #before-you-begin-windows }", + "anchor": "before-you-begin-before-you-begin-windows" }, { "depth": 3, - "title": "Purchase a Core", - "anchor": "purchase-a-core" + "title": "Set Up Windows Subsystem for Linux", + "anchor": "set-up-windows-subsystem-for-linux" }, { "depth": 3, - "title": "Verify Your Purchase", - "anchor": "verify-your-purchase" + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-windows }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-windows" }, { - "depth": 3, - "title": "Assign Your Parachain to the Core", - "anchor": "assign-your-parachain-to-the-core" + "depth": 2, + "title": "Verifying Installation", + "anchor": "verifying-installation" }, { "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 9049, - "words": 1345, + "chars": 12756, + "words": 1840, "headings": 12, - "estimated_token_count_total": 2103 + "estimated_token_count_total": 2709 }, - "hash": "sha256:15154f211753665d9af70dc81d15ceb3f0954e3febf9282c68c0074881d620c6", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:2ee5656f749b4bca445172f2bc66c7fc39af40ff173626662ae4c399f49cf909", "token_estimator": "heuristic-v1" }, { - "id": "parachains-launch-a-parachain-set-up-the-parachain-template", - "title": "Set Up the Polkadot SDK Parachain Template", - "slug": "parachains-launch-a-parachain-set-up-the-parachain-template", + "id": "parachains-integrations-indexers", + "title": "Indexers", + "slug": "parachains-integrations-indexers", "categories": [ - "Basics", - "Parachains" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/", - "preview": "The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/indexers/", + "preview": "Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges:", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Polkadot SDK Utility Tools", - "anchor": "polkadot-sdk-utility-tools" - }, - { - "depth": 2, - "title": "Clone the Template", - "anchor": "clone-the-template" + "title": "The Challenge of Blockchain Data Access", + "anchor": "the-challenge-of-blockchain-data-access" }, { "depth": 2, - "title": "Explore the Project Structure", - "anchor": "explore-the-project-structure" + "title": "What is a Blockchain Indexer?", + "anchor": "what-is-a-blockchain-indexer" }, { "depth": 2, - "title": "Compile the Runtime", - "anchor": "compile-the-runtime" - }, + "title": "Indexer Implementations", + "anchor": "indexer-implementations" + } + ], + "stats": { + "chars": 2230, + "words": 302, + "headings": 3, + "estimated_token_count_total": 428 + }, + "hash": "sha256:cfcc76bb24779c9b613f2c046b6f99a0f2529c25fd82287d804f6b945b936227", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-integrations-oracles", + "title": "Oracles", + "slug": "parachains-integrations-oracles", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/oracles/", + "preview": "Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the \"blockchain oracle problem.\" Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain.", + "outline": [ { "depth": 2, - "title": "Verify the Build", - "anchor": "verify-the-build" + "title": "What is a Blockchain Oracle?", + "anchor": "what-is-a-blockchain-oracle" }, { "depth": 2, - "title": "Run the Node Locally", - "anchor": "run-the-node-locally" - }, + "title": "Oracle Implementations", + "anchor": "oracle-implementations" + } + ], + "stats": { + "chars": 1343, + "words": 181, + "headings": 2, + "estimated_token_count_total": 245 + }, + "hash": "sha256:6d8e01281a5895fd2bc4438b24c170c72a496de0b838626a53e87685aea4aa25", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-integrations-wallets", + "title": "Wallets", + "slug": "parachains-integrations-wallets", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/wallets/", + "preview": "A wallet serves as your gateway to interacting with blockchain networks. Rather than storing funds, wallets secure your private keys, controlling access to your blockchain assets. Your private key provides complete control over all permitted transactions on your blockchain account, making it essential to keep it secure.", + "outline": [ { "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" + "title": "What is a Blockchain Wallet?", + "anchor": "what-is-a-blockchain-wallet" }, { "depth": 2, - "title": "Stop the Node", - "anchor": "stop-the-node" + "title": "Hot Wallets", + "anchor": "hot-wallets" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 2, + "title": "Cold Wallets", + "anchor": "cold-wallets" } ], "stats": { - "chars": 10608, - "words": 1512, - "headings": 11, - "estimated_token_count_total": 2379 + "chars": 2921, + "words": 401, + "headings": 3, + "estimated_token_count_total": 633 }, - "hash": "sha256:637b9460bb65621cbc7c1bff272ea287d5181a983bc61418167959e108e21791", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:62c5ad101282227f79eac0e30a3ba9ce3ae1bf9e358bd58c0b17ef45db29c2ff", "token_estimator": "heuristic-v1" }, { - "id": "parachains-overview", - "title": "Parachains Overview", - "slug": "parachains-overview", + "id": "parachains-interoperability-channels-between-parachains", + "title": "Opening HRMP Channels Between Parachains", + "slug": "parachains-interoperability-channels-between-parachains", "categories": [ - "Basics", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-overview.md", - "html_url": "https://docs.polkadot.com/parachains/overview/", - "preview": "A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/", + "preview": "For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required:", "outline": [ { "depth": 2, @@ -8081,97 +5719,69 @@ }, { "depth": 2, - "title": "Polkadot SDK: Parachain Architecture", - "anchor": "polkadot-sdk-parachain-architecture" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Substrate: The Foundation", - "anchor": "substrate-the-foundation" + "depth": 2, + "title": "Procedure to Initiate an HRMP Channel", + "anchor": "procedure-to-initiate-an-hrmp-channel" }, { "depth": 3, - "title": "FRAME: Building Blocks for Your Runtime", - "anchor": "frame-building-blocks-for-your-runtime" + "title": "Fund Sender Sovereign Account", + "anchor": "fund-sender-sovereign-account" }, { "depth": 3, - "title": "Cumulus: Parachain-Specific Functionality", - "anchor": "cumulus-parachain-specific-functionality" + "title": "Create Channel Opening Extrinsic", + "anchor": "create-channel-opening-extrinsic" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 8461, - "words": 1024, - "headings": 6, - "estimated_token_count_total": 1751 - }, - "hash": "sha256:bbef601f2645c23200a3b16bc1b8e5bcad2aafdee6d60ae860ce8b5a53122c14", - "last_modified": "2025-10-28T14:15:59+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-runtime-maintenance-runtime-upgrades", - "title": "Runtime Upgrades", - "slug": "parachains-runtime-maintenance-runtime-upgrades", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/", - "preview": "One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Craft and Submit the XCM Message from the Sender", + "anchor": "craft-and-submit-the-xcm-message-from-the-sender" }, { "depth": 2, - "title": "How Runtime Upgrades Work", - "anchor": "how-runtime-upgrades-work" + "title": "Procedure to Accept an HRMP Channel", + "anchor": "procedure-to-accept-an-hrmp-channel" }, { "depth": 3, - "title": "Runtime Versioning", - "anchor": "runtime-versioning" + "title": "Fund Receiver Sovereign Account", + "anchor": "fund-receiver-sovereign-account" }, { "depth": 3, - "title": "Accessing the Runtime Version", - "anchor": "accessing-the-runtime-version" + "title": "Create Channel Accepting Extrinsic", + "anchor": "create-channel-accepting-extrinsic" }, { - "depth": 2, - "title": "Storage Migrations", - "anchor": "storage-migrations" + "depth": 3, + "title": "Craft and Submit the XCM Message from the Receiver", + "anchor": "craft-and-submit-the-xcm-message-from-the-receiver" } ], "stats": { - "chars": 5837, - "words": 811, - "headings": 5, - "estimated_token_count_total": 1161 + "chars": 10934, + "words": 1549, + "headings": 10, + "estimated_token_count_total": 2285 }, - "hash": "sha256:ec31270001a6cd9d0a8ecb7974ad161d5c1ef4d3023d5a6af9fbc5a6ca46cbca", - "last_modified": "2025-10-28T14:42:14+00:00", + "hash": "sha256:b8de1228b9976765accd18ff724038bed6f2449367f500bc3177ab2a053abe63", "token_estimator": "heuristic-v1" }, { - "id": "parachains-runtime-maintenance-storage-migrations", - "title": "Storage Migrations", - "slug": "parachains-runtime-maintenance-storage-migrations", + "id": "parachains-interoperability-channels-with-system-parachains", + "title": "Opening HRMP Channels with System Parachains", + "slug": "parachains-interoperability-channels-with-system-parachains", "categories": [ "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/", - "preview": "Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/", + "preview": "While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach.", "outline": [ { "depth": 2, @@ -8180,70 +5790,50 @@ }, { "depth": 2, - "title": "Storage Migration Scenarios", - "anchor": "storage-migration-scenarios" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Implement Storage Migrations", - "anchor": "implement-storage-migrations" - }, - { - "depth": 3, - "title": "Core Migration Function", - "anchor": "core-migration-function" - }, - { - "depth": 3, - "title": "Migration Testing Hooks", - "anchor": "migration-testing-hooks" + "title": "Procedure to Establish an HRMP Channel", + "anchor": "procedure-to-establish-an-hrmp-channel" }, { "depth": 3, - "title": "Migration Structure", - "anchor": "migration-structure" + "title": "Fund Parachain Sovereign Account", + "anchor": "fund-parachain-sovereign-account" }, { "depth": 3, - "title": "Migration Organization", - "anchor": "migration-organization" + "title": "Create Establish Channel with System Extrinsic", + "anchor": "create-establish-channel-with-system-extrinsic" }, { "depth": 3, - "title": "Scheduling Migrations", - "anchor": "scheduling-migrations" - }, - { - "depth": 2, - "title": "Single-Block Migrations", - "anchor": "single-block-migrations" - }, - { - "depth": 2, - "title": "Multi Block Migrations", - "anchor": "multi-block-migrations" + "title": "Craft and Submit the XCM Message", + "anchor": "craft-and-submit-the-xcm-message" } ], "stats": { - "chars": 18500, - "words": 2363, - "headings": 10, - "estimated_token_count_total": 4014 + "chars": 7203, + "words": 889, + "headings": 6, + "estimated_token_count_total": 1427 }, - "hash": "sha256:55dc252fdecf1590048ce8d009b822e90231442abe81e9593cf1635944a31336", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:b501d99c464fb049d46676827b6a325a195c90617becc4a7db305441c115350a", "token_estimator": "heuristic-v1" }, { - "id": "parachains-runtime-maintenance-unlock-parachains", - "title": "Unlock a Parachain", - "slug": "parachains-runtime-maintenance-unlock-parachains", + "id": "parachains-interoperability-get-started", + "title": "Introduction to XCM", + "slug": "parachains-interoperability-get-started", "categories": [ - "Parachains" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-unlock-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/unlock-parachains/", - "preview": "Parachain locks are a critical security mechanism in the Polkadot ecosystem designed to maintain decentralization during the parachain lifecycle. These locks prevent potential centralization risks that could emerge during the early stages of parachain operation.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/get-started/", + "preview": "Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.", "outline": [ { "depth": 2, @@ -8252,51 +5842,54 @@ }, { "depth": 2, - "title": "Check If the Parachain Is Locked", - "anchor": "check-if-the-parachain-is-locked" + "title": "Messaging Format", + "anchor": "messaging-format" }, { "depth": 2, - "title": "How to Unlock a Parachain", - "anchor": "how-to-unlock-a-parachain" + "title": "The Four Principles of XCM", + "anchor": "the-four-principles-of-xcm" }, { - "depth": 3, - "title": "Prepare the Unlock Call", - "anchor": "prepare-the-unlock-call" + "depth": 2, + "title": "The XCM Tech Stack", + "anchor": "the-xcm-tech-stack" }, { - "depth": 3, - "title": "Fund the Sovereign Account", - "anchor": "fund-the-sovereign-account" + "depth": 2, + "title": "Core Functionalities of XCM", + "anchor": "core-functionalities-of-xcm" }, { - "depth": 3, - "title": "Craft and Submit the XCM", - "anchor": "craft-and-submit-the-xcm" + "depth": 2, + "title": "XCM Example", + "anchor": "xcm-example" + }, + { + "depth": 2, + "title": "Overview", + "anchor": "overview" } ], "stats": { - "chars": 9232, - "words": 1276, - "headings": 6, - "estimated_token_count_total": 2028 + "chars": 7450, + "words": 974, + "headings": 7, + "estimated_token_count_total": 1501 }, - "hash": "sha256:e408d05199cc184fc6fe8bb212efb3c9aa6cb79258977e07566692176c912def", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:3b26606dd5310c4b8ade5d05270ebf1e06f59afcda4ca2b985e07948215a197e", "token_estimator": "heuristic-v1" }, { - "id": "parachains-testing-fork-a-parachain", - "title": "Get Started", - "slug": "parachains-testing-fork-a-parachain", + "id": "parachains-launch-a-parachain-deploy-to-polkadot", + "title": "Deploy on Polkadot", + "slug": "parachains-launch-a-parachain-deploy-to-polkadot", "categories": [ - "Parachains", - "Tooling" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md", - "html_url": "https://docs.polkadot.com/parachains/testing/fork-a-parachain/", - "preview": "[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-deploy-to-polkadot.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/deploy-to-polkadot/", + "preview": "Previously, you learned how to [choose and set up a parachain template](/parachains/launch-a-parachain/choose-a-template/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to the Polkadot TestNet. Deploying to a TestNet is a crucial step for validating your parachain's functionality and preparing it for eventual MainNet deployment.", "outline": [ { "depth": 2, @@ -8305,71 +5898,64 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Get Started with an Account and Tokens", + "anchor": "get-started-with-an-account-and-tokens" }, { "depth": 2, - "title": "Install Chopsticks", - "anchor": "install-chopsticks" - }, - { - "depth": 3, - "title": "Global Installation", - "anchor": "global-installation" + "title": "Reserve a Parachain Identifier", + "anchor": "reserve-a-parachain-identifier" }, { - "depth": 3, - "title": "Local Installation", - "anchor": "local-installation" + "depth": 2, + "title": "Generate Custom Keys for Your Collators", + "anchor": "generate-custom-keys-for-your-collators" }, { "depth": 2, - "title": "Configure Chopsticks", - "anchor": "configure-chopsticks" + "title": "Generate the Chain Specification", + "anchor": "generate-the-chain-specification" }, { - "depth": 3, - "title": "Configuration File", - "anchor": "configuration-file" + "depth": 2, + "title": "Export Required Files", + "anchor": "export-required-files" }, { - "depth": 3, - "title": "CLI Flags", - "anchor": "cli-flags" + "depth": 2, + "title": "Register a Parathread", + "anchor": "register-a-parathread" }, { "depth": 2, - "title": "WebSocket Commands", - "anchor": "websocket-commands" + "title": "Start the Collator Node", + "anchor": "start-the-collator-node" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Producing Blocks", + "anchor": "producing-blocks" } ], "stats": { - "chars": 10894, - "words": 1330, - "headings": 10, - "estimated_token_count_total": 2614 + "chars": 14404, + "words": 2116, + "headings": 9, + "estimated_token_count_total": 3296 }, - "hash": "sha256:4325cdd697814b8043db808da3dee86d3d9c6fc7dd523aae7fe8914d59d1b39c", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:fde940bced4380fc01b1840907059d03f6d47b6cb54bf78c95269ac57adbc99e", "token_estimator": "heuristic-v1" }, { - "id": "parachains-testing-run-a-parachain-network", - "title": "Get Started", - "slug": "parachains-testing-run-a-parachain-network", + "id": "parachains-launch-a-parachain-obtain-coretime", + "title": "Obtain Coretime", + "slug": "parachains-launch-a-parachain-obtain-coretime", "categories": [ - "Parachains", - "Tooling" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md", - "html_url": "https://docs.polkadot.com/parachains/testing/run-a-parachain-network/", - "preview": "Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/", + "preview": "After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime.", "outline": [ { "depth": 2, @@ -8378,91 +5964,80 @@ }, { "depth": 2, - "title": "Install Zombienet", - "anchor": "install-zombienet" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Providers", - "anchor": "providers" - }, - { - "depth": 3, - "title": "Kubernetes", - "anchor": "kubernetes" + "title": "Order On-Demand Coretime", + "anchor": "order-on-demand-coretime" }, { "depth": 3, - "title": "Podman", - "anchor": "podman" + "title": "On-Demand Extrinsics", + "anchor": "on-demand-extrinsics" }, { "depth": 3, - "title": "Local Provider", - "anchor": "local-provider" + "title": "Place an On-Demand Order", + "anchor": "place-an-on-demand-order" }, { "depth": 2, - "title": "Configure Zombienet", - "anchor": "configure-zombienet" - }, - { - "depth": 3, - "title": "Configuration Files", - "anchor": "configuration-files" + "title": "Purchase Bulk Coretime", + "anchor": "purchase-bulk-coretime" }, { "depth": 3, - "title": "CLI Usage", - "anchor": "cli-usage" + "title": "Connect Your Wallet to RegionX", + "anchor": "connect-your-wallet-to-regionx" }, { "depth": 3, - "title": "Settings", - "anchor": "settings" + "title": "Obtain Coretime Chain Funds", + "anchor": "obtain-coretime-chain-funds" }, { "depth": 3, - "title": "Relay Chain Configuration", - "anchor": "relay-chain-configuration" + "title": "Purchase a Core", + "anchor": "purchase-a-core" }, { "depth": 3, - "title": "Parachain Configuration", - "anchor": "parachain-configuration" + "title": "Verify Your Purchase", + "anchor": "verify-your-purchase" }, { "depth": 3, - "title": "XCM Configuration", - "anchor": "xcm-configuration" + "title": "Assign Your Parachain to the Core", + "anchor": "assign-your-parachain-to-the-core" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 41636, - "words": 4599, - "headings": 14, - "estimated_token_count_total": 9871 + "chars": 9049, + "words": 1345, + "headings": 12, + "estimated_token_count_total": 2103 }, - "hash": "sha256:0d7e04fd952cc9d5bd8cdbfd87cc4004c5f95e896a16bc7f89dfc4caeac8f371", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:15154f211753665d9af70dc81d15ceb3f0954e3febf9282c68c0074881d620c6", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-parachains-consensus", - "title": "Parachain Consensus", - "slug": "polkadot-protocol-architecture-parachains-consensus", + "id": "parachains-launch-a-parachain-set-up-the-parachain-template", + "title": "Set Up the Polkadot SDK Parachain Template", + "slug": "parachains-launch-a-parachain-set-up-the-parachain-template", "categories": [ - "Polkadot Protocol", + "Basics", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains-consensus.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/consensus/", - "preview": "Parachains are independent blockchains built with the Polkadot SDK, designed to leverage Polkadot’s relay chain for shared security and transaction finality. These specialized chains operate as part of Polkadot’s execution sharding model, where each parachain manages its own state and transactions while relying on the relay chain for validation and consensus.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/", + "preview": "The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs.", "outline": [ { "depth": 2, @@ -8471,82 +6046,48 @@ }, { "depth": 2, - "title": "The Role of Collators", - "anchor": "the-role-of-collators" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Consensus and Validation", - "anchor": "consensus-and-validation" - }, - { - "depth": 3, - "title": "Path of a Parachain Block", - "anchor": "path-of-a-parachain-block" + "title": "Polkadot SDK Utility Tools", + "anchor": "polkadot-sdk-utility-tools" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 6150, - "words": 790, - "headings": 5, - "estimated_token_count_total": 1125 - }, - "hash": "sha256:9875239c6071033a37a0f67fabca5a6e840c4a287620309f47b4f29c5a95a1cb", - "last_modified": "2025-10-28T14:42:15+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-architecture-parachains-overview", - "title": "Overview", - "slug": "polkadot-protocol-architecture-parachains-overview", - "categories": [ - "Basics", - "Polkadot Protocol", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains-overview.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/overview/", - "preview": "A [_parachain_](/polkadot-protocol/glossary#parachain){target=\\_blank} is a coherent, application-specific blockchain that derives security from its respective relay chain. Parachains on Polkadot are each their own separate, fully functioning blockchain. The primary difference between a parachain and a regular, \"solo\" blockchain is that the relay chain verifies the state of all parachains that are connected to it. In many ways, parachains can be thought of as a [\"cynical\" rollup](#cryptoeconomic", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Clone the Template", + "anchor": "clone-the-template" }, { "depth": 2, - "title": "Coherent Systems", - "anchor": "coherent-systems" + "title": "Explore the Project Structure", + "anchor": "explore-the-project-structure" }, { "depth": 2, - "title": "Flexible Ecosystem", - "anchor": "flexible-ecosystem" + "title": "Compile the Runtime", + "anchor": "compile-the-runtime" }, { "depth": 2, - "title": "State Transition Functions (Runtimes)", - "anchor": "state-transition-functions-runtimes" + "title": "Verify the Build", + "anchor": "verify-the-build" }, { "depth": 2, - "title": "Shared Security: Validated by the Relay Chain", - "anchor": "shared-security-validated-by-the-relay-chain" + "title": "Run the Node Locally", + "anchor": "run-the-node-locally" }, { - "depth": 3, - "title": "Cryptoeconomic Security: ELVES Protocol", - "anchor": "cryptoeconomic-security-elves-protocol" + "depth": 2, + "title": "Interact with the Node", + "anchor": "interact-with-the-node" }, { "depth": 2, - "title": "Interoperability", - "anchor": "interoperability" + "title": "Stop the Node", + "anchor": "stop-the-node" }, { "depth": 2, @@ -8555,83 +6096,70 @@ } ], "stats": { - "chars": 9561, - "words": 1321, - "headings": 8, - "estimated_token_count_total": 1861 + "chars": 10608, + "words": 1512, + "headings": 11, + "estimated_token_count_total": 2379 }, - "hash": "sha256:932c12e1af939698279ede2eacb2190e1f56119582adf2064d6cf86f7a4f3e3c", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:637b9460bb65621cbc7c1bff272ea287d5181a983bc61418167959e108e21791", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-parachains", - "title": "Parachains", - "slug": "polkadot-protocol-architecture-parachains", + "id": "parachains-runtime-maintenance-runtime-upgrades", + "title": "Runtime Upgrades", + "slug": "parachains-runtime-maintenance-runtime-upgrades", "categories": [ - "Uncategorized" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/", - "preview": "Discover how parachains secure their networks and reach consensus by harnessing Polkadot’s relay chain and its robust validator framework. This integrated architecture ensures shared security and seamless coordination across the entire ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/", + "preview": "One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.", "outline": [ { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 725, - "words": 93, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:00be43ac8d666bbe15c5c2fa5a5085697d0bb5a6f341ebbb943a209f0be355df", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-architecture-polkadot-chain", - "title": "The Polkadot Relay Chain", - "slug": "polkadot-protocol-architecture-polkadot-chain", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-polkadot-chain.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/", - "preview": "Discover the central role of the Polkadot relay chain in securing the network and fostering interoperability. As the backbone of Polkadot, the relay chain provides shared security and ensures consensus across the ecosystem. It empowers parachains with flexible coretime allocation, enabling them to purchase blockspace on demand, ensuring efficiency and scalability for diverse blockchain applications.", - "outline": [ + "title": "Introduction", + "anchor": "introduction" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "How Runtime Upgrades Work", + "anchor": "how-runtime-upgrades-work" + }, + { + "depth": 3, + "title": "Runtime Versioning", + "anchor": "runtime-versioning" + }, + { + "depth": 3, + "title": "Accessing the Runtime Version", + "anchor": "accessing-the-runtime-version" + }, + { + "depth": 2, + "title": "Storage Migrations", + "anchor": "storage-migrations" } ], "stats": { - "chars": 481, - "words": 63, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 5837, + "words": 811, + "headings": 5, + "estimated_token_count_total": 1161 }, - "hash": "sha256:2d228c52844df8952520fafdd3e6f0e26bfd2f32b5ee60c6241cf7d38603643c", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:ec31270001a6cd9d0a8ecb7974ad161d5c1ef4d3023d5a6af9fbc5a6ca46cbca", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-polkadot-chain-overview", - "title": "Overview of the Polkadot Relay Chain", - "slug": "polkadot-protocol-architecture-polkadot-chain-overview", + "id": "parachains-runtime-maintenance-storage-migrations", + "title": "Storage Migrations", + "slug": "parachains-runtime-maintenance-storage-migrations", "categories": [ - "Basics", - "Polkadot Protocol", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-polkadot-chain-overview.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/overview/", - "preview": "Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/polkadot-protocol/glossary/#nominated-proof-of-stake-npos){target=\\_blank}, and cross-c", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/", + "preview": "Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime", "outline": [ { "depth": 2, @@ -8640,75 +6168,69 @@ }, { "depth": 2, - "title": "Polkadot 1.0", - "anchor": "polkadot-10" + "title": "Storage Migration Scenarios", + "anchor": "storage-migration-scenarios" }, { - "depth": 3, - "title": "High-Level Architecture", - "anchor": "high-level-architecture" + "depth": 2, + "title": "Implement Storage Migrations", + "anchor": "implement-storage-migrations" }, { "depth": 3, - "title": "Polkadot's Additional Functionalities", - "anchor": "polkadots-additional-functionalities" + "title": "Core Migration Function", + "anchor": "core-migration-function" }, { "depth": 3, - "title": "Polkadot's Resilience", - "anchor": "polkadots-resilience" + "title": "Migration Testing Hooks", + "anchor": "migration-testing-hooks" }, { "depth": 3, - "title": "Polkadot's Blockspace", - "anchor": "polkadots-blockspace" - }, - { - "depth": 2, - "title": "DOT Token", - "anchor": "dot-token" + "title": "Migration Structure", + "anchor": "migration-structure" }, { "depth": 3, - "title": "Redenomination of DOT", - "anchor": "redenomination-of-dot" + "title": "Migration Organization", + "anchor": "migration-organization" }, { "depth": 3, - "title": "The Planck Unit", - "anchor": "the-planck-unit" + "title": "Scheduling Migrations", + "anchor": "scheduling-migrations" }, { - "depth": 3, - "title": "Uses for DOT", - "anchor": "uses-for-dot" + "depth": 2, + "title": "Single-Block Migrations", + "anchor": "single-block-migrations" }, { "depth": 2, - "title": "JAM and the Road Ahead", - "anchor": "jam-and-the-road-ahead" + "title": "Multi Block Migrations", + "anchor": "multi-block-migrations" } ], "stats": { - "chars": 12513, - "words": 1781, - "headings": 11, - "estimated_token_count_total": 2591 + "chars": 18500, + "words": 2363, + "headings": 10, + "estimated_token_count_total": 4014 }, - "hash": "sha256:201e7efa0ad6b24890dd06f69714e19d9700ab7f7a51a33fe6d6e0664b7170b2", - "last_modified": "2025-10-28T14:15:59+00:00", + "hash": "sha256:55dc252fdecf1590048ce8d009b822e90231442abe81e9593cf1635944a31336", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-polkadot-chain-pos-consensus", - "title": "Proof of Stake Consensus", - "slug": "polkadot-protocol-architecture-polkadot-chain-pos-consensus", + "id": "parachains-runtime-maintenance-unlock-parachains", + "title": "Unlock a Parachain", + "slug": "parachains-runtime-maintenance-unlock-parachains", "categories": [ - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-polkadot-chain-pos-consensus.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/pos-consensus/", - "preview": "Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/polkadot-protocol/glossary/#nominated-proof-of-stake-npos){target=\\_blank} model a", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-unlock-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/unlock-parachains/", + "preview": "Parachain locks are a critical security mechanism in the Polkadot ecosystem designed to maintain decentralization during the parachain lifecycle. These locks prevent potential centralization risks that could emerge during the early stages of parachain operation.", "outline": [ { "depth": 2, @@ -8717,86 +6239,122 @@ }, { "depth": 2, - "title": "Nominated Proof of Stake", - "anchor": "nominated-proof-of-stake" + "title": "Check If the Parachain Is Locked", + "anchor": "check-if-the-parachain-is-locked" }, { "depth": 2, - "title": "Hybrid Consensus", - "anchor": "hybrid-consensus" + "title": "How to Unlock a Parachain", + "anchor": "how-to-unlock-a-parachain" }, { - "depth": 2, - "title": "Block Production - BABE", - "anchor": "block-production-babe" + "depth": 3, + "title": "Prepare the Unlock Call", + "anchor": "prepare-the-unlock-call" }, { "depth": 3, - "title": "Validator Participation", - "anchor": "validator-participation" + "title": "Fund the Sovereign Account", + "anchor": "fund-the-sovereign-account" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Craft and Submit the XCM", + "anchor": "craft-and-submit-the-xcm" + } + ], + "stats": { + "chars": 9232, + "words": 1276, + "headings": 6, + "estimated_token_count_total": 2028 + }, + "hash": "sha256:e408d05199cc184fc6fe8bb212efb3c9aa6cb79258977e07566692176c912def", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-testing-fork-a-parachain", + "title": "Get Started", + "slug": "parachains-testing-fork-a-parachain", + "categories": [ + "Parachains", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md", + "html_url": "https://docs.polkadot.com/parachains/testing/fork-a-parachain/", + "preview": "[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Finality Gadget - GRANDPA", - "anchor": "finality-gadget-grandpa" + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Install Chopsticks", + "anchor": "install-chopsticks" }, { "depth": 3, - "title": "Probabilistic vs. Provable Finality", - "anchor": "probabilistic-vs-provable-finality" + "title": "Global Installation", + "anchor": "global-installation" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-2" + "title": "Local Installation", + "anchor": "local-installation" }, { "depth": 2, - "title": "Fork Choice", - "anchor": "fork-choice" + "title": "Configure Chopsticks", + "anchor": "configure-chopsticks" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-3" + "title": "Configuration File", + "anchor": "configuration-file" + }, + { + "depth": 3, + "title": "CLI Flags", + "anchor": "cli-flags" }, { "depth": 2, - "title": "Bridging - BEEFY", - "anchor": "bridging-beefy" + "title": "WebSocket Commands", + "anchor": "websocket-commands" }, { - "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-4" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 12788, - "words": 1838, - "headings": 13, - "estimated_token_count_total": 2534 + "chars": 10894, + "words": 1330, + "headings": 10, + "estimated_token_count_total": 2614 }, - "hash": "sha256:191df9b098e17e9de4597c9f8ced8abbafdfabc7e0f5c0a94d767fc2c9d7742b", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:4325cdd697814b8043db808da3dee86d3d9c6fc7dd523aae7fe8914d59d1b39c", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-system-chains-asset-hub", - "title": "Asset Hub", - "slug": "polkadot-protocol-architecture-system-chains-asset-hub", + "id": "parachains-testing-run-a-parachain-network", + "title": "Get Started", + "slug": "parachains-testing-run-a-parachain-network", "categories": [ - "Polkadot Protocol" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-system-chains-asset-hub.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/system-chains/asset-hub/", - "preview": "The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integra", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md", + "html_url": "https://docs.polkadot.com/parachains/testing/run-a-parachain-network/", + "preview": "Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.", "outline": [ { "depth": 2, @@ -8805,103 +6363,110 @@ }, { "depth": 2, - "title": "Assets Basics", - "anchor": "assets-basics" + "title": "Install Zombienet", + "anchor": "install-zombienet" }, { "depth": 2, - "title": "Assets Pallet", - "anchor": "assets-pallet" + "title": "Providers", + "anchor": "providers" }, { "depth": 3, - "title": "Key Features", - "anchor": "key-features" + "title": "Kubernetes", + "anchor": "kubernetes" }, { "depth": 3, - "title": "Main Functions", - "anchor": "main-functions" + "title": "Podman", + "anchor": "podman" }, { "depth": 3, - "title": "Querying Functions", - "anchor": "querying-functions" + "title": "Local Provider", + "anchor": "local-provider" }, { - "depth": 3, - "title": "Permission Models and Roles", - "anchor": "permission-models-and-roles" + "depth": 2, + "title": "Configure Zombienet", + "anchor": "configure-zombienet" }, { "depth": 3, - "title": "Asset Freezing", - "anchor": "asset-freezing" + "title": "Configuration Files", + "anchor": "configuration-files" }, { "depth": 3, - "title": "Non-Custodial Transfers (Approval API)", - "anchor": "non-custodial-transfers-approval-api" - }, - { - "depth": 2, - "title": "Foreign Assets", - "anchor": "foreign-assets" + "title": "CLI Usage", + "anchor": "cli-usage" }, { "depth": 3, - "title": "Handling Foreign Assets", - "anchor": "handling-foreign-assets" - }, - { - "depth": 2, - "title": "Integration", - "anchor": "integration" + "title": "Settings", + "anchor": "settings" }, { "depth": 3, - "title": "API Sidecar", - "anchor": "api-sidecar" + "title": "Relay Chain Configuration", + "anchor": "relay-chain-configuration" }, { "depth": 3, - "title": "TxWrapper", - "anchor": "txwrapper" + "title": "Parachain Configuration", + "anchor": "parachain-configuration" }, { "depth": 3, - "title": "ParaSpell", - "anchor": "paraspell" + "title": "XCM Configuration", + "anchor": "xcm-configuration" }, { - "depth": 3, - "title": "Parachain Node", - "anchor": "parachain-node" - }, + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 41636, + "words": 4599, + "headings": 14, + "estimated_token_count_total": 9871 + }, + "hash": "sha256:0d7e04fd952cc9d5bd8cdbfd87cc4004c5f95e896a16bc7f89dfc4caeac8f371", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol-architecture-parachains-consensus", + "title": "Parachain Consensus", + "slug": "polkadot-protocol-architecture-parachains-consensus", + "categories": [ + "Polkadot Protocol", + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains-consensus.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/consensus/", + "preview": "Parachains are independent blockchains built with the Polkadot SDK, designed to leverage Polkadot’s relay chain for shared security and transaction finality. These specialized chains operate as part of Polkadot’s execution sharding model, where each parachain manages its own state and transactions while relying on the relay chain for validation and consensus.", + "outline": [ { "depth": 2, - "title": "XCM Transfer Monitoring", - "anchor": "xcm-transfer-monitoring" - }, - { - "depth": 3, - "title": "Monitor XCM Deposits", - "anchor": "monitor-xcm-deposits" + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Track XCM Information Back to the Source", - "anchor": "track-xcm-information-back-to-the-source" + "depth": 2, + "title": "The Role of Collators", + "anchor": "the-role-of-collators" }, { - "depth": 3, - "title": "Practical Monitoring Examples", - "anchor": "practical-monitoring-examples" + "depth": 2, + "title": "Consensus and Validation", + "anchor": "consensus-and-validation" }, { "depth": 3, - "title": "Monitor for Failed XCM Transfers", - "anchor": "monitor-for-failed-xcm-transfers" + "title": "Path of a Parachain Block", + "anchor": "path-of-a-parachain-block" }, { "depth": 2, @@ -8910,26 +6475,26 @@ } ], "stats": { - "chars": 20100, - "words": 2910, - "headings": 22, - "estimated_token_count_total": 4105 + "chars": 6150, + "words": 790, + "headings": 5, + "estimated_token_count_total": 1125 }, - "hash": "sha256:759ab6dea0ad03c3f627558ea186d9f32351fa559acde82931684efc2da59d46", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:9875239c6071033a37a0f67fabca5a6e840c4a287620309f47b4f29c5a95a1cb", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-system-chains-bridge-hub", - "title": "Bridge Hub", - "slug": "polkadot-protocol-architecture-system-chains-bridge-hub", + "id": "polkadot-protocol-architecture-parachains-overview", + "title": "Overview", + "slug": "polkadot-protocol-architecture-parachains-overview", "categories": [ - "Polkadot Protocol" + "Basics", + "Polkadot Protocol", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-system-chains-bridge-hub.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/system-chains/bridge-hub/", - "preview": "The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/polkadot-protocol/glossary/#pallet){target=\\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains-overview.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/overview/", + "preview": "A [_parachain_](/polkadot-protocol/glossary#parachain){target=\\_blank} is a coherent, application-specific blockchain that derives security from its respective relay chain. Parachains on Polkadot are each their own separate, fully functioning blockchain. The primary difference between a parachain and a regular, \"solo\" blockchain is that the relay chain verifies the state of all parachains that are connected to it. In many ways, parachains can be thought of as a [\"cynical\" rollup](#cryptoeconomic", "outline": [ { "depth": 2, @@ -8938,23 +6503,33 @@ }, { "depth": 2, - "title": "Trustless Bridging", - "anchor": "trustless-bridging" + "title": "Coherent Systems", + "anchor": "coherent-systems" }, { "depth": 2, - "title": "Bridging Components", - "anchor": "bridging-components" + "title": "Flexible Ecosystem", + "anchor": "flexible-ecosystem" + }, + { + "depth": 2, + "title": "State Transition Functions (Runtimes)", + "anchor": "state-transition-functions-runtimes" + }, + { + "depth": 2, + "title": "Shared Security: Validated by the Relay Chain", + "anchor": "shared-security-validated-by-the-relay-chain" }, { "depth": 3, - "title": "Ethereum-Specific Support", - "anchor": "ethereum-specific-support" + "title": "Cryptoeconomic Security: ELVES Protocol", + "anchor": "cryptoeconomic-security-elves-protocol" }, { "depth": 2, - "title": "Deployed Bridges", - "anchor": "deployed-bridges" + "title": "Interoperability", + "anchor": "interoperability" }, { "depth": 2, @@ -8963,47 +6538,64 @@ } ], "stats": { - "chars": 5475, - "words": 775, - "headings": 6, - "estimated_token_count_total": 1218 + "chars": 9561, + "words": 1321, + "headings": 8, + "estimated_token_count_total": 1861 }, - "hash": "sha256:26c156146ef9743fc26c6499294ff14186f97edbc2a34f445d3366b72f7148ae", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:932c12e1af939698279ede2eacb2190e1f56119582adf2064d6cf86f7a4f3e3c", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-system-chains-collectives", - "title": "Collectives Chain", - "slug": "polkadot-protocol-architecture-system-chains-collectives", + "id": "polkadot-protocol-architecture-parachains", + "title": "Parachains", + "slug": "polkadot-protocol-architecture-parachains", "categories": [ - "Polkadot Protocol" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-system-chains-collectives.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/system-chains/collectives/", - "preview": "Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/", + "preview": "Discover how parachains secure their networks and reach consensus by harnessing Polkadot’s relay chain and its robust validator framework. This integrated architecture ensures shared security and seamless coordination across the entire ecosystem.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 725, + "words": 93, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:3b9160b166d9b42b124f3b07eb26bdc5499fbbace6f951095009a5eee7fccbb6", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol-architecture-polkadot-chain", + "title": "The Polkadot Relay Chain", + "slug": "polkadot-protocol-architecture-polkadot-chain", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-polkadot-chain.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/", + "preview": "Discover the central role of the Polkadot relay chain in securing the network and fostering interoperability. As the backbone of Polkadot, the relay chain provides shared security and ensures consensus across the ecosystem. It empowers parachains with flexible coretime allocation, enabling them to purchase blockspace on demand, ensuring efficiency and scalability for diverse blockchain applications.", + "outline": [ { "depth": 2, - "title": "Key Collectives", - "anchor": "key-collectives" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 2288, - "words": 293, - "headings": 2, - "estimated_token_count_total": 424 + "chars": 481, + "words": 63, + "headings": 1, + "estimated_token_count_total": 12 }, - "hash": "sha256:59ec351fbb8d3a392e90f4f5bf6b62f58b21d6d7a900c5e367e5d2e09ecb3aca", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:c29356358f095b0d413e4c6525146b3f1b0b900853aada2168e7e55cd8dd6641", "token_estimator": "heuristic-v1" }, { @@ -9045,7 +6637,6 @@ "estimated_token_count_total": 1230 }, "hash": "sha256:8d186fa56ccbbf4b6c85cffc5521b9a99a20e9517f3b4a435730745803cbf2e8", - "last_modified": "2025-10-28T14:42:15+00:00", "token_estimator": "heuristic-v1" }, { @@ -9113,7 +6704,6 @@ "estimated_token_count_total": 1643 }, "hash": "sha256:100377787627052a29bd1173270b5ad307639b828c331e71c85d4c00bc5692d8", - "last_modified": "2025-10-28T14:42:15+00:00", "token_estimator": "heuristic-v1" }, { @@ -9139,9 +6729,7 @@ "headings": 1, "estimated_token_count_total": 12 }, - "hash": "sha256:8239d1e8d8642cb7c10e9e5f971c99b999e9e4a87373b50bf4a691225c1e4702", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:6ef13c197dd1865fcc1a405d67486f1d053534d576bb32fe47a442fd2c11b6cd", "token_estimator": "heuristic-v1" }, { @@ -9172,9 +6760,7 @@ "headings": 2, "estimated_token_count_total": 177 }, - "hash": "sha256:f0e04286eacf23b182186f23e9854c0cd251545b8a8d561d2503f962dbfe32c0", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:ffda04c93c70ec7204be28b642fa6e51f6bf9436d4792ecd25136696683f0902", "token_estimator": "heuristic-v1" }, { @@ -9205,9 +6791,7 @@ "headings": 2, "estimated_token_count_total": 233 }, - "hash": "sha256:baba9dd41091b792d09005d55d3df0bf65b35f42b40ebe63caf425a0978a22b0", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:58fd5c8c092ee748c2979164f985a67071a6ccb88492e79cdad536363364c858", "token_estimator": "heuristic-v1" }, { @@ -9233,9 +6817,7 @@ "headings": 1, "estimated_token_count_total": 12 }, - "hash": "sha256:62beec261e72529f70e07a641177d489d2c8872f9c9d618cbadf1ac0fd881986", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:235f33cdb64494815dbb3eb58ea98c69935098684e1b34b6d15356bc54b082ea", "token_estimator": "heuristic-v1" }, { @@ -9250,33 +6832,143 @@ "preview": "This section equips developers with the essential knowledge to create, deploy, and enhance applications and blockchains within the Polkadot ecosystem. Gain a comprehensive understanding of Polkadot’s foundational components, including accounts, balances, and transactions, as well as advanced topics like data encoding and cryptographic methods. Mastering these concepts is vital for building robust and secure applications on Polkadot.", "outline": [ { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 998, + "words": 130, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:1514316acba1e9bba82ae1c82b09481e9d03d286e6f5d93b66e5a85fd4be7bca", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol-smart-contract-basics-evm-vs-polkavm", + "title": "EVM vs PolkaVM", + "slug": "polkadot-protocol-smart-contract-basics-evm-vs-polkavm", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-evm-vs-polkavm.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Core Virtual Machine Architecture", + "anchor": "core-virtual-machine-architecture" + }, + { + "depth": 3, + "title": "High-Level Architecture Comparison", + "anchor": "high-level-architecture-comparison" + }, + { + "depth": 2, + "title": "Gas Model", + "anchor": "gas-model" + }, + { + "depth": 3, + "title": "Dynamic Gas Value Scaling", + "anchor": "dynamic-gas-value-scaling" + }, + { + "depth": 3, + "title": "Multi-Dimensional Resource Metering", + "anchor": "multi-dimensional-resource-metering" + }, + { + "depth": 2, + "title": "Memory Management", + "anchor": "memory-management" + }, + { + "depth": 3, + "title": "Current Memory Limits", + "anchor": "current-memory-limits" + }, + { + "depth": 2, + "title": "Account Management - Existential Deposit", + "anchor": "account-management-existential-deposit" + }, + { + "depth": 3, + "title": "Account Management Comparison", + "anchor": "account-management-comparison" + }, + { + "depth": 2, + "title": "Contract Deployment", + "anchor": "contract-deployment" + }, + { + "depth": 2, + "title": "Solidity and YUL IR Translation Incompatibilities", + "anchor": "solidity-and-yul-ir-translation-incompatibilities" + }, + { + "depth": 3, + "title": "Contract Code Structure", + "anchor": "contract-code-structure" + }, + { + "depth": 3, + "title": "Solidity-Specific Differences", + "anchor": "solidity-specific-differences" + }, + { + "depth": 3, + "title": "YUL Function Translation Differences", + "anchor": "yul-function-translation-differences" + }, + { + "depth": 3, + "title": "Unsupported Operations", + "anchor": "unsupported-operations" + }, + { + "depth": 3, + "title": "Compilation Pipeline Considerations", + "anchor": "compilation-pipeline-considerations" + }, + { + "depth": 3, + "title": "Memory Pointer Limitations", + "anchor": "memory-pointer-limitations" } ], "stats": { - "chars": 29648, - "words": 4201, - "headings": 15, - "estimated_token_count_total": 6521 + "chars": 27673, + "words": 3392, + "headings": 18, + "estimated_token_count_total": 5305 }, - "hash": "sha256:1f9ce923b3ce296571fe63837c0d3c3c791a339ef02db09ead6b2b92e9d1bfd5", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:fe651be49fe0a9ae899b2cbf9c663325f407718dc63f1d2c6a2dc4931be751fa", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-parachain-basics-blocks-transactions-fees-blocks", - "title": "Blocks", - "slug": "polkadot-protocol-parachain-basics-blocks-transactions-fees-blocks", + "id": "polkadot-protocol-smart-contract-basics-networks", + "title": "Networks for Polkadot Hub Smart Contracts", + "slug": "polkadot-protocol-smart-contract-basics-networks", "categories": [ "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-blocks-transactions-fees-blocks.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/blocks-transactions-fees/blocks/", - "preview": "In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/polkadot-protocol/parachain-basics/blocks-transactions-fees/transactions/){target=\\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and import", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-networks.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/networks/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -9285,551 +6977,509 @@ }, { "depth": 2, - "title": "What is a Block?", - "anchor": "what-is-a-block" + "title": "Network Overview", + "anchor": "network-overview" }, { "depth": 2, - "title": "Block Production", - "anchor": "block-production" + "title": "Local Development", + "anchor": "local-development" + }, + { + "depth": 2, + "title": "Test Networks", + "anchor": "test-networks" }, { "depth": 3, - "title": "Initialize Block", - "anchor": "initialize-block" + "title": "Passet Hub", + "anchor": "passet-hub" }, { "depth": 3, - "title": "Finalize Block", - "anchor": "finalize-block" + "title": "Westend Hub", + "anchor": "westend-hub" }, { "depth": 2, - "title": "Block Authoring and Import", - "anchor": "block-authoring-and-import" + "title": "Production Networks", + "anchor": "production-networks" }, { "depth": 3, - "title": "Block Import Queue", - "anchor": "block-import-queue" + "title": "Polkadot Hub", + "anchor": "polkadot-hub" }, { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "depth": 3, + "title": "Kusama Hub", + "anchor": "kusama-hub" } ], "stats": { - "chars": 6266, - "words": 912, - "headings": 8, - "estimated_token_count_total": 1399 + "chars": 5108, + "words": 696, + "headings": 9, + "estimated_token_count_total": 891 }, - "hash": "sha256:bcad23a74d962cab72b54cdc090bf9ee0cd5ecf79f70fb642f154668c2743983", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:b5acdc9acf0e44836b8a4518155eba7d16cc3b103c557a00970ffb1c44c3e9f6", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-parachain-basics-blocks-transactions-fees-fees", - "title": "Transactions Weights and Fees", - "slug": "polkadot-protocol-parachain-basics-blocks-transactions-fees-fees", + "id": "polkadot-protocol-smart-contract-basics-overview", + "title": "Smart Contracts Basics Overview", + "slug": "polkadot-protocol-smart-contract-basics-overview", "categories": [ "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-blocks-transactions-fees-fees.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/blocks-transactions-fees/fees/", - "preview": "When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop th", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-overview.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/overview/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, - "title": "Introductions", - "anchor": "introductions" - }, - { - "depth": 2, - "title": "How Fees are Calculated", - "anchor": "how-fees-are-calculated" - }, - { - "depth": 2, - "title": "Using the Transaction Payment Pallet", - "anchor": "using-the-transaction-payment-pallet" - }, - { - "depth": 3, - "title": "Understanding the Inclusion Fee", - "anchor": "understanding-the-inclusion-fee" - }, - { - "depth": 3, - "title": "Accounts with an Insufficient Balance", - "anchor": "accounts-with-an-insufficient-balance" - }, - { - "depth": 3, - "title": "Fee Multipliers", - "anchor": "fee-multipliers" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Transactions with Special Requirements", - "anchor": "transactions-with-special-requirements" + "title": "Smart Contracts Versus Parachains", + "anchor": "smart-contracts-versus-parachains" }, { "depth": 2, - "title": "Default Weight Annotations", - "anchor": "default-weight-annotations" + "title": "Building a Smart Contract", + "anchor": "building-a-smart-contract" }, { "depth": 3, - "title": "Weights and Database Read/Write Operations", - "anchor": "weights-and-database-readwrite-operations" + "title": "PolkaVM Contracts", + "anchor": "polkavm-contracts" }, { "depth": 3, - "title": "Dispatch Classes", - "anchor": "dispatch-classes" + "title": "EVM Contracts", + "anchor": "evm-contracts" }, { "depth": 3, - "title": "Dynamic Weights", - "anchor": "dynamic-weights" - }, + "title": "Wasm Contracts", + "anchor": "wasm-contracts" + } + ], + "stats": { + "chars": 10854, + "words": 1559, + "headings": 6, + "estimated_token_count_total": 2550 + }, + "hash": "sha256:5d293525ce81d27e32c26938a029a6a82b137221a0630d084f528853ffaf798e", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol-smart-contract-basics", + "title": "Smart Contract Basics", + "slug": "polkadot-protocol-smart-contract-basics", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Gain a deep understanding of smart contracts on Polkadot, from execution environments to transaction mechanics.", + "outline": [ { "depth": 2, - "title": "Post Dispatch Weight Correction", - "anchor": "post-dispatch-weight-correction" + "title": "Key Topics", + "anchor": "key-topics" }, { "depth": 2, - "title": "Custom Fees", - "anchor": "custom-fees" - }, - { - "depth": 3, - "title": "Custom Weights", - "anchor": "custom-weights" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 1110, + "words": 136, + "headings": 2, + "estimated_token_count_total": 148 + }, + "hash": "sha256:e8dac01e89b7aac4b887e962e91084c253f5ea25c1abc3a56355390d0c3201c8", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol", + "title": "Learn About the Polkadot Protocol", + "slug": "polkadot-protocol", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/", + "preview": "The Polkadot protocol is designed to enable scalable, secure, and interoperable networks. It introduces a unique multichain architecture that allows independent blockchains, known as parachains, to operate seamlessly while benefiting from the shared security of the relay chain. Polkadot’s decentralized governance ensures that network upgrades and decisions are community-driven, while its cross-chain messaging and interoperability features make it a hub for multichain applications.", + "outline": [ { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 20797, - "words": 2917, - "headings": 15, - "estimated_token_count_total": 4464 + "chars": 1170, + "words": 150, + "headings": 1, + "estimated_token_count_total": 12 }, - "hash": "sha256:299597c39d0e4e4902be8e45b354fff78a862aa5799e4f16d16787a97a1e3da8", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:49be4b4b5289572086eaaaf9ccff3bee7879b534188331c9a8052b3fe5aa4933", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-parachain-basics-blocks-transactions-fees-transactions", - "title": "Transactions", - "slug": "polkadot-protocol-parachain-basics-blocks-transactions-fees-transactions", + "id": "reference-glossary", + "title": "Glossary", + "slug": "reference-glossary", "categories": [ - "Basics", - "Polkadot Protocol" + "Reference" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-blocks-transactions-fees-transactions.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/blocks-transactions-fees/transactions/", - "preview": "Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md", + "html_url": "https://docs.polkadot.com/reference/glossary/", + "preview": "Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Authority", + "anchor": "authority" }, { "depth": 2, - "title": "What Is a Transaction?", - "anchor": "what-is-a-transaction" + "title": "Authority Round (Aura)", + "anchor": "authority-round-aura" + }, + { + "depth": 2, + "title": "Blind Assignment of Blockchain Extension (BABE)", + "anchor": "blind-assignment-of-blockchain-extension-babe" + }, + { + "depth": 2, + "title": "Block Author", + "anchor": "block-author" + }, + { + "depth": 2, + "title": "Byzantine Fault Tolerance (BFT)", + "anchor": "byzantine-fault-tolerance-bft" }, { "depth": 3, - "title": "Signed Transactions", - "anchor": "signed-transactions" + "title": "Byzantine Failure", + "anchor": "byzantine-failure" }, { "depth": 3, - "title": "Unsigned Transactions", - "anchor": "unsigned-transactions" + "title": "Practical Byzantine Fault Tolerance (pBFT)", + "anchor": "practical-byzantine-fault-tolerance-pbft" }, { "depth": 3, - "title": "Inherent Transactions", - "anchor": "inherent-transactions" + "title": "Preimage", + "anchor": "preimage" }, { "depth": 2, - "title": "Transaction Formats", - "anchor": "transaction-formats" + "title": "Call", + "anchor": "call" }, { - "depth": 3, - "title": "Types of Transaction Formats", - "anchor": "types-of-transaction-formats" + "depth": 2, + "title": "Chain Specification", + "anchor": "chain-specification" }, { - "depth": 3, - "title": "Signed Transaction Data Structure", - "anchor": "signed-transaction-data-structure" + "depth": 2, + "title": "Collator", + "anchor": "collator" }, { - "depth": 3, - "title": "Signed Extensions", - "anchor": "signed-extensions" + "depth": 2, + "title": "Collective", + "anchor": "collective" }, { "depth": 2, - "title": "Transaction Construction", - "anchor": "transaction-construction" + "title": "Consensus", + "anchor": "consensus" }, { - "depth": 3, - "title": "Construct a Signed Transaction", - "anchor": "construct-a-signed-transaction" + "depth": 2, + "title": "Consensus Algorithm", + "anchor": "consensus-algorithm" }, { - "depth": 3, - "title": "Transaction Encoding", - "anchor": "transaction-encoding" + "depth": 2, + "title": "Consensus Engine", + "anchor": "consensus-engine" }, { - "depth": 3, - "title": "Customize Transaction Construction", - "anchor": "customize-transaction-construction" + "depth": 2, + "title": "Coretime", + "anchor": "coretime" }, { "depth": 2, - "title": "Lifecycle of a Transaction", - "anchor": "lifecycle-of-a-transaction" + "title": "Development Phrase", + "anchor": "development-phrase" }, { - "depth": 3, - "title": "Define Transaction Properties", - "anchor": "define-transaction-properties" + "depth": 2, + "title": "Digest", + "anchor": "digest" }, { - "depth": 3, - "title": "Process on a Block Authoring Node", - "anchor": "process-on-a-block-authoring-node" + "depth": 2, + "title": "Dispatchable", + "anchor": "dispatchable" }, { - "depth": 3, - "title": "Validate and Queue", - "anchor": "validate-and-queue" + "depth": 2, + "title": "Events", + "anchor": "events" }, { - "depth": 3, - "title": "Transaction Ordering and Priority", - "anchor": "transaction-ordering-and-priority" + "depth": 2, + "title": "Executor", + "anchor": "executor" }, { - "depth": 3, - "title": "Transaction Execution", - "anchor": "transaction-execution" + "depth": 2, + "title": "Existential Deposit", + "anchor": "existential-deposit" }, { "depth": 2, - "title": "Transaction Mortality", - "anchor": "transaction-mortality" + "title": "Extrinsic", + "anchor": "extrinsic" }, { "depth": 2, - "title": "Unique Identifiers for Extrinsics", - "anchor": "unique-identifiers-for-extrinsics" + "title": "Fork Choice Rule/Strategy", + "anchor": "fork-choice-rulestrategy" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 23604, - "words": 3333, - "headings": 22, - "estimated_token_count_total": 4705 - }, - "hash": "sha256:6675634d4c5f274a7cc69802ee0a2d259e38efd5afd1c9dacc2d0fecfb370e4c", - "last_modified": "2025-10-28T14:15:59+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-parachain-basics-chain-data", - "title": "Chain Data", - "slug": "polkadot-protocol-parachain-basics-chain-data", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-chain-data.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/chain-data/", - "preview": "Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you", - "outline": [ + "title": "FRAME (Framework for Runtime Aggregation of Modularized Entities)", + "anchor": "frame-framework-for-runtime-aggregation-of-modularized-entities" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Full Node", + "anchor": "full-node" }, { "depth": 2, - "title": "Application Development", - "anchor": "application-development" + "title": "Genesis Configuration", + "anchor": "genesis-configuration" }, { "depth": 2, - "title": "Understand Metadata", - "anchor": "understand-metadata" + "title": "GRANDPA", + "anchor": "grandpa" }, { "depth": 2, - "title": "Expose Runtime Information as Metadata", - "anchor": "expose-runtime-information-as-metadata" + "title": "Header", + "anchor": "header" }, { "depth": 2, - "title": "Generate Metadata", - "anchor": "generate-metadata" + "title": "Hybrid Consensus", + "anchor": "hybrid-consensus" }, { "depth": 2, - "title": "Retrieve Runtime Metadata", - "anchor": "retrieve-runtime-metadata" + "title": "Inherent Transactions", + "anchor": "inherent-transactions" }, { - "depth": 3, - "title": "Use Polkadot.js", - "anchor": "use-polkadotjs" + "depth": 2, + "title": "JSON-RPC", + "anchor": "json-rpc" }, { - "depth": 3, - "title": "Use Curl", - "anchor": "use-curl" + "depth": 2, + "title": "Keystore", + "anchor": "keystore" }, { - "depth": 3, - "title": "Use Subxt", - "anchor": "use-subxt" + "depth": 2, + "title": "Kusama", + "anchor": "kusama" }, { "depth": 2, - "title": "Client Applications and Metadata", - "anchor": "client-applications-and-metadata" + "title": "libp2p", + "anchor": "libp2p" }, { "depth": 2, - "title": "Metadata Format", - "anchor": "metadata-format" + "title": "Light Client", + "anchor": "light-client" }, { - "depth": 3, - "title": "Pallets", - "anchor": "pallets" + "depth": 2, + "title": "Metadata", + "anchor": "metadata" }, { - "depth": 3, - "title": "Extrinsic", - "anchor": "extrinsic" + "depth": 2, + "title": "Nominated Proof of Stake (NPoS)", + "anchor": "nominated-proof-of-stake-npos" }, { "depth": 2, - "title": "Included RPC APIs", - "anchor": "included-rpc-apis" + "title": "Oracle", + "anchor": "oracle" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 18678, - "words": 2220, - "headings": 15, - "estimated_token_count_total": 3782 - }, - "hash": "sha256:eb4da21d561e9fd9333d97805318f0e263f54570120d3852ce7eba64da604cc2", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-parachain-basics-cryptography", - "title": "Cryptography", - "slug": "polkadot-protocol-parachain-basics-cryptography", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-cryptography.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/cryptography/", - "preview": "Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem.", - "outline": [ + "title": "Origin", + "anchor": "origin" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Pallet", + "anchor": "pallet" }, { "depth": 2, - "title": "Hash Functions", - "anchor": "hash-functions" + "title": "Parachain", + "anchor": "parachain" }, { - "depth": 3, - "title": "Key Properties of Hash Functions", - "anchor": "key-properties-of-hash-functions" + "depth": 2, + "title": "Paseo", + "anchor": "paseo" }, { - "depth": 3, - "title": "Blake2", - "anchor": "blake2" + "depth": 2, + "title": "Polkadot", + "anchor": "polkadot" }, { "depth": 2, - "title": "Types of Cryptography", - "anchor": "types-of-cryptography" + "title": "Polkadot Cloud", + "anchor": "polkadot-cloud" }, { - "depth": 3, - "title": "Symmetric Cryptography", - "anchor": "symmetric-cryptography" + "depth": 2, + "title": "Polkadot Hub", + "anchor": "polkadot-hub" }, { - "depth": 3, - "title": "Asymmetric Cryptography", - "anchor": "asymmetric-cryptography" + "depth": 2, + "title": "PolkaVM", + "anchor": "polkavm" }, { - "depth": 3, - "title": "Trade-offs and Compromises", - "anchor": "trade-offs-and-compromises" + "depth": 2, + "title": "Relay Chain", + "anchor": "relay-chain" }, { "depth": 2, - "title": "Digital Signatures", - "anchor": "digital-signatures" + "title": "Rococo", + "anchor": "rococo" }, { - "depth": 3, - "title": "Example of Creating a Digital Signature", - "anchor": "example-of-creating-a-digital-signature" + "depth": 2, + "title": "Runtime", + "anchor": "runtime" }, { "depth": 2, - "title": "Elliptic Curve", - "anchor": "elliptic-curve" + "title": "Slot", + "anchor": "slot" }, { - "depth": 3, - "title": "Various Implementations", - "anchor": "various-implementations" - } - ], - "stats": { - "chars": 8860, - "words": 1293, - "headings": 12, - "estimated_token_count_total": 1797 - }, - "hash": "sha256:259dcef86aadc513675258b665cc3940db65af6eb32a5db85da6ac339966fa60", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-parachain-basics-data-encoding", - "title": "Data Encoding", - "slug": "polkadot-protocol-parachain-basics-data-encoding", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-data-encoding.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/data-encoding/", - "preview": "The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data.", - "outline": [ + "depth": 2, + "title": "Sovereign Account", + "anchor": "sovereign-account" + }, + { + "depth": 2, + "title": "SS58 Address Format", + "anchor": "ss58-address-format" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "State Transition Function (STF)", + "anchor": "state-transition-function-stf" }, { "depth": 2, - "title": "SCALE Codec", - "anchor": "scale-codec" + "title": "Storage Item", + "anchor": "storage-item" }, { - "depth": 3, - "title": "Encode", - "anchor": "encode" + "depth": 2, + "title": "Substrate", + "anchor": "substrate" }, { - "depth": 3, - "title": "Decode", - "anchor": "decode" + "depth": 2, + "title": "Transaction", + "anchor": "transaction" }, { - "depth": 3, - "title": "CompactAs", - "anchor": "compactas" + "depth": 2, + "title": "Transaction Era", + "anchor": "transaction-era" }, { - "depth": 3, - "title": "HasCompact", - "anchor": "hascompact" + "depth": 2, + "title": "Trie (Patricia Merkle Tree)", + "anchor": "trie-patricia-merkle-tree" }, { - "depth": 3, - "title": "EncodeLike", - "anchor": "encodelike" + "depth": 2, + "title": "Validator", + "anchor": "validator" }, { - "depth": 3, - "title": "Data Types", - "anchor": "data-types" + "depth": 2, + "title": "WebAssembly (Wasm)", + "anchor": "webassembly-wasm" }, { "depth": 2, - "title": "Encode and Decode Rust Trait Implementations", - "anchor": "encode-and-decode-rust-trait-implementations" + "title": "Weight", + "anchor": "weight" }, { "depth": 2, - "title": "SCALE Codec Libraries", - "anchor": "scale-codec-libraries" + "title": "Westend", + "anchor": "westend" } ], "stats": { - "chars": 13629, - "words": 1314, - "headings": 10, - "estimated_token_count_total": 3213 + "chars": 24739, + "words": 3626, + "headings": 63, + "estimated_token_count_total": 5273 }, - "hash": "sha256:e448294b6e52291ac0add5fa6533572814e6cd27af42bdaccc2000b86f52d775", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:40bd67811e7eabc79ca5d105eae388b19380d9f035022da17fc0d6bb173c817c", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-parachain-basics-interoperability", - "title": "Interoperability", - "slug": "polkadot-protocol-parachain-basics-interoperability", + "id": "reference-governance-origins-tracks", + "title": "Origins and Tracks", + "slug": "reference-governance-origins-tracks", "categories": [ - "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-interoperability.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/interoperability/", - "preview": "Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance-origins-tracks.md", + "html_url": "https://docs.polkadot.com/reference/governance/origins-tracks/", + "preview": "Polkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency.", "outline": [ { "depth": 2, @@ -9838,58 +7488,40 @@ }, { "depth": 2, - "title": "Why Interoperability Matters", - "anchor": "why-interoperability-matters" - }, - { - "depth": 2, - "title": "Key Mechanisms for Interoperability", - "anchor": "key-mechanisms-for-interoperability" - }, - { - "depth": 3, - "title": "Cross-Consensus Messaging (XCM): The Backbone of Communication", - "anchor": "cross-consensus-messaging-xcm-the-backbone-of-communication" - }, - { - "depth": 3, - "title": "Bridges: Connecting External Networks", - "anchor": "bridges-connecting-external-networks" + "title": "Origins", + "anchor": "origins" }, { "depth": 2, - "title": "The Polkadot Advantage", - "anchor": "the-polkadot-advantage" + "title": "Tracks", + "anchor": "tracks" }, { "depth": 2, - "title": "Looking Ahead", - "anchor": "looking-ahead" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 4657, - "words": 588, - "headings": 7, - "estimated_token_count_total": 780 + "chars": 3333, + "words": 469, + "headings": 4, + "estimated_token_count_total": 631 }, - "hash": "sha256:077e7e5bfc9509cf09f455959a5da7a74b7af69836b3c4b334692f32e306ddf1", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:baba9dd41091b792d09005d55d3df0bf65b35f42b40ebe63caf425a0978a22b0", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-parachain-basics-networks", - "title": "Networks", - "slug": "polkadot-protocol-parachain-basics-networks", + "id": "reference-governance", + "title": "On-Chain Governance Overview", + "slug": "reference-governance", "categories": [ "Basics", - "Polkadot Protocol", - "Networks" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-networks.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/networks/", - "preview": "The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's va", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md", + "html_url": "https://docs.polkadot.com/reference/governance/", + "preview": "Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model.", "outline": [ { "depth": 2, @@ -9898,72 +7530,65 @@ }, { "depth": 2, - "title": "Network Overview", - "anchor": "network-overview" + "title": "Governance Evolution", + "anchor": "governance-evolution" }, { "depth": 2, - "title": "Polkadot Development Networks", - "anchor": "polkadot-development-networks" + "title": "OpenGov Key Features", + "anchor": "opengov-key-features" }, { "depth": 2, - "title": "Kusama Network", - "anchor": "kusama-network" + "title": "Origins and Tracks", + "anchor": "origins-and-tracks" }, { "depth": 2, - "title": "Test Networks", - "anchor": "test-networks" + "title": "Referendums", + "anchor": "referendums" }, { "depth": 3, - "title": "Westend", - "anchor": "westend" + "title": "Vote on Referendums", + "anchor": "vote-on-referendums" }, { "depth": 3, - "title": "Paseo", - "anchor": "paseo" - }, - { - "depth": 2, - "title": "Local Test Networks", - "anchor": "local-test-networks" + "title": "Delegate Voting Power", + "anchor": "delegate-voting-power" }, { "depth": 3, - "title": "Zombienet", - "anchor": "zombienet" + "title": "Cancel a Referendum", + "anchor": "cancel-a-referendum" }, { - "depth": 3, - "title": "Chopsticks", - "anchor": "chopsticks" + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 7834, - "words": 1111, - "headings": 10, - "estimated_token_count_total": 1473 + "chars": 7493, + "words": 1019, + "headings": 9, + "estimated_token_count_total": 1611 }, - "hash": "sha256:695c624a1d7a3ed6fea0f4f5c19bb2100be986cec29ba58edb4598b9e9b98494", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:62beec261e72529f70e07a641177d489d2c8872f9c9d618cbadf1ac0fd881986", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-parachain-basics-node-and-runtime", - "title": "Node and Runtime", - "slug": "polkadot-protocol-parachain-basics-node-and-runtime", + "id": "reference-parachains-accounts", + "title": "Polkadot SDK Accounts", + "slug": "reference-parachains-accounts", "categories": [ "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-node-and-runtime.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/node-and-runtime/", - "preview": "Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md", + "html_url": "https://docs.polkadot.com/reference/parachains/accounts/", + "preview": "Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains.", "outline": [ { "depth": 2, @@ -9972,72 +7597,95 @@ }, { "depth": 2, - "title": "Architectural Principles", - "anchor": "architectural-principles" + "title": "Account Data Structure", + "anchor": "account-data-structure" }, { "depth": 3, - "title": "Advantages of this Architecture", - "anchor": "advantages-of-this-architecture" + "title": "Account", + "anchor": "account" }, { - "depth": 2, - "title": "Node (Client)", - "anchor": "node-client" + "depth": 3, + "title": "Account Info", + "anchor": "account-info" + }, + { + "depth": 3, + "title": "Account Reference Counters", + "anchor": "account-reference-counters" }, { "depth": 2, - "title": "Runtime", - "anchor": "runtime" + "title": "Account Balance Types", + "anchor": "account-balance-types" }, { "depth": 3, - "title": "Characteristics", - "anchor": "characteristics" + "title": "Balance Types", + "anchor": "balance-types" }, { "depth": 3, - "title": "Key Functions", - "anchor": "key-functions" + "title": "Locks", + "anchor": "locks" + }, + { + "depth": 3, + "title": "Balance Types on Polkadot.js", + "anchor": "balance-types-on-polkadotjs" }, { "depth": 2, - "title": "Communication Between Node and Runtime", - "anchor": "communication-between-node-and-runtime" + "title": "Address Formats", + "anchor": "address-formats" }, { "depth": 3, - "title": "Runtime APIs", - "anchor": "runtime-apis" + "title": "Basic Format", + "anchor": "basic-format" }, { "depth": 3, - "title": "Host Functions", - "anchor": "host-functions" + "title": "Address Type", + "anchor": "address-type" + }, + { + "depth": 3, + "title": "Address Length", + "anchor": "address-length" + }, + { + "depth": 3, + "title": "Checksum Types", + "anchor": "checksum-types" + }, + { + "depth": 3, + "title": "Validating Addresses", + "anchor": "validating-addresses" } ], "stats": { - "chars": 4937, - "words": 628, - "headings": 10, - "estimated_token_count_total": 914 + "chars": 29604, + "words": 4194, + "headings": 15, + "estimated_token_count_total": 6507 }, - "hash": "sha256:8122e21c149d0863cfe3b37fc5606bcdb91668e9d265f0f05451a61ff70e4e93", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:0104a9132a69345a2faac37fca0e2853a2ded1efb009511a83a98d44509ab887", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-parachain-basics-randomness", - "title": "Randomness", - "slug": "polkadot-protocol-parachain-basics-randomness", + "id": "reference-parachains-blocks-transactions-fees-blocks", + "title": "Blocks", + "slug": "reference-parachains-blocks-transactions-fees-blocks", "categories": [ "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-randomness.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/randomness/", - "preview": "Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as \"random\" numbers on a computer are actually pseudo-random. These numbers rely on an initial \"seed,\" which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\\_blank}, [heart rates](https://m", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md", + "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/", + "preview": "In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the", "outline": [ { "depth": 2, @@ -10046,23 +7694,33 @@ }, { "depth": 2, - "title": "VRF", - "anchor": "vrf" + "title": "What is a Block?", + "anchor": "what-is-a-block" + }, + { + "depth": 2, + "title": "Block Production", + "anchor": "block-production" }, { "depth": 3, - "title": "How VRF Works", - "anchor": "how-vrf-works" + "title": "Initialize Block", + "anchor": "initialize-block" }, { - "depth": 2, - "title": "RANDAO", - "anchor": "randao" + "depth": 3, + "title": "Finalize Block", + "anchor": "finalize-block" }, { "depth": 2, - "title": "VDFs", - "anchor": "vdfs" + "title": "Block Authoring and Import", + "anchor": "block-authoring-and-import" + }, + { + "depth": 3, + "title": "Block Import Queue", + "anchor": "block-import-queue" }, { "depth": 2, @@ -10071,160 +7729,122 @@ } ], "stats": { - "chars": 6541, - "words": 1008, - "headings": 6, - "estimated_token_count_total": 1394 + "chars": 6252, + "words": 910, + "headings": 8, + "estimated_token_count_total": 1395 }, - "hash": "sha256:217a79109aff1607594a0238fd91bfa812827620887c4f063c7e0a7a37f967d6", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:424783c102bea5dae5b8749635858c6c59055563442a98f57521f0027dafa8d3", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-smart-contract-basics-accounts", - "title": "Accounts in Asset Hub Smart Contracts", - "slug": "polkadot-protocol-smart-contract-basics-accounts", + "id": "reference-parachains-blocks-transactions-fees-fees", + "title": "Transactions Weights and Fees", + "slug": "reference-parachains-blocks-transactions-fees-fees", "categories": [ "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-accounts.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/accounts/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md", + "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/", + "preview": "When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop th", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Introductions", + "anchor": "introductions" }, { "depth": 2, - "title": "Address Types and Mappings", - "anchor": "address-types-and-mappings" + "title": "How Fees are Calculated", + "anchor": "how-fees-are-calculated" }, { - "depth": 3, - "title": "Ethereum to Polkadot Mapping", - "anchor": "ethereum-to-polkadot-mapping" + "depth": 2, + "title": "Using the Transaction Payment Pallet", + "anchor": "using-the-transaction-payment-pallet" }, { "depth": 3, - "title": "Polkadot to Ethereum Mapping", - "anchor": "polkadot-to-ethereum-mapping" + "title": "Understanding the Inclusion Fee", + "anchor": "understanding-the-inclusion-fee" }, { "depth": 3, - "title": "Account Mapping for Native Polkadot Accounts", - "anchor": "account-mapping-for-native-polkadot-accounts" - }, - { - "depth": 2, - "title": "Account Registration", - "anchor": "account-registration" + "title": "Accounts with an Insufficient Balance", + "anchor": "accounts-with-an-insufficient-balance" }, { - "depth": 2, - "title": "Fallback Accounts", - "anchor": "fallback-accounts" + "depth": 3, + "title": "Fee Multipliers", + "anchor": "fee-multipliers" }, { "depth": 2, - "title": "Contract Address Generation", - "anchor": "contract-address-generation" + "title": "Transactions with Special Requirements", + "anchor": "transactions-with-special-requirements" }, { "depth": 2, - "title": "Security Considerations", - "anchor": "security-considerations" - } - ], - "stats": { - "chars": 8538, - "words": 1141, - "headings": 9, - "estimated_token_count_total": 1822 - }, - "hash": "sha256:db2b1806153242680043ced536f64fc8a2ed3c09adc1bec5aa287168b48e0994", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-smart-contract-basics-blocks-transactions-fees", - "title": "Transactions and Fees on Asset Hub", - "slug": "polkadot-protocol-smart-contract-basics-blocks-transactions-fees", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-blocks-transactions-fees.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/blocks-transactions-fees/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Default Weight Annotations", + "anchor": "default-weight-annotations" }, { - "depth": 2, - "title": "Smart Contract Blocks", - "anchor": "smart-contract-blocks" + "depth": 3, + "title": "Weights and Database Read/Write Operations", + "anchor": "weights-and-database-readwrite-operations" }, { - "depth": 2, - "title": "Smart Contract Transactions", - "anchor": "smart-contract-transactions" + "depth": 3, + "title": "Dispatch Classes", + "anchor": "dispatch-classes" }, { "depth": 3, - "title": "EVM Transaction Types", - "anchor": "evm-transaction-types" + "title": "Dynamic Weights", + "anchor": "dynamic-weights" }, { "depth": 2, - "title": "Fees and Gas", - "anchor": "fees-and-gas" + "title": "Post Dispatch Weight Correction", + "anchor": "post-dispatch-weight-correction" }, { - "depth": 3, - "title": "Gas Model Overview", - "anchor": "gas-model-overview" + "depth": 2, + "title": "Custom Fees", + "anchor": "custom-fees" }, { "depth": 3, - "title": "Fee Components", - "anchor": "fee-components" + "title": "Custom Weights", + "anchor": "custom-weights" }, { - "depth": 3, - "title": "Gas Calculation and Conversion", - "anchor": "gas-calculation-and-conversion" + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 6361, - "words": 789, - "headings": 8, - "estimated_token_count_total": 1178 + "chars": 20800, + "words": 2917, + "headings": 15, + "estimated_token_count_total": 4464 }, - "hash": "sha256:9a6b3fa6c005d75c25f0f683b7d8c3b65891454743b794c12b005f910b81609c", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:7d0c3fa7982b3e1843adb8f27422456397580b3a3eba5047b381da8517742536", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-smart-contract-basics-evm-vs-polkavm", - "title": "EVM vs PolkaVM", - "slug": "polkadot-protocol-smart-contract-basics-evm-vs-polkavm", + "id": "reference-parachains-blocks-transactions-fees-transactions", + "title": "Transactions", + "slug": "reference-parachains-blocks-transactions-fees-transactions", "categories": [ "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-evm-vs-polkavm.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md", + "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/", + "preview": "Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions.", "outline": [ { "depth": 2, @@ -10233,179 +7853,246 @@ }, { "depth": 2, - "title": "Core Virtual Machine Architecture", - "anchor": "core-virtual-machine-architecture" + "title": "What Is a Transaction?", + "anchor": "what-is-a-transaction" }, { "depth": 3, - "title": "High-Level Architecture Comparison", - "anchor": "high-level-architecture-comparison" + "title": "Signed Transactions", + "anchor": "signed-transactions" }, { - "depth": 2, - "title": "Gas Model", - "anchor": "gas-model" + "depth": 3, + "title": "Unsigned Transactions", + "anchor": "unsigned-transactions" }, { "depth": 3, - "title": "Dynamic Gas Value Scaling", - "anchor": "dynamic-gas-value-scaling" + "title": "Inherent Transactions", + "anchor": "inherent-transactions" + }, + { + "depth": 2, + "title": "Transaction Formats", + "anchor": "transaction-formats" }, { "depth": 3, - "title": "Multi-Dimensional Resource Metering", - "anchor": "multi-dimensional-resource-metering" + "title": "Types of Transaction Formats", + "anchor": "types-of-transaction-formats" }, { - "depth": 2, - "title": "Memory Management", - "anchor": "memory-management" + "depth": 3, + "title": "Signed Transaction Data Structure", + "anchor": "signed-transaction-data-structure" }, { "depth": 3, - "title": "Current Memory Limits", - "anchor": "current-memory-limits" + "title": "Signed Extensions", + "anchor": "signed-extensions" }, { "depth": 2, - "title": "Account Management - Existential Deposit", - "anchor": "account-management-existential-deposit" + "title": "Transaction Construction", + "anchor": "transaction-construction" }, { "depth": 3, - "title": "Account Management Comparison", - "anchor": "account-management-comparison" + "title": "Construct a Signed Transaction", + "anchor": "construct-a-signed-transaction" }, { - "depth": 2, - "title": "Contract Deployment", - "anchor": "contract-deployment" + "depth": 3, + "title": "Transaction Encoding", + "anchor": "transaction-encoding" + }, + { + "depth": 3, + "title": "Customize Transaction Construction", + "anchor": "customize-transaction-construction" }, { "depth": 2, - "title": "Solidity and YUL IR Translation Incompatibilities", - "anchor": "solidity-and-yul-ir-translation-incompatibilities" + "title": "Lifecycle of a Transaction", + "anchor": "lifecycle-of-a-transaction" }, { "depth": 3, - "title": "Contract Code Structure", - "anchor": "contract-code-structure" + "title": "Define Transaction Properties", + "anchor": "define-transaction-properties" }, { "depth": 3, - "title": "Solidity-Specific Differences", - "anchor": "solidity-specific-differences" + "title": "Process on a Block Authoring Node", + "anchor": "process-on-a-block-authoring-node" }, { "depth": 3, - "title": "YUL Function Translation Differences", - "anchor": "yul-function-translation-differences" + "title": "Validate and Queue", + "anchor": "validate-and-queue" }, { "depth": 3, - "title": "Unsupported Operations", - "anchor": "unsupported-operations" + "title": "Transaction Ordering and Priority", + "anchor": "transaction-ordering-and-priority" }, { "depth": 3, - "title": "Compilation Pipeline Considerations", - "anchor": "compilation-pipeline-considerations" + "title": "Transaction Execution", + "anchor": "transaction-execution" }, { - "depth": 3, - "title": "Memory Pointer Limitations", - "anchor": "memory-pointer-limitations" + "depth": 2, + "title": "Transaction Mortality", + "anchor": "transaction-mortality" + }, + { + "depth": 2, + "title": "Unique Identifiers for Extrinsics", + "anchor": "unique-identifiers-for-extrinsics" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 27673, - "words": 3392, - "headings": 18, - "estimated_token_count_total": 5305 + "chars": 23610, + "words": 3333, + "headings": 22, + "estimated_token_count_total": 4708 }, - "hash": "sha256:fe651be49fe0a9ae899b2cbf9c663325f407718dc63f1d2c6a2dc4931be751fa", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:66726634d3a51cd9c471621054a6e5f09c8061dca6144b64c8bcf45626359617", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-smart-contract-basics-networks", - "title": "Networks for Polkadot Hub Smart Contracts", - "slug": "polkadot-protocol-smart-contract-basics-networks", + "id": "reference-parachains-chain-data", + "title": "Chain Data", + "slug": "reference-parachains-chain-data", "categories": [ "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-networks.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/networks/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md", + "html_url": "https://docs.polkadot.com/reference/parachains/chain-data/", + "preview": "Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Application Development", + "anchor": "application-development" + }, + { + "depth": 2, + "title": "Understand Metadata", + "anchor": "understand-metadata" }, { "depth": 2, - "title": "Network Overview", - "anchor": "network-overview" + "title": "Expose Runtime Information as Metadata", + "anchor": "expose-runtime-information-as-metadata" }, { "depth": 2, - "title": "Local Development", - "anchor": "local-development" + "title": "Generate Metadata", + "anchor": "generate-metadata" }, { "depth": 2, - "title": "Test Networks", - "anchor": "test-networks" + "title": "Retrieve Runtime Metadata", + "anchor": "retrieve-runtime-metadata" }, { "depth": 3, - "title": "Passet Hub", - "anchor": "passet-hub" + "title": "Use Polkadot.js", + "anchor": "use-polkadotjs" }, { "depth": 3, - "title": "Westend Hub", - "anchor": "westend-hub" + "title": "Use Curl", + "anchor": "use-curl" + }, + { + "depth": 3, + "title": "Use Subxt", + "anchor": "use-subxt" }, { "depth": 2, - "title": "Production Networks", - "anchor": "production-networks" + "title": "Client Applications and Metadata", + "anchor": "client-applications-and-metadata" + }, + { + "depth": 2, + "title": "Metadata Format", + "anchor": "metadata-format" }, { "depth": 3, - "title": "Polkadot Hub", - "anchor": "polkadot-hub" + "title": "Pallets", + "anchor": "pallets" }, { "depth": 3, - "title": "Kusama Hub", - "anchor": "kusama-hub" + "title": "Extrinsic", + "anchor": "extrinsic" + }, + { + "depth": 2, + "title": "Included RPC APIs", + "anchor": "included-rpc-apis" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 5108, - "words": 696, - "headings": 9, - "estimated_token_count_total": 891 + "chars": 18650, + "words": 2216, + "headings": 15, + "estimated_token_count_total": 3774 }, - "hash": "sha256:b5acdc9acf0e44836b8a4518155eba7d16cc3b103c557a00970ffb1c44c3e9f6", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:49238d1e9e2c33e0fcd3a84b5e30f0d3840d7d23a783b538875e0a23f38efc1d", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-smart-contract-basics-overview", - "title": "Smart Contracts Basics Overview", - "slug": "polkadot-protocol-smart-contract-basics-overview", + "id": "reference-parachains-consensus-async-backing", + "title": "reference-parachains-consensus-async-backing", + "slug": "reference-parachains-consensus-async-backing", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-async-backing.md", + "html_url": "https://docs.polkadot.com/reference/parachains/consensus/async-backing/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-consensus-elastic-scaling", + "title": "Elastic Scaling", + "slug": "reference-parachains-consensus-elastic-scaling", "categories": [ - "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-overview.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/overview/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-elastic-scaling.md", + "html_url": "https://docs.polkadot.com/reference/parachains/consensus/elastic-scaling/", + "preview": "Polkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains.", "outline": [ { "depth": 2, @@ -10414,354 +8101,384 @@ }, { "depth": 2, - "title": "Smart Contracts Versus Parachains", - "anchor": "smart-contracts-versus-parachains" + "title": "How Elastic Scaling Works", + "anchor": "how-elastic-scaling-works" }, { "depth": 2, - "title": "Building a Smart Contract", - "anchor": "building-a-smart-contract" + "title": "Benefits of Elastic Scaling", + "anchor": "benefits-of-elastic-scaling" }, { - "depth": 3, - "title": "PolkaVM Contracts", - "anchor": "polkavm-contracts" + "depth": 2, + "title": "Use Cases", + "anchor": "use-cases" }, { "depth": 3, - "title": "EVM Contracts", - "anchor": "evm-contracts" + "title": "Handling Sudden Traffic Spikes", + "anchor": "handling-sudden-traffic-spikes" }, { "depth": 3, - "title": "Wasm Contracts", - "anchor": "wasm-contracts" - } - ], - "stats": { - "chars": 10854, - "words": 1559, - "headings": 6, - "estimated_token_count_total": 2550 - }, - "hash": "sha256:e2cf14bcb483308f73a80c8e8871ce1a86fa694576d2e6e51beafc24488f4d58", - "last_modified": "2025-10-28T14:42:15+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-smart-contract-basics", - "title": "Smart Contract Basics", - "slug": "polkadot-protocol-smart-contract-basics", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Gain a deep understanding of smart contracts on Polkadot, from execution environments to transaction mechanics.", - "outline": [ + "title": "Supporting Early-Stage Growth", + "anchor": "supporting-early-stage-growth" + }, { - "depth": 2, - "title": "Key Topics", - "anchor": "key-topics" + "depth": 3, + "title": "Scaling Massive IoT Networks", + "anchor": "scaling-massive-iot-networks" }, { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "depth": 3, + "title": "Powering Real-Time, Low-Latency Systems", + "anchor": "powering-real-time-low-latency-systems" } ], "stats": { - "chars": 1110, - "words": 136, - "headings": 2, - "estimated_token_count_total": 148 + "chars": 7871, + "words": 1047, + "headings": 8, + "estimated_token_count_total": 1440 }, - "hash": "sha256:e8dac01e89b7aac4b887e962e91084c253f5ea25c1abc3a56355390d0c3201c8", + "hash": "sha256:2d228c52844df8952520fafdd3e6f0e26bfd2f32b5ee60c6241cf7d38603643c", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol", - "title": "Learn About the Polkadot Protocol", - "slug": "polkadot-protocol", + "id": "reference-parachains-consensus", + "title": "reference-parachains-consensus", + "slug": "reference-parachains-consensus", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/", - "preview": "The Polkadot protocol is designed to enable scalable, secure, and interoperable networks. It introduces a unique multichain architecture that allows independent blockchains, known as parachains, to operate seamlessly while benefiting from the shared security of the relay chain. Polkadot’s decentralized governance ensures that network upgrades and decisions are community-driven, while its cross-chain messaging and interoperability features make it a hub for multichain applications.", - "outline": [ - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus.md", + "html_url": "https://docs.polkadot.com/reference/parachains/consensus/", + "preview": "TODO", + "outline": [], "stats": { - "chars": 1170, - "words": 150, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 }, - "hash": "sha256:6992c9a2d1b315b64d9782880105cf2d436750249a84577aceb95cc213863009", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", "token_estimator": "heuristic-v1" }, { - "id": "reference-glossary", - "title": "Glossary", - "slug": "reference-glossary", + "id": "reference-parachains-cryptography", + "title": "Cryptography", + "slug": "reference-parachains-cryptography", "categories": [ - "Reference" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md", - "html_url": "https://docs.polkadot.com/reference/glossary/", - "preview": "Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md", + "html_url": "https://docs.polkadot.com/reference/parachains/cryptography/", + "preview": "Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem.", "outline": [ { "depth": 2, - "title": "Authority", - "anchor": "authority" - }, - { - "depth": 2, - "title": "Authority Round (Aura)", - "anchor": "authority-round-aura" - }, - { - "depth": 2, - "title": "Blind Assignment of Blockchain Extension (BABE)", - "anchor": "blind-assignment-of-blockchain-extension-babe" - }, - { - "depth": 2, - "title": "Block Author", - "anchor": "block-author" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Byzantine Fault Tolerance (BFT)", - "anchor": "byzantine-fault-tolerance-bft" - }, - { - "depth": 3, - "title": "Byzantine Failure", - "anchor": "byzantine-failure" + "title": "Hash Functions", + "anchor": "hash-functions" }, { "depth": 3, - "title": "Practical Byzantine Fault Tolerance (pBFT)", - "anchor": "practical-byzantine-fault-tolerance-pbft" + "title": "Key Properties of Hash Functions", + "anchor": "key-properties-of-hash-functions" }, { "depth": 3, - "title": "Preimage", - "anchor": "preimage" - }, - { - "depth": 2, - "title": "Call", - "anchor": "call" - }, - { - "depth": 2, - "title": "Chain Specification", - "anchor": "chain-specification" - }, - { - "depth": 2, - "title": "Collator", - "anchor": "collator" + "title": "Blake2", + "anchor": "blake2" }, { "depth": 2, - "title": "Collective", - "anchor": "collective" + "title": "Types of Cryptography", + "anchor": "types-of-cryptography" }, { - "depth": 2, - "title": "Consensus", - "anchor": "consensus" + "depth": 3, + "title": "Symmetric Cryptography", + "anchor": "symmetric-cryptography" }, { - "depth": 2, - "title": "Consensus Algorithm", - "anchor": "consensus-algorithm" + "depth": 3, + "title": "Asymmetric Cryptography", + "anchor": "asymmetric-cryptography" }, { - "depth": 2, - "title": "Consensus Engine", - "anchor": "consensus-engine" + "depth": 3, + "title": "Trade-offs and Compromises", + "anchor": "trade-offs-and-compromises" }, { "depth": 2, - "title": "Coretime", - "anchor": "coretime" + "title": "Digital Signatures", + "anchor": "digital-signatures" }, { - "depth": 2, - "title": "Development Phrase", - "anchor": "development-phrase" + "depth": 3, + "title": "Example of Creating a Digital Signature", + "anchor": "example-of-creating-a-digital-signature" }, { "depth": 2, - "title": "Digest", - "anchor": "digest" + "title": "Elliptic Curve", + "anchor": "elliptic-curve" }, { - "depth": 2, - "title": "Dispatchable", - "anchor": "dispatchable" - }, + "depth": 3, + "title": "Various Implementations", + "anchor": "various-implementations" + } + ], + "stats": { + "chars": 8860, + "words": 1293, + "headings": 12, + "estimated_token_count_total": 1797 + }, + "hash": "sha256:259dcef86aadc513675258b665cc3940db65af6eb32a5db85da6ac339966fa60", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-data-encoding", + "title": "Data Encoding", + "slug": "reference-parachains-data-encoding", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md", + "html_url": "https://docs.polkadot.com/reference/parachains/data-encoding/", + "preview": "The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data.", + "outline": [ { "depth": 2, - "title": "Events", - "anchor": "events" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Executor", - "anchor": "executor" + "title": "SCALE Codec", + "anchor": "scale-codec" }, { - "depth": 2, - "title": "Existential Deposit", - "anchor": "existential-deposit" + "depth": 3, + "title": "Encode", + "anchor": "encode" }, { - "depth": 2, - "title": "Extrinsic", - "anchor": "extrinsic" + "depth": 3, + "title": "Decode", + "anchor": "decode" }, { - "depth": 2, - "title": "Fork Choice Rule/Strategy", - "anchor": "fork-choice-rulestrategy" + "depth": 3, + "title": "CompactAs", + "anchor": "compactas" }, { - "depth": 2, - "title": "FRAME (Framework for Runtime Aggregation of Modularized Entities)", - "anchor": "frame-framework-for-runtime-aggregation-of-modularized-entities" + "depth": 3, + "title": "HasCompact", + "anchor": "hascompact" }, { - "depth": 2, - "title": "Full Node", - "anchor": "full-node" + "depth": 3, + "title": "EncodeLike", + "anchor": "encodelike" }, { - "depth": 2, - "title": "Genesis Configuration", - "anchor": "genesis-configuration" + "depth": 3, + "title": "Data Types", + "anchor": "data-types" }, { "depth": 2, - "title": "GRANDPA", - "anchor": "grandpa" + "title": "Encode and Decode Rust Trait Implementations", + "anchor": "encode-and-decode-rust-trait-implementations" }, { "depth": 2, - "title": "Header", - "anchor": "header" - }, + "title": "SCALE Codec Libraries", + "anchor": "scale-codec-libraries" + } + ], + "stats": { + "chars": 13629, + "words": 1314, + "headings": 10, + "estimated_token_count_total": 3213 + }, + "hash": "sha256:e448294b6e52291ac0add5fa6533572814e6cd27af42bdaccc2000b86f52d775", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-interoperability", + "title": "Interoperability", + "slug": "reference-parachains-interoperability", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md", + "html_url": "https://docs.polkadot.com/reference/parachains/interoperability/", + "preview": "Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions.", + "outline": [ { "depth": 2, - "title": "Hybrid Consensus", - "anchor": "hybrid-consensus" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Inherent Transactions", - "anchor": "inherent-transactions" + "title": "Why Interoperability Matters", + "anchor": "why-interoperability-matters" }, { "depth": 2, - "title": "JSON-RPC", - "anchor": "json-rpc" + "title": "Key Mechanisms for Interoperability", + "anchor": "key-mechanisms-for-interoperability" }, { - "depth": 2, - "title": "Keystore", - "anchor": "keystore" + "depth": 3, + "title": "Cross-Consensus Messaging (XCM): The Backbone of Communication", + "anchor": "cross-consensus-messaging-xcm-the-backbone-of-communication" }, { - "depth": 2, - "title": "Kusama", - "anchor": "kusama" + "depth": 3, + "title": "Bridges: Connecting External Networks", + "anchor": "bridges-connecting-external-networks" }, { "depth": 2, - "title": "libp2p", - "anchor": "libp2p" + "title": "The Polkadot Advantage", + "anchor": "the-polkadot-advantage" }, { "depth": 2, - "title": "Light Client", - "anchor": "light-client" - }, + "title": "Looking Ahead", + "anchor": "looking-ahead" + } + ], + "stats": { + "chars": 4635, + "words": 584, + "headings": 7, + "estimated_token_count_total": 772 + }, + "hash": "sha256:11bb4f113bdda5852a3115e64d5ba47f8eccd4e3619a05ad960ab3a541f31346", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-networks", + "title": "Networks", + "slug": "reference-parachains-networks", + "categories": [ + "Basics", + "Polkadot Protocol", + "Networks" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md", + "html_url": "https://docs.polkadot.com/reference/parachains/networks/", + "preview": "The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's va", + "outline": [ { "depth": 2, - "title": "Metadata", - "anchor": "metadata" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Nominated Proof of Stake (NPoS)", - "anchor": "nominated-proof-of-stake-npos" + "title": "Network Overview", + "anchor": "network-overview" }, { "depth": 2, - "title": "Oracle", - "anchor": "oracle" + "title": "Polkadot Development Networks", + "anchor": "polkadot-development-networks" }, { "depth": 2, - "title": "Origin", - "anchor": "origin" + "title": "Kusama Network", + "anchor": "kusama-network" }, { "depth": 2, - "title": "Pallet", - "anchor": "pallet" + "title": "Test Networks", + "anchor": "test-networks" }, { - "depth": 2, - "title": "Parachain", - "anchor": "parachain" + "depth": 3, + "title": "Westend", + "anchor": "westend" }, { - "depth": 2, + "depth": 3, "title": "Paseo", "anchor": "paseo" }, { "depth": 2, - "title": "Polkadot", - "anchor": "polkadot" + "title": "Local Test Networks", + "anchor": "local-test-networks" }, { - "depth": 2, - "title": "Polkadot Cloud", - "anchor": "polkadot-cloud" + "depth": 3, + "title": "Zombienet", + "anchor": "zombienet" }, + { + "depth": 3, + "title": "Chopsticks", + "anchor": "chopsticks" + } + ], + "stats": { + "chars": 7834, + "words": 1111, + "headings": 10, + "estimated_token_count_total": 1473 + }, + "hash": "sha256:e49e063a2cc0fb5a48c6cdc3de266bb6e025a006940fea8e90cc4d5f9884900f", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-node-and-runtime", + "title": "Node and Runtime", + "slug": "reference-parachains-node-and-runtime", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md", + "html_url": "https://docs.polkadot.com/reference/parachains/node-and-runtime/", + "preview": "Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network.", + "outline": [ { "depth": 2, - "title": "Polkadot Hub", - "anchor": "polkadot-hub" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "PolkaVM", - "anchor": "polkavm" + "title": "Architectural Principles", + "anchor": "architectural-principles" }, { - "depth": 2, - "title": "Relay Chain", - "anchor": "relay-chain" + "depth": 3, + "title": "Advantages of this Architecture", + "anchor": "advantages-of-this-architecture" }, { "depth": 2, - "title": "Rococo", - "anchor": "rococo" + "title": "Node (Client)", + "anchor": "node-client" }, { "depth": 2, @@ -10769,91 +8486,103 @@ "anchor": "runtime" }, { - "depth": 2, - "title": "Slot", - "anchor": "slot" - }, - { - "depth": 2, - "title": "Sovereign Account", - "anchor": "sovereign-account" - }, - { - "depth": 2, - "title": "SS58 Address Format", - "anchor": "ss58-address-format" + "depth": 3, + "title": "Characteristics", + "anchor": "characteristics" }, { - "depth": 2, - "title": "State Transition Function (STF)", - "anchor": "state-transition-function-stf" + "depth": 3, + "title": "Key Functions", + "anchor": "key-functions" }, { "depth": 2, - "title": "Storage Item", - "anchor": "storage-item" + "title": "Communication Between Node and Runtime", + "anchor": "communication-between-node-and-runtime" }, { - "depth": 2, - "title": "Substrate", - "anchor": "substrate" + "depth": 3, + "title": "Runtime APIs", + "anchor": "runtime-apis" }, { - "depth": 2, - "title": "Transaction", - "anchor": "transaction" - }, + "depth": 3, + "title": "Host Functions", + "anchor": "host-functions" + } + ], + "stats": { + "chars": 4937, + "words": 628, + "headings": 10, + "estimated_token_count_total": 914 + }, + "hash": "sha256:8122e21c149d0863cfe3b37fc5606bcdb91668e9d265f0f05451a61ff70e4e93", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-randomness", + "title": "Randomness", + "slug": "reference-parachains-randomness", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md", + "html_url": "https://docs.polkadot.com/reference/parachains/randomness/", + "preview": "Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as \"random\" numbers on a computer are actually pseudo-random. These numbers rely on an initial \"seed,\" which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\\_blank}, [heart rates](https://m", + "outline": [ { "depth": 2, - "title": "Transaction Era", - "anchor": "transaction-era" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Trie (Patricia Merkle Tree)", - "anchor": "trie-patricia-merkle-tree" + "title": "VRF", + "anchor": "vrf" }, { - "depth": 2, - "title": "Validator", - "anchor": "validator" + "depth": 3, + "title": "How VRF Works", + "anchor": "how-vrf-works" }, { "depth": 2, - "title": "WebAssembly (Wasm)", - "anchor": "webassembly-wasm" + "title": "RANDAO", + "anchor": "randao" }, { "depth": 2, - "title": "Weight", - "anchor": "weight" + "title": "VDFs", + "anchor": "vdfs" }, { "depth": 2, - "title": "Westend", - "anchor": "westend" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 24739, - "words": 3626, - "headings": 63, - "estimated_token_count_total": 5273 + "chars": 6503, + "words": 1005, + "headings": 6, + "estimated_token_count_total": 1388 }, - "hash": "sha256:40bd67811e7eabc79ca5d105eae388b19380d9f035022da17fc0d6bb173c817c", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:c7d8a5a4263fd21af458ab0bd102377104affdf2431b4fe74eeff4ebe62a4a81", "token_estimator": "heuristic-v1" }, { - "id": "reference-governance-origins-tracks", - "title": "Origins and Tracks", - "slug": "reference-governance-origins-tracks", + "id": "reference-parachains", + "title": "Parachains Overview", + "slug": "reference-parachains", "categories": [ - "Polkadot Protocol" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance-origins-tracks.md", - "html_url": "https://docs.polkadot.com/reference/governance/origins-tracks/", - "preview": "Polkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md", + "html_url": "https://docs.polkadot.com/reference/parachains/", + "preview": "A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network.", "outline": [ { "depth": 2, @@ -10862,41 +8591,49 @@ }, { "depth": 2, - "title": "Origins", - "anchor": "origins" + "title": "Polkadot SDK: Parachain Architecture", + "anchor": "polkadot-sdk-parachain-architecture" }, { - "depth": 2, - "title": "Tracks", - "anchor": "tracks" + "depth": 3, + "title": "Substrate: The Foundation", + "anchor": "substrate-the-foundation" + }, + { + "depth": 3, + "title": "FRAME: Building Blocks for Your Runtime", + "anchor": "frame-building-blocks-for-your-runtime" + }, + { + "depth": 3, + "title": "Cumulus: Parachain-Specific Functionality", + "anchor": "cumulus-parachain-specific-functionality" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 3333, - "words": 469, - "headings": 4, - "estimated_token_count_total": 631 + "chars": 8495, + "words": 1029, + "headings": 6, + "estimated_token_count_total": 1759 }, - "hash": "sha256:baba9dd41091b792d09005d55d3df0bf65b35f42b40ebe63caf425a0978a22b0", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:ecb0d9459e08920db7d2d59dc7c01aba7a91ce8c9e39256bd0c3efa473dbaa17", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-accounts", - "title": "Polkadot SDK Accounts", - "slug": "reference-parachains-accounts", + "id": "reference-polkadot-hub-assets-and-smart-contracts", + "title": "Asset Hub", + "slug": "reference-polkadot-hub-assets-and-smart-contracts", "categories": [ - "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md", - "html_url": "https://docs.polkadot.com/reference/parachains/accounts/", - "preview": "Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/assets-and-smart-contracts/", + "preview": "The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integra", "outline": [ { "depth": 2, @@ -10905,96 +8642,129 @@ }, { "depth": 2, - "title": "Account Data Structure", - "anchor": "account-data-structure" + "title": "Assets Basics", + "anchor": "assets-basics" + }, + { + "depth": 2, + "title": "Assets Pallet", + "anchor": "assets-pallet" }, { "depth": 3, - "title": "Account", - "anchor": "account" + "title": "Key Features", + "anchor": "key-features" }, { "depth": 3, - "title": "Account Info", - "anchor": "account-info" + "title": "Main Functions", + "anchor": "main-functions" }, { "depth": 3, - "title": "Account Reference Counters", - "anchor": "account-reference-counters" + "title": "Querying Functions", + "anchor": "querying-functions" }, { - "depth": 2, - "title": "Account Balance Types", - "anchor": "account-balance-types" + "depth": 3, + "title": "Permission Models and Roles", + "anchor": "permission-models-and-roles" }, { "depth": 3, - "title": "Balance Types", - "anchor": "balance-types" + "title": "Asset Freezing", + "anchor": "asset-freezing" }, { "depth": 3, - "title": "Locks", - "anchor": "locks" + "title": "Non-Custodial Transfers (Approval API)", + "anchor": "non-custodial-transfers-approval-api" + }, + { + "depth": 2, + "title": "Foreign Assets", + "anchor": "foreign-assets" }, { "depth": 3, - "title": "Balance Types on Polkadot.js", - "anchor": "balance-types-on-polkadotjs" + "title": "Handling Foreign Assets", + "anchor": "handling-foreign-assets" }, { "depth": 2, - "title": "Address Formats", - "anchor": "address-formats" + "title": "Integration", + "anchor": "integration" }, { "depth": 3, - "title": "Basic Format", - "anchor": "basic-format" + "title": "API Sidecar", + "anchor": "api-sidecar" }, { "depth": 3, - "title": "Address Type", - "anchor": "address-type" + "title": "TxWrapper", + "anchor": "txwrapper" + }, + { + "depth": 3, + "title": "ParaSpell", + "anchor": "paraspell" + }, + { + "depth": 3, + "title": "Parachain Node", + "anchor": "parachain-node" + }, + { + "depth": 2, + "title": "XCM Transfer Monitoring", + "anchor": "xcm-transfer-monitoring" + }, + { + "depth": 3, + "title": "Monitor XCM Deposits", + "anchor": "monitor-xcm-deposits" }, { "depth": 3, - "title": "Address Length", - "anchor": "address-length" + "title": "Track XCM Information Back to the Source", + "anchor": "track-xcm-information-back-to-the-source" }, { "depth": 3, - "title": "Checksum Types", - "anchor": "checksum-types" + "title": "Practical Monitoring Examples", + "anchor": "practical-monitoring-examples" }, { "depth": 3, - "title": "Validating Addresses", - "anchor": "validating-addresses" + "title": "Monitor for Failed XCM Transfers", + "anchor": "monitor-for-failed-xcm-transfers" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 29604, - "words": 4194, - "headings": 15, - "estimated_token_count_total": 6507 + "chars": 20065, + "words": 2901, + "headings": 22, + "estimated_token_count_total": 4087 }, - "hash": "sha256:0104a9132a69345a2faac37fca0e2853a2ded1efb009511a83a98d44509ab887", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:73c34bb1dc80d04f765812c3ed2f247aeda6ce55598b0680d0bd157f25456b99", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-blocks", - "title": "Blocks", - "slug": "reference-parachains-blocks-transactions-fees-blocks", + "id": "reference-polkadot-hub-bridging", + "title": "Bridge Hub", + "slug": "reference-polkadot-hub-bridging", "categories": [ - "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/", - "preview": "In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-bridging.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/bridging/", + "preview": "The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interope", "outline": [ { "depth": 2, @@ -11003,159 +8773,126 @@ }, { "depth": 2, - "title": "What is a Block?", - "anchor": "what-is-a-block" + "title": "Trustless Bridging", + "anchor": "trustless-bridging" }, { "depth": 2, - "title": "Block Production", - "anchor": "block-production" - }, - { - "depth": 3, - "title": "Initialize Block", - "anchor": "initialize-block" + "title": "Bridging Components", + "anchor": "bridging-components" }, { "depth": 3, - "title": "Finalize Block", - "anchor": "finalize-block" + "title": "Ethereum-Specific Support", + "anchor": "ethereum-specific-support" }, { "depth": 2, - "title": "Block Authoring and Import", - "anchor": "block-authoring-and-import" - }, - { - "depth": 3, - "title": "Block Import Queue", - "anchor": "block-import-queue" + "title": "Deployed Bridges", + "anchor": "deployed-bridges" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 6252, - "words": 910, - "headings": 8, - "estimated_token_count_total": 1395 + "chars": 5467, + "words": 776, + "headings": 6, + "estimated_token_count_total": 1220 }, - "hash": "sha256:424783c102bea5dae5b8749635858c6c59055563442a98f57521f0027dafa8d3", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:86734ba8bcdea7913f488edf666a6104bed0a18649d57abde82c149c41c2b871", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-fees", - "title": "Transactions Weights and Fees", - "slug": "reference-parachains-blocks-transactions-fees-fees", + "id": "reference-polkadot-hub-collectives-and-daos", + "title": "Collectives Chain", + "slug": "reference-polkadot-hub-collectives-and-daos", "categories": [ - "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/", - "preview": "When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop th", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-collectives-and-daos.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/collectives-and-daos/", + "preview": "Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem.", "outline": [ { "depth": 2, - "title": "Introductions", - "anchor": "introductions" - }, - { - "depth": 2, - "title": "How Fees are Calculated", - "anchor": "how-fees-are-calculated" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Using the Transaction Payment Pallet", - "anchor": "using-the-transaction-payment-pallet" - }, - { - "depth": 3, - "title": "Understanding the Inclusion Fee", - "anchor": "understanding-the-inclusion-fee" - }, - { - "depth": 3, - "title": "Accounts with an Insufficient Balance", - "anchor": "accounts-with-an-insufficient-balance" - }, - { - "depth": 3, - "title": "Fee Multipliers", - "anchor": "fee-multipliers" - }, + "title": "Key Collectives", + "anchor": "key-collectives" + } + ], + "stats": { + "chars": 2288, + "words": 293, + "headings": 2, + "estimated_token_count_total": 424 + }, + "hash": "sha256:59ec351fbb8d3a392e90f4f5bf6b62f58b21d6d7a900c5e367e5d2e09ecb3aca", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-consensus-and-security-agile-coretime", + "title": "Agile Coretime", + "slug": "reference-polkadot-hub-consensus-and-security-agile-coretime", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/agile-coretime/", + "preview": "Agile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains.", + "outline": [ { "depth": 2, - "title": "Transactions with Special Requirements", - "anchor": "transactions-with-special-requirements" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Default Weight Annotations", - "anchor": "default-weight-annotations" - }, - { - "depth": 3, - "title": "Weights and Database Read/Write Operations", - "anchor": "weights-and-database-readwrite-operations" - }, - { - "depth": 3, - "title": "Dispatch Classes", - "anchor": "dispatch-classes" + "title": "Bulk Coretime", + "anchor": "bulk-coretime" }, { "depth": 3, - "title": "Dynamic Weights", - "anchor": "dynamic-weights" - }, - { - "depth": 2, - "title": "Post Dispatch Weight Correction", - "anchor": "post-dispatch-weight-correction" - }, - { - "depth": 2, - "title": "Custom Fees", - "anchor": "custom-fees" + "title": "Coretime Interlacing", + "anchor": "coretime-interlacing" }, { "depth": 3, - "title": "Custom Weights", - "anchor": "custom-weights" + "title": "Coretime Splitting", + "anchor": "coretime-splitting" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "On-Demand Coretime", + "anchor": "on-demand-coretime" } ], "stats": { - "chars": 20800, - "words": 2917, - "headings": 15, - "estimated_token_count_total": 4464 + "chars": 3028, + "words": 452, + "headings": 5, + "estimated_token_count_total": 619 }, - "hash": "sha256:7d0c3fa7982b3e1843adb8f27422456397580b3a3eba5047b381da8517742536", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:00be43ac8d666bbe15c5c2fa5a5085697d0bb5a6f341ebbb943a209f0be355df", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-transactions", - "title": "Transactions", - "slug": "reference-parachains-blocks-transactions-fees-transactions", + "id": "reference-polkadot-hub-consensus-and-security-pos-consensus", + "title": "Proof of Stake Consensus", + "slug": "reference-polkadot-hub-consensus-and-security-pos-consensus", "categories": [ - "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/", - "preview": "Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/pos-consensus/", + "preview": "Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank} model and a com", "outline": [ { "depth": 2, @@ -11164,131 +8901,162 @@ }, { "depth": 2, - "title": "What Is a Transaction?", - "anchor": "what-is-a-transaction" + "title": "Nominated Proof of Stake", + "anchor": "nominated-proof-of-stake" }, { - "depth": 3, - "title": "Signed Transactions", - "anchor": "signed-transactions" + "depth": 2, + "title": "Hybrid Consensus", + "anchor": "hybrid-consensus" }, { - "depth": 3, - "title": "Unsigned Transactions", - "anchor": "unsigned-transactions" + "depth": 2, + "title": "Block Production - BABE", + "anchor": "block-production-babe" }, { "depth": 3, - "title": "Inherent Transactions", - "anchor": "inherent-transactions" + "title": "Validator Participation", + "anchor": "validator-participation" }, { - "depth": 2, - "title": "Transaction Formats", - "anchor": "transaction-formats" + "depth": 3, + "title": "Additional Resources", + "anchor": "additional-resources" }, { - "depth": 3, - "title": "Types of Transaction Formats", - "anchor": "types-of-transaction-formats" + "depth": 2, + "title": "Finality Gadget - GRANDPA", + "anchor": "finality-gadget-grandpa" }, { "depth": 3, - "title": "Signed Transaction Data Structure", - "anchor": "signed-transaction-data-structure" + "title": "Probabilistic vs. Provable Finality", + "anchor": "probabilistic-vs-provable-finality" }, { "depth": 3, - "title": "Signed Extensions", - "anchor": "signed-extensions" + "title": "Additional Resources", + "anchor": "additional-resources-2" }, { "depth": 2, - "title": "Transaction Construction", - "anchor": "transaction-construction" - }, - { - "depth": 3, - "title": "Construct a Signed Transaction", - "anchor": "construct-a-signed-transaction" + "title": "Fork Choice", + "anchor": "fork-choice" }, { "depth": 3, - "title": "Transaction Encoding", - "anchor": "transaction-encoding" + "title": "Additional Resources", + "anchor": "additional-resources-3" + }, + { + "depth": 2, + "title": "Bridging - BEEFY", + "anchor": "bridging-beefy" }, { "depth": 3, - "title": "Customize Transaction Construction", - "anchor": "customize-transaction-construction" + "title": "Additional Resources", + "anchor": "additional-resources-4" + } + ], + "stats": { + "chars": 12753, + "words": 1834, + "headings": 13, + "estimated_token_count_total": 2526 + }, + "hash": "sha256:231fc555eefe5f910fb36e0c03945147d0fb235272850797391751f4444b0a9c", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-consensus-and-security-relay-chain", + "title": "Overview of the Polkadot Relay Chain", + "slug": "reference-polkadot-hub-consensus-and-security-relay-chain", + "categories": [ + "Basics", + "Polkadot Protocol", + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/", + "preview": "Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank}, and cross-chain int", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Lifecycle of a Transaction", - "anchor": "lifecycle-of-a-transaction" + "title": "Polkadot 1.0", + "anchor": "polkadot-10" }, { "depth": 3, - "title": "Define Transaction Properties", - "anchor": "define-transaction-properties" + "title": "High-Level Architecture", + "anchor": "high-level-architecture" }, { "depth": 3, - "title": "Process on a Block Authoring Node", - "anchor": "process-on-a-block-authoring-node" + "title": "Polkadot's Additional Functionalities", + "anchor": "polkadots-additional-functionalities" }, { "depth": 3, - "title": "Validate and Queue", - "anchor": "validate-and-queue" + "title": "Polkadot's Resilience", + "anchor": "polkadots-resilience" }, { "depth": 3, - "title": "Transaction Ordering and Priority", - "anchor": "transaction-ordering-and-priority" + "title": "Polkadot's Blockspace", + "anchor": "polkadots-blockspace" + }, + { + "depth": 2, + "title": "DOT Token", + "anchor": "dot-token" }, { "depth": 3, - "title": "Transaction Execution", - "anchor": "transaction-execution" + "title": "Redenomination of DOT", + "anchor": "redenomination-of-dot" }, { - "depth": 2, - "title": "Transaction Mortality", - "anchor": "transaction-mortality" + "depth": 3, + "title": "The Planck Unit", + "anchor": "the-planck-unit" }, { - "depth": 2, - "title": "Unique Identifiers for Extrinsics", - "anchor": "unique-identifiers-for-extrinsics" + "depth": 3, + "title": "Uses for DOT", + "anchor": "uses-for-dot" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "JAM and the Road Ahead", + "anchor": "jam-and-the-road-ahead" } ], "stats": { - "chars": 23610, - "words": 3333, - "headings": 22, - "estimated_token_count_total": 4708 + "chars": 12430, + "words": 1771, + "headings": 11, + "estimated_token_count_total": 2571 }, - "hash": "sha256:547f062b248779f0b3e823778120c4f32e449937b6f270ddf97378bc6d795c62", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:8a914e4309d4fe7070e62d7abe4665b6c76c8dc5ec3219332eccb16b77b0dd95", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-chain-data", - "title": "Chain Data", - "slug": "reference-parachains-chain-data", + "id": "reference-polkadot-hub-people-and-identity", + "title": "People Chain", + "slug": "reference-polkadot-hub-people-and-identity", "categories": [ - "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md", - "html_url": "https://docs.polkadot.com/reference/parachains/chain-data/", - "preview": "Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-people-and-identity.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/people-and-identity/", + "preview": "People chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management.", "outline": [ { "depth": 2, @@ -11297,116 +9065,167 @@ }, { "depth": 2, - "title": "Application Development", - "anchor": "application-development" + "title": "Identity Management System", + "anchor": "identity-management-system" }, { - "depth": 2, - "title": "Understand Metadata", - "anchor": "understand-metadata" + "depth": 3, + "title": "Sub-Identities", + "anchor": "sub-identities" }, { "depth": 2, - "title": "Expose Runtime Information as Metadata", - "anchor": "expose-runtime-information-as-metadata" + "title": "Verification Process", + "anchor": "verification-process" }, { - "depth": 2, - "title": "Generate Metadata", - "anchor": "generate-metadata" + "depth": 3, + "title": "Judgment Requests", + "anchor": "judgment-requests" }, { - "depth": 2, - "title": "Retrieve Runtime Metadata", - "anchor": "retrieve-runtime-metadata" + "depth": 3, + "title": "Judgment Classifications", + "anchor": "judgment-classifications" }, { "depth": 3, - "title": "Use Polkadot.js", - "anchor": "use-polkadotjs" + "title": "Registrars", + "anchor": "registrars" }, { - "depth": 3, - "title": "Use Curl", - "anchor": "use-curl" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 4750, + "words": 606, + "headings": 8, + "estimated_token_count_total": 876 + }, + "hash": "sha256:8239d1e8d8642cb7c10e9e5f971c99b999e9e4a87373b50bf4a691225c1e4702", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub", + "title": "reference-polkadot-hub", + "slug": "reference-polkadot-hub", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-chopsticks", + "title": "reference-tools-chopsticks", + "slug": "reference-tools-chopsticks", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md", + "html_url": "https://docs.polkadot.com/reference/tools/chopsticks/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-dedot", + "title": "Dedot", + "slug": "reference-tools-dedot", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md", + "html_url": "https://docs.polkadot.com/reference/tools/dedot/", + "preview": "[Dedot](https://github.com/dedotdev/dedot){target=\\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\\_blank}.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 3, - "title": "Use Subxt", - "anchor": "use-subxt" + "title": "Key Features", + "anchor": "key-features" }, { "depth": 2, - "title": "Client Applications and Metadata", - "anchor": "client-applications-and-metadata" + "title": "Installation", + "anchor": "installation" }, { "depth": 2, - "title": "Metadata Format", - "anchor": "metadata-format" + "title": "Get Started", + "anchor": "get-started" }, { "depth": 3, - "title": "Pallets", - "anchor": "pallets" + "title": "Initialize a Client Instance", + "anchor": "initialize-a-client-instance" }, { "depth": 3, - "title": "Extrinsic", - "anchor": "extrinsic" + "title": "Enable Type and API Suggestions", + "anchor": "enable-type-and-api-suggestions" }, { - "depth": 2, - "title": "Included RPC APIs", - "anchor": "included-rpc-apis" + "depth": 3, + "title": "Read On-Chain Data", + "anchor": "read-on-chain-data" }, { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 18650, - "words": 2216, - "headings": 15, - "estimated_token_count_total": 3774 - }, - "hash": "sha256:49238d1e9e2c33e0fcd3a84b5e30f0d3840d7d23a783b538875e0a23f38efc1d", - "last_modified": "2025-10-28T14:42:15+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-consensus-async-backing", - "title": "reference-parachains-consensus-async-backing", - "slug": "reference-parachains-consensus-async-backing", - "categories": [ - "Uncategorized" + "depth": 3, + "title": "Sign and Send Transactions", + "anchor": "sign-and-send-transactions" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-async-backing.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/async-backing/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 8855, + "words": 1100, + "headings": 9, + "estimated_token_count_total": 2300 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:ba24e31e2ad94fbf1d73f1878da92dd2e1476db00170780bbdf0e65ab18bc961", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-consensus-elastic-scaling", - "title": "Elastic Scaling", - "slug": "reference-parachains-consensus-elastic-scaling", + "id": "reference-tools-light-clients", + "title": "Light Clients", + "slug": "reference-tools-light-clients", "categories": [ - "Polkadot Protocol" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-elastic-scaling.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/elastic-scaling/", - "preview": "Polkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md", + "html_url": "https://docs.polkadot.com/reference/tools/light-clients/", + "preview": "Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes.", "outline": [ { "depth": 2, @@ -11415,61 +9234,55 @@ }, { "depth": 2, - "title": "How Elastic Scaling Works", - "anchor": "how-elastic-scaling-works" + "title": "Light Clients Workflow", + "anchor": "light-clients-workflow" }, { "depth": 2, - "title": "Benefits of Elastic Scaling", - "anchor": "benefits-of-elastic-scaling" + "title": "JSON-RPC and Light Client Comparison", + "anchor": "json-rpc-and-light-client-comparison" }, { "depth": 2, - "title": "Use Cases", - "anchor": "use-cases" - }, - { - "depth": 3, - "title": "Handling Sudden Traffic Spikes", - "anchor": "handling-sudden-traffic-spikes" + "title": "Using Light Clients", + "anchor": "using-light-clients" }, { "depth": 3, - "title": "Supporting Early-Stage Growth", - "anchor": "supporting-early-stage-growth" + "title": "PAPI Light Client Support", + "anchor": "papi-light-client-support" }, { "depth": 3, - "title": "Scaling Massive IoT Networks", - "anchor": "scaling-massive-iot-networks" + "title": "Substrate Connect - Browser Extension", + "anchor": "substrate-connect-browser-extension" }, { - "depth": 3, - "title": "Powering Real-Time, Low-Latency Systems", - "anchor": "powering-real-time-low-latency-systems" + "depth": 2, + "title": "Resources", + "anchor": "resources" } ], "stats": { - "chars": 7871, - "words": 1047, - "headings": 8, - "estimated_token_count_total": 1440 + "chars": 6490, + "words": 870, + "headings": 7, + "estimated_token_count_total": 1430 }, - "hash": "sha256:2d228c52844df8952520fafdd3e6f0e26bfd2f32b5ee60c6241cf7d38603643c", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:1284c42be692167e01bcc44e2e134ec20615402675fac26df246c00aa1588d80", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-cryptography", - "title": "Cryptography", - "slug": "reference-parachains-cryptography", + "id": "reference-tools-moonwall", + "title": "E2E Testing with Moonwall", + "slug": "reference-tools-moonwall", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md", - "html_url": "https://docs.polkadot.com/reference/parachains/cryptography/", - "preview": "Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md", + "html_url": "https://docs.polkadot.com/reference/tools/moonwall/", + "preview": "Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations.", "outline": [ { "depth": 2, @@ -11478,81 +9291,65 @@ }, { "depth": 2, - "title": "Hash Functions", - "anchor": "hash-functions" - }, - { - "depth": 3, - "title": "Key Properties of Hash Functions", - "anchor": "key-properties-of-hash-functions" - }, - { - "depth": 3, - "title": "Blake2", - "anchor": "blake2" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Types of Cryptography", - "anchor": "types-of-cryptography" - }, - { - "depth": 3, - "title": "Symmetric Cryptography", - "anchor": "symmetric-cryptography" + "title": "Install Moonwall", + "anchor": "install-moonwall" }, { "depth": 3, - "title": "Asymmetric Cryptography", - "anchor": "asymmetric-cryptography" + "title": "Global Installation", + "anchor": "global-installation" }, { "depth": 3, - "title": "Trade-offs and Compromises", - "anchor": "trade-offs-and-compromises" + "title": "Local Installation", + "anchor": "local-installation" }, { "depth": 2, - "title": "Digital Signatures", - "anchor": "digital-signatures" + "title": "Initialize Moonwall", + "anchor": "initialize-moonwall" }, { - "depth": 3, - "title": "Example of Creating a Digital Signature", - "anchor": "example-of-creating-a-digital-signature" + "depth": 2, + "title": "Writing Tests", + "anchor": "writing-tests" }, { "depth": 2, - "title": "Elliptic Curve", - "anchor": "elliptic-curve" + "title": "Running the Tests", + "anchor": "running-the-tests" }, { - "depth": 3, - "title": "Various Implementations", - "anchor": "various-implementations" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 8860, - "words": 1293, - "headings": 12, - "estimated_token_count_total": 1797 + "chars": 10240, + "words": 1295, + "headings": 9, + "estimated_token_count_total": 2453 }, - "hash": "sha256:259dcef86aadc513675258b665cc3940db65af6eb32a5db85da6ac339966fa60", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:2c77cfb38bb2e466a8f56dabbb706fcd2e90cf1634fc9beb7f0ee95a75735653", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-data-encoding", - "title": "Data Encoding", - "slug": "reference-parachains-data-encoding", + "id": "reference-tools-omninode", + "title": "Polkadot Omni Node", + "slug": "reference-tools-omninode", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md", - "html_url": "https://docs.polkadot.com/reference/parachains/data-encoding/", - "preview": "The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md", + "html_url": "https://docs.polkadot.com/reference/tools/omninode/", + "preview": "The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\\_blank} file, allowing it to adapt dynamically to different parachains.", "outline": [ { "depth": 2, @@ -11561,71 +9358,65 @@ }, { "depth": 2, - "title": "SCALE Codec", - "anchor": "scale-codec" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Encode", - "anchor": "encode" + "depth": 2, + "title": "Install Polkadot Omni Node", + "anchor": "install-polkadot-omni-node" }, { - "depth": 3, - "title": "Decode", - "anchor": "decode" + "depth": 2, + "title": "Obtain Chain Specifications", + "anchor": "obtain-chain-specifications" }, { - "depth": 3, - "title": "CompactAs", - "anchor": "compactas" + "depth": 2, + "title": "Run a Parachain Full Node", + "anchor": "run-a-parachain-full-node" }, { - "depth": 3, - "title": "HasCompact", - "anchor": "hascompact" + "depth": 2, + "title": "Interact with the Node", + "anchor": "interact-with-the-node" }, { - "depth": 3, - "title": "EncodeLike", - "anchor": "encodelike" + "depth": 2, + "title": "Parachain Compatibility", + "anchor": "parachain-compatibility" }, { "depth": 3, - "title": "Data Types", - "anchor": "data-types" - }, - { - "depth": 2, - "title": "Encode and Decode Rust Trait Implementations", - "anchor": "encode-and-decode-rust-trait-implementations" + "title": "Required Runtime APIs", + "anchor": "required-runtime-apis" }, { - "depth": 2, - "title": "SCALE Codec Libraries", - "anchor": "scale-codec-libraries" + "depth": 3, + "title": "Required Pallets", + "anchor": "required-pallets" } ], "stats": { - "chars": 13629, - "words": 1314, - "headings": 10, - "estimated_token_count_total": 3213 + "chars": 8916, + "words": 1165, + "headings": 9, + "estimated_token_count_total": 2018 }, - "hash": "sha256:e448294b6e52291ac0add5fa6533572814e6cd27af42bdaccc2000b86f52d775", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:a87815deff81936d7f50842f8600004990076c1a33e7e6b408ab954b6ce47259", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-interoperability", - "title": "Interoperability", - "slug": "reference-parachains-interoperability", + "id": "reference-tools-papi", + "title": "Polkadot-API", + "slug": "reference-tools-papi", "categories": [ - "Basics", - "Polkadot Protocol" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md", - "html_url": "https://docs.polkadot.com/reference/parachains/interoperability/", - "preview": "Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md", + "html_url": "https://docs.polkadot.com/reference/tools/papi/", + "preview": "[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications.", "outline": [ { "depth": 2, @@ -11634,130 +9425,153 @@ }, { "depth": 2, - "title": "Why Interoperability Matters", - "anchor": "why-interoperability-matters" - }, - { - "depth": 2, - "title": "Key Mechanisms for Interoperability", - "anchor": "key-mechanisms-for-interoperability" + "title": "Get Started", + "anchor": "get-started" }, { "depth": 3, - "title": "Cross-Consensus Messaging (XCM): The Backbone of Communication", - "anchor": "cross-consensus-messaging-xcm-the-backbone-of-communication" + "title": "API Instantiation", + "anchor": "api-instantiation" }, { "depth": 3, - "title": "Bridges: Connecting External Networks", - "anchor": "bridges-connecting-external-networks" + "title": "Reading Chain Data", + "anchor": "reading-chain-data" }, { - "depth": 2, - "title": "The Polkadot Advantage", - "anchor": "the-polkadot-advantage" + "depth": 3, + "title": "Sending Transactions", + "anchor": "sending-transactions" }, { "depth": 2, - "title": "Looking Ahead", - "anchor": "looking-ahead" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 4635, - "words": 584, - "headings": 7, - "estimated_token_count_total": 772 + "chars": 8957, + "words": 1156, + "headings": 6, + "estimated_token_count_total": 1987 }, - "hash": "sha256:11bb4f113bdda5852a3115e64d5ba47f8eccd4e3619a05ad960ab3a541f31346", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:2ca93b09d3bb9159bbf53816886a9b242bb3c13b996c51fd52962e049e2d5477", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-networks", - "title": "Networks", - "slug": "reference-parachains-networks", + "id": "reference-tools-paraspell", + "title": "ParaSpell XCM SDK", + "slug": "reference-tools-paraspell", "categories": [ - "Basics", - "Polkadot Protocol", - "Networks" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md", - "html_url": "https://docs.polkadot.com/reference/parachains/networks/", - "preview": "The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's va", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md", + "html_url": "https://docs.polkadot.com/reference/tools/paraspell/", + "preview": "[ParaSpell](https://paraspell.github.io/docs/){target=\\_blank} is a comprehensive suite of open-source tools designed to simplify cross-chain interactions within the Polkadot ecosystem. At its core, ParaSpell is dedicated to enhancing the functionality of the [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} protocol by providing developers with a unified and streamlined experience for building interoperable decentralized applications (dApps).", "outline": [ { "depth": 2, "title": "Introduction", "anchor": "introduction" }, + { + "depth": 3, + "title": "ParaSpell XCM SDK", + "anchor": "paraspell-xcm-sdk" + } + ], + "stats": { + "chars": 3005, + "words": 433, + "headings": 2, + "estimated_token_count_total": 669 + }, + "hash": "sha256:a7f9c4a03153ee637a0557d2cea0b622c849667ce793b1294bb3299cf036197d", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-polkadart", + "title": "Polkadart", + "slug": "reference-tools-polkadart", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md", + "html_url": "https://docs.polkadot.com/reference/tools/polkadart/", + "preview": "Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications.", + "outline": [ { "depth": 2, - "title": "Network Overview", - "anchor": "network-overview" + "title": "Installation", + "anchor": "installation" }, { "depth": 2, - "title": "Polkadot Development Networks", - "anchor": "polkadot-development-networks" + "title": "Get Started", + "anchor": "get-started" }, { - "depth": 2, - "title": "Kusama Network", - "anchor": "kusama-network" + "depth": 3, + "title": "Type Generation", + "anchor": "type-generation" }, { - "depth": 2, - "title": "Test Networks", - "anchor": "test-networks" + "depth": 3, + "title": "Run Generator", + "anchor": "run-generator" }, { "depth": 3, - "title": "Westend", - "anchor": "westend" + "title": "Use Generated Types", + "anchor": "use-generated-types" }, { "depth": 3, - "title": "Paseo", - "anchor": "paseo" + "title": "Creating an API Instance", + "anchor": "creating-an-api-instance" }, { - "depth": 2, - "title": "Local Test Networks", - "anchor": "local-test-networks" + "depth": 3, + "title": "Reading Chain Data", + "anchor": "reading-chain-data" }, { "depth": 3, - "title": "Zombienet", - "anchor": "zombienet" + "title": "Subscribe to New Blocks", + "anchor": "subscribe-to-new-blocks" }, { "depth": 3, - "title": "Chopsticks", - "anchor": "chopsticks" + "title": "Send a Transaction", + "anchor": "send-a-transaction" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 7834, - "words": 1111, + "chars": 5178, + "words": 624, "headings": 10, - "estimated_token_count_total": 1473 + "estimated_token_count_total": 1084 }, - "hash": "sha256:e49e063a2cc0fb5a48c6cdc3de266bb6e025a006940fea8e90cc4d5f9884900f", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:7f533abe61586af8438e350c41b741d74a8edb839f9dc4139bc4619ba3748258", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-node-and-runtime", - "title": "Node and Runtime", - "slug": "reference-parachains-node-and-runtime", + "id": "reference-tools-polkadot-js-api", + "title": "Polkadot.js API", + "slug": "reference-tools-polkadot-js-api", "categories": [ - "Basics", - "Polkadot Protocol" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md", - "html_url": "https://docs.polkadot.com/reference/parachains/node-and-runtime/", - "preview": "Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md", + "html_url": "https://docs.polkadot.com/reference/tools/polkadot-js-api/", + "preview": "!!! warning \"Maintenance Mode Only\" The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank} (modern, type-safe API) as actively maintained alternatives.", "outline": [ { "depth": 2, @@ -11765,72 +9579,66 @@ "anchor": "introduction" }, { - "depth": 2, - "title": "Architectural Principles", - "anchor": "architectural-principles" + "depth": 3, + "title": "Dynamic API Generation", + "anchor": "dynamic-api-generation" }, { "depth": 3, - "title": "Advantages of this Architecture", - "anchor": "advantages-of-this-architecture" + "title": "Available API Categories", + "anchor": "available-api-categories" }, { "depth": 2, - "title": "Node (Client)", - "anchor": "node-client" + "title": "Installation", + "anchor": "installation" }, { "depth": 2, - "title": "Runtime", - "anchor": "runtime" + "title": "Get Started", + "anchor": "get-started" }, { "depth": 3, - "title": "Characteristics", - "anchor": "characteristics" + "title": "Creating an API Instance", + "anchor": "creating-an-api-instance" }, { "depth": 3, - "title": "Key Functions", - "anchor": "key-functions" - }, - { - "depth": 2, - "title": "Communication Between Node and Runtime", - "anchor": "communication-between-node-and-runtime" + "title": "Reading Chain Data", + "anchor": "reading-chain-data" }, { "depth": 3, - "title": "Runtime APIs", - "anchor": "runtime-apis" + "title": "Sending Transactions", + "anchor": "sending-transactions" }, { - "depth": 3, - "title": "Host Functions", - "anchor": "host-functions" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 4937, - "words": 628, - "headings": 10, - "estimated_token_count_total": 914 + "chars": 5042, + "words": 684, + "headings": 9, + "estimated_token_count_total": 1166 }, - "hash": "sha256:8122e21c149d0863cfe3b37fc5606bcdb91668e9d265f0f05451a61ff70e4e93", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:ed3986f30880fefca5975fcdc847c68b4aca65862c63e3002b25391b0521781d", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-randomness", - "title": "Randomness", - "slug": "reference-parachains-randomness", + "id": "reference-tools-py-substrate-interface", + "title": "Python Substrate Interface", + "slug": "reference-tools-py-substrate-interface", "categories": [ - "Basics", - "Polkadot Protocol" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md", - "html_url": "https://docs.polkadot.com/reference/parachains/randomness/", - "preview": "Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as \"random\" numbers on a computer are actually pseudo-random. These numbers rely on an initial \"seed,\" which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\\_blank}, [heart rates](https://m", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md", + "html_url": "https://docs.polkadot.com/reference/tools/py-substrate-interface/", + "preview": "The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for:", "outline": [ { "depth": 2, @@ -11839,50 +9647,55 @@ }, { "depth": 2, - "title": "VRF", - "anchor": "vrf" + "title": "Installation", + "anchor": "installation" + }, + { + "depth": 2, + "title": "Get Started", + "anchor": "get-started" }, { "depth": 3, - "title": "How VRF Works", - "anchor": "how-vrf-works" + "title": "Establishing Connection", + "anchor": "establishing-connection" }, { - "depth": 2, - "title": "RANDAO", - "anchor": "randao" + "depth": 3, + "title": "Reading Chain State", + "anchor": "reading-chain-state" }, { - "depth": 2, - "title": "VDFs", - "anchor": "vdfs" + "depth": 3, + "title": "Submitting Transactions", + "anchor": "submitting-transactions" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 6503, - "words": 1005, - "headings": 6, - "estimated_token_count_total": 1388 + "chars": 4302, + "words": 541, + "headings": 7, + "estimated_token_count_total": 942 }, - "hash": "sha256:c7d8a5a4263fd21af458ab0bd102377104affdf2431b4fe74eeff4ebe62a4a81", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:8987fc35cd28602054ee018031f773e2e3837425107c51d0e2ac68a94b86e9c0", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-assets-and-smart-contracts", - "title": "Asset Hub", - "slug": "reference-polkadot-hub-assets-and-smart-contracts", + "id": "reference-tools-sidecar", + "title": "Sidecar REST API", + "slug": "reference-tools-sidecar", "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/assets-and-smart-contracts/", - "preview": "The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integra", + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md", + "html_url": "https://docs.polkadot.com/reference/tools/sidecar/", + "preview": "The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more.", "outline": [ { "depth": 2, @@ -11891,103 +9704,95 @@ }, { "depth": 2, - "title": "Assets Basics", - "anchor": "assets-basics" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Assets Pallet", - "anchor": "assets-pallet" - }, - { - "depth": 3, - "title": "Key Features", - "anchor": "key-features" - }, - { - "depth": 3, - "title": "Main Functions", - "anchor": "main-functions" - }, - { - "depth": 3, - "title": "Querying Functions", - "anchor": "querying-functions" - }, - { - "depth": 3, - "title": "Permission Models and Roles", - "anchor": "permission-models-and-roles" + "title": "Installation", + "anchor": "installation" }, { - "depth": 3, - "title": "Asset Freezing", - "anchor": "asset-freezing" + "depth": 2, + "title": "Usage", + "anchor": "usage" }, { "depth": 3, - "title": "Non-Custodial Transfers (Approval API)", - "anchor": "non-custodial-transfers-approval-api" + "title": "Endpoints", + "anchor": "endpoints" }, { "depth": 2, - "title": "Foreign Assets", - "anchor": "foreign-assets" - }, - { - "depth": 3, - "title": "Handling Foreign Assets", - "anchor": "handling-foreign-assets" - }, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 7309, + "words": 1033, + "headings": 6, + "estimated_token_count_total": 1945 + }, + "hash": "sha256:0795462182cb97256bb5c2acb035855fe0d6557185de8ac99482725ecb4f94c1", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-subxt", + "title": "Subxt Rust API", + "slug": "reference-tools-subxt", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md", + "html_url": "https://docs.polkadot.com/reference/tools/subxt/", + "preview": "Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability.", + "outline": [ { "depth": 2, - "title": "Integration", - "anchor": "integration" + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "API Sidecar", - "anchor": "api-sidecar" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "TxWrapper", - "anchor": "txwrapper" + "depth": 2, + "title": "Installation", + "anchor": "installation" }, { - "depth": 3, - "title": "ParaSpell", - "anchor": "paraspell" + "depth": 2, + "title": "Get Started", + "anchor": "get-started" }, { "depth": 3, - "title": "Parachain Node", - "anchor": "parachain-node" - }, - { - "depth": 2, - "title": "XCM Transfer Monitoring", - "anchor": "xcm-transfer-monitoring" + "title": "Download Chain Metadata", + "anchor": "download-chain-metadata" }, { "depth": 3, - "title": "Monitor XCM Deposits", - "anchor": "monitor-xcm-deposits" + "title": "Generate Type-Safe Interfaces", + "anchor": "generate-type-safe-interfaces" }, { "depth": 3, - "title": "Track XCM Information Back to the Source", - "anchor": "track-xcm-information-back-to-the-source" + "title": "Initialize the Subxt Client", + "anchor": "initialize-the-subxt-client" }, { "depth": 3, - "title": "Practical Monitoring Examples", - "anchor": "practical-monitoring-examples" + "title": "Read Chain Data", + "anchor": "read-chain-data" }, { "depth": 3, - "title": "Monitor for Failed XCM Transfers", - "anchor": "monitor-for-failed-xcm-transfers" + "title": "Submit Transactions", + "anchor": "submit-transactions" }, { "depth": 2, @@ -11996,25 +9801,26 @@ } ], "stats": { - "chars": 20065, - "words": 2901, - "headings": 22, - "estimated_token_count_total": 4087 + "chars": 9174, + "words": 1175, + "headings": 10, + "estimated_token_count_total": 2187 }, - "hash": "sha256:73c34bb1dc80d04f765812c3ed2f247aeda6ce55598b0680d0bd157f25456b99", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:56269d9ea47f5b4e92cd7d5a1e65ab06d181a9c380f90bb3ef285529b12299f7", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-bridging", - "title": "Bridge Hub", - "slug": "reference-polkadot-hub-bridging", + "id": "reference-tools-xcm-tools", + "title": "XCM Tools", + "slug": "reference-tools-xcm-tools", "categories": [ - "Polkadot Protocol" + "Basics", + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-bridging.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/bridging/", - "preview": "The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interope", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md", + "html_url": "https://docs.polkadot.com/reference/tools/xcm-tools/", + "preview": "As described in the [Interoperability](/develop/interoperability){target=\\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem.", "outline": [ { "depth": 2, @@ -12023,218 +9829,263 @@ }, { "depth": 2, - "title": "Trustless Bridging", - "anchor": "trustless-bridging" + "title": "Popular XCM Tools", + "anchor": "popular-xcm-tools" }, { - "depth": 2, - "title": "Bridging Components", - "anchor": "bridging-components" + "depth": 3, + "title": "Moonsong Labs XCM Tools", + "anchor": "moonsong-labs-xcm-tools" }, { "depth": 3, - "title": "Ethereum-Specific Support", - "anchor": "ethereum-specific-support" + "title": "ParaSpell", + "anchor": "paraspell" }, { - "depth": 2, - "title": "Deployed Bridges", - "anchor": "deployed-bridges" + "depth": 3, + "title": "Astar XCM Tools", + "anchor": "astar-xcm-tools" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Chopsticks", + "anchor": "chopsticks" + }, + { + "depth": 3, + "title": "Moonbeam XCM SDK", + "anchor": "moonbeam-xcm-sdk" } ], "stats": { - "chars": 5467, - "words": 776, - "headings": 6, - "estimated_token_count_total": 1220 + "chars": 7524, + "words": 1043, + "headings": 7, + "estimated_token_count_total": 1700 }, - "hash": "sha256:86734ba8bcdea7913f488edf666a6104bed0a18649d57abde82c149c41c2b871", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:47328231d6ff4dc52cd93aaf1baf5d0bc2d9fc372f3d79339d87aafa0dabd1b8", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-collectives-and-daos", - "title": "Collectives Chain", - "slug": "reference-polkadot-hub-collectives-and-daos", + "id": "reference-tools-zombienet", + "title": "reference-tools-zombienet", + "slug": "reference-tools-zombienet", "categories": [ - "Polkadot Protocol" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-collectives-and-daos.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/collectives-and-daos/", - "preview": "Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md", + "html_url": "https://docs.polkadot.com/reference/tools/zombienet/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference", + "title": "reference", + "slug": "reference", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md", + "html_url": "https://docs.polkadot.com/reference/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-connect", + "title": "Connect to Polkadot", + "slug": "smart-contracts-connect", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-connect.md", + "html_url": "https://docs.polkadot.com/smart-contracts/connect/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Networks Details", + "anchor": "networks-details" }, { "depth": 2, - "title": "Key Collectives", - "anchor": "key-collectives" + "title": "Test Tokens", + "anchor": "test-tokens" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 2288, - "words": 293, - "headings": 2, - "estimated_token_count_total": 424 + "chars": 3459, + "words": 476, + "headings": 3, + "estimated_token_count_total": 558 }, - "hash": "sha256:59ec351fbb8d3a392e90f4f5bf6b62f58b21d6d7a900c5e367e5d2e09ecb3aca", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:a2490223926957381913ae0ed22e2df3611a6713ec9d77a3015d1cd6a578b3f6", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-consensus-and-security-agile-coretime", - "title": "Agile Coretime", - "slug": "reference-polkadot-hub-consensus-and-security-agile-coretime", + "id": "smart-contracts-cookbook-dapps-zero-to-hero", + "title": "Zero to Hero Smart Contract DApp", + "slug": "smart-contracts-cookbook-dapps-zero-to-hero", "categories": [ - "Polkadot Protocol" + "dApp", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/agile-coretime/", - "preview": "Agile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/dapps/zero-to-hero/", + "preview": "Decentralized applications (dApps) are a key component of the Web3 ecosystem, enabling developers to build applications that communicate directly with blockchain networks. Polkadot Hub, a blockchain with smart contract support, serves as a robust platform for deploying and interacting with dApps.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Bulk Coretime", - "anchor": "bulk-coretime" + "title": "Project Overview", + "anchor": "project-overview" + }, + { + "depth": 2, + "title": "Create and Deploy the Storage Contract", + "anchor": "create-and-deploy-the-storage-contract" }, { "depth": 3, - "title": "Coretime Interlacing", - "anchor": "coretime-interlacing" + "title": "Set Up Hardhat Project", + "anchor": "set-up-hardhat-project" }, { "depth": 3, - "title": "Coretime Splitting", - "anchor": "coretime-splitting" + "title": "Create the Storage Contract", + "anchor": "create-the-storage-contract" }, { - "depth": 2, - "title": "On-Demand Coretime", - "anchor": "on-demand-coretime" - } - ], - "stats": { - "chars": 3028, - "words": 452, - "headings": 5, - "estimated_token_count_total": 619 - }, - "hash": "sha256:00be43ac8d666bbe15c5c2fa5a5085697d0bb5a6f341ebbb943a209f0be355df", - "last_modified": "2025-10-28T14:42:15+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-consensus-and-security-pos-consensus", - "title": "Proof of Stake Consensus", - "slug": "reference-polkadot-hub-consensus-and-security-pos-consensus", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/pos-consensus/", - "preview": "Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank} model and a com", - "outline": [ + "depth": 3, + "title": "Configure Hardhat for Polkadot Hub", + "anchor": "configure-hardhat-for-polkadot-hub" + }, + { + "depth": 3, + "title": "Compile the Contract", + "anchor": "compile-the-contract" + }, + { + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 3, + "title": "Export the Contract ABI", + "anchor": "export-the-contract-abi" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Set Up the dApp Project", + "anchor": "set-up-the-dapp-project" }, { "depth": 2, - "title": "Nominated Proof of Stake", - "anchor": "nominated-proof-of-stake" + "title": "Install Dependencies", + "anchor": "install-dependencies" }, { "depth": 2, - "title": "Hybrid Consensus", - "anchor": "hybrid-consensus" + "title": "Connect to Polkadot Hub", + "anchor": "connect-to-polkadot-hub" }, { "depth": 2, - "title": "Block Production - BABE", - "anchor": "block-production-babe" + "title": "Set Up the Smart Contract Interface", + "anchor": "set-up-the-smart-contract-interface" }, { - "depth": 3, - "title": "Validator Participation", - "anchor": "validator-participation" + "depth": 2, + "title": "Create the Wallet Connection Component", + "anchor": "create-the-wallet-connection-component" }, { - "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources" + "depth": 2, + "title": "Create the Read Contract Component", + "anchor": "create-the-read-contract-component" }, { "depth": 2, - "title": "Finality Gadget - GRANDPA", - "anchor": "finality-gadget-grandpa" + "title": "Create the Write Contract Component", + "anchor": "create-the-write-contract-component" }, { - "depth": 3, - "title": "Probabilistic vs. Provable Finality", - "anchor": "probabilistic-vs-provable-finality" + "depth": 2, + "title": "How It Works", + "anchor": "how-it-works" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-2" + "title": "Wallet Connection", + "anchor": "wallet-connection" }, { - "depth": 2, - "title": "Fork Choice", - "anchor": "fork-choice" + "depth": 3, + "title": "Data Reads", + "anchor": "data-reads" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-3" + "title": "Data Writes", + "anchor": "data-writes" }, { "depth": 2, - "title": "Bridging - BEEFY", - "anchor": "bridging-beefy" + "title": "Conclusion", + "anchor": "conclusion" }, { - "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-4" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 12753, - "words": 1834, - "headings": 13, - "estimated_token_count_total": 2526 + "chars": 31207, + "words": 3688, + "headings": 22, + "estimated_token_count_total": 6967 }, - "hash": "sha256:231fc555eefe5f910fb36e0c03945147d0fb235272850797391751f4444b0a9c", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:b200f93a9179f0b2588ba722dd4c118536136faf3c39eabccf4abf5c346f78a8", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-consensus-and-security-relay-chain", - "title": "Overview of the Polkadot Relay Chain", - "slug": "reference-polkadot-hub-consensus-and-security-relay-chain", + "id": "smart-contracts-cookbook-eth-dapps-uniswap-v2", + "title": "Deploying Uniswap V2 on Polkadot", + "slug": "smart-contracts-cookbook-eth-dapps-uniswap-v2", "categories": [ - "Basics", - "Polkadot Protocol", - "Parachains" + "dApps", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/", - "preview": "Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank}, and cross-chain int", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -12243,579 +10094,573 @@ }, { "depth": 2, - "title": "Polkadot 1.0", - "anchor": "polkadot-10" - }, - { - "depth": 3, - "title": "High-Level Architecture", - "anchor": "high-level-architecture" - }, - { - "depth": 3, - "title": "Polkadot's Additional Functionalities", - "anchor": "polkadots-additional-functionalities" - }, - { - "depth": 3, - "title": "Polkadot's Resilience", - "anchor": "polkadots-resilience" - }, - { - "depth": 3, - "title": "Polkadot's Blockspace", - "anchor": "polkadots-blockspace" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "DOT Token", - "anchor": "dot-token" + "title": "Set Up the Project", + "anchor": "set-up-the-project" }, { - "depth": 3, - "title": "Redenomination of DOT", - "anchor": "redenomination-of-dot" + "depth": 2, + "title": "Understanding Uniswap V2 Architecture", + "anchor": "understanding-uniswap-v2-architecture" }, { - "depth": 3, - "title": "The Planck Unit", - "anchor": "the-planck-unit" + "depth": 2, + "title": "Test the Contracts", + "anchor": "test-the-contracts" }, { - "depth": 3, - "title": "Uses for DOT", - "anchor": "uses-for-dot" + "depth": 2, + "title": "Deploy the Contracts", + "anchor": "deploy-the-contracts" }, { "depth": 2, - "title": "JAM and the Road Ahead", - "anchor": "jam-and-the-road-ahead" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 12430, - "words": 1771, - "headings": 11, - "estimated_token_count_total": 2571 + "chars": 11280, + "words": 1560, + "headings": 7, + "estimated_token_count_total": 2671 }, - "hash": "sha256:8a914e4309d4fe7070e62d7abe4665b6c76c8dc5ec3219332eccb16b77b0dd95", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:2a42198668c759f63aa602115bf2d290ec7d03bbc3a3df20e30e85027e1b1cc3", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-people-and-identity", - "title": "People Chain", - "slug": "reference-polkadot-hub-people-and-identity", + "id": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", + "title": "Deploy a Basic Contract to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", "categories": [ - "Polkadot Protocol" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-people-and-identity.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/people-and-identity/", - "preview": "People chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/.deploy-basic-pvm/", + "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", "outline": [ { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "JavaScript with Ethers.js", + "anchor": "javascript-with-ethersjs" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" + }, + { + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" }, { "depth": 2, - "title": "Identity Management System", - "anchor": "identity-management-system" + "title": "Remix IDE", + "anchor": "remix-ide" }, { "depth": 3, - "title": "Sub-Identities", - "anchor": "sub-identities" + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" }, { "depth": 2, - "title": "Verification Process", - "anchor": "verification-process" + "title": "Hardhat", + "anchor": "hardhat" }, { "depth": 3, - "title": "Judgment Requests", - "anchor": "judgment-requests" + "title": "Setup", + "anchor": "setup-2" }, { "depth": 3, - "title": "Judgment Classifications", - "anchor": "judgment-classifications" + "title": "Configure Hardhat", + "anchor": "configure-hardhat" }, { "depth": 3, - "title": "Registrars", - "anchor": "registrars" + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4750, - "words": 606, - "headings": 8, - "estimated_token_count_total": 876 - }, - "hash": "sha256:8239d1e8d8642cb7c10e9e5f971c99b999e9e4a87373b50bf4a691225c1e4702", - "last_modified": "2025-10-28T14:42:15+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-chopsticks", - "title": "reference-tools-chopsticks", - "slug": "reference-tools-chopsticks", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md", - "html_url": "https://docs.polkadot.com/reference/tools/chopsticks/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:15+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-dedot", - "title": "Dedot", - "slug": "reference-tools-dedot", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md", - "html_url": "https://docs.polkadot.com/reference/tools/dedot/", - "preview": "[Dedot](https://github.com/dedotdev/dedot){target=\\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\\_blank}.", - "outline": [ + "depth": 3, + "title": "Compile", + "anchor": "compile-2" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" }, { "depth": 3, - "title": "Key Features", - "anchor": "key-features" + "title": "Deploy", + "anchor": "deploy-2" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Foundry", + "anchor": "foundry" }, { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "depth": 3, + "title": "Setup", + "anchor": "setup-3" }, { "depth": 3, - "title": "Initialize a Client Instance", - "anchor": "initialize-a-client-instance" + "title": "Configure Foundry", + "anchor": "configure-foundry" }, { "depth": 3, - "title": "Enable Type and API Suggestions", - "anchor": "enable-type-and-api-suggestions" + "title": "Create Your Contract", + "anchor": "create-your-contract-2" }, { "depth": 3, - "title": "Read On-Chain Data", - "anchor": "read-on-chain-data" + "title": "Compile", + "anchor": "compile-3" }, { "depth": 3, - "title": "Sign and Send Transactions", - "anchor": "sign-and-send-transactions" + "title": "Deploy", + "anchor": "deploy-3" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Conclusion", + "anchor": "conclusion" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 8855, - "words": 1100, - "headings": 9, - "estimated_token_count_total": 2300 + "chars": 13872, + "words": 1640, + "headings": 24, + "estimated_token_count_total": 3228 }, - "hash": "sha256:ba24e31e2ad94fbf1d73f1878da92dd2e1476db00170780bbdf0e65ab18bc961", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:8f29b0f0b56f8c136206211a858cdc5bc27bcd9119eab179a6cd306182d910cb", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-light-clients", - "title": "Light Clients", - "slug": "reference-tools-light-clients", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-ethers-js", + "title": "JavaScript with Ethers.js", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-ethers-js", "categories": [ - "Parachains", - "Tooling" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md", - "html_url": "https://docs.polkadot.com/reference/tools/light-clients/", - "preview": "Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-ethers-js.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-ethers-js/", + "preview": "[Ethers.js](https://docs.ethers.org/v6/){target=\\_blank} provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications.", "outline": [ { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Light Clients Workflow", - "anchor": "light-clients-workflow" - }, - { - "depth": 2, - "title": "JSON-RPC and Light Client Comparison", - "anchor": "json-rpc-and-light-client-comparison" - }, - { - "depth": 2, - "title": "Using Light Clients", - "anchor": "using-light-clients" + "depth": 3, + "title": "Setup", + "anchor": "setup" }, { "depth": 3, - "title": "PAPI Light Client Support", - "anchor": "papi-light-client-support" + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" }, { "depth": 3, - "title": "Substrate Connect - Browser Extension", - "anchor": "substrate-connect-browser-extension" + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" }, { - "depth": 2, - "title": "Resources", - "anchor": "resources" + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 6490, - "words": 870, - "headings": 7, - "estimated_token_count_total": 1430 + "chars": 6935, + "words": 767, + "headings": 4, + "estimated_token_count_total": 1490 }, - "hash": "sha256:1284c42be692167e01bcc44e2e134ec20615402675fac26df246c00aa1588d80", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:b0af34b460192f665ca70e7d7985e87b9f59a1a359888f6d14d651daedbcd711", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-moonwall", - "title": "E2E Testing with Moonwall", - "slug": "reference-tools-moonwall", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-foundry", + "title": "Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-foundry", "categories": [ - "Parachains", - "Tooling" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md", - "html_url": "https://docs.polkadot.com/reference/tools/moonwall/", - "preview": "Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-foundry/", + "preview": "[Foundry](https://getfoundry.sh/){target=\\_blank} offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Install Moonwall", - "anchor": "install-moonwall" - }, { "depth": 3, - "title": "Global Installation", - "anchor": "global-installation" + "title": "Setup", + "anchor": "setup" }, { "depth": 3, - "title": "Local Installation", - "anchor": "local-installation" + "title": "Configure Foundry", + "anchor": "configure-foundry" }, { - "depth": 2, - "title": "Initialize Moonwall", - "anchor": "initialize-moonwall" + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { - "depth": 2, - "title": "Writing Tests", - "anchor": "writing-tests" + "depth": 3, + "title": "Compile", + "anchor": "compile" }, { - "depth": 2, - "title": "Running the Tests", - "anchor": "running-the-tests" + "depth": 3, + "title": "Deploy", + "anchor": "deploy" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 10240, - "words": 1295, - "headings": 9, - "estimated_token_count_total": 2453 + "chars": 2125, + "words": 276, + "headings": 6, + "estimated_token_count_total": 429 }, - "hash": "sha256:2c77cfb38bb2e466a8f56dabbb706fcd2e90cf1634fc9beb7f0ee95a75735653", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:f7687b9a1e80ab381cf4fb24f37cccfb98ddf139bf687e8832af99364ef0a8a9", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-omninode", - "title": "Polkadot Omni Node", - "slug": "reference-tools-omninode", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat", + "title": "hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat", "categories": [ - "Parachains", - "Tooling" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md", - "html_url": "https://docs.polkadot.com/reference/tools/omninode/", - "preview": "The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\\_blank} file, allowing it to adapt dynamically to different parachains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-hardhat/", + "preview": "[Hardhat](https://hardhat.org/){target=\\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", "outline": [ { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Install Polkadot Omni Node", - "anchor": "install-polkadot-omni-node" + "depth": 3, + "title": "Setup", + "anchor": "setup" }, { - "depth": 2, - "title": "Obtain Chain Specifications", - "anchor": "obtain-chain-specifications" + "depth": 3, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" }, { - "depth": 2, - "title": "Run a Parachain Full Node", - "anchor": "run-a-parachain-full-node" + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { - "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" + "depth": 3, + "title": "Compile", + "anchor": "compile" }, { - "depth": 2, - "title": "Parachain Compatibility", - "anchor": "parachain-compatibility" + "depth": 3, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" }, { "depth": 3, - "title": "Required Runtime APIs", - "anchor": "required-runtime-apis" + "title": "Deploy", + "anchor": "deploy" }, { "depth": 3, - "title": "Required Pallets", - "anchor": "required-pallets" + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 8916, - "words": 1165, - "headings": 9, - "estimated_token_count_total": 2018 + "chars": 3336, + "words": 375, + "headings": 7, + "estimated_token_count_total": 672 }, - "hash": "sha256:a87815deff81936d7f50842f8600004990076c1a33e7e6b408ab954b6ce47259", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:93ca24da15095dd0bb03657f53d27771934aee055c11af529445a50e161f79a3", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-papi", - "title": "Polkadot-API", - "slug": "reference-tools-papi", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-remix", + "title": "Remix IDE", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-remix", "categories": [ - "Tooling", - "Dapps" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md", - "html_url": "https://docs.polkadot.com/reference/tools/papi/", - "preview": "[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-remix/", + "preview": "[Remix IDE](https://remix.live/){target=\\_blank} offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", "outline": [ { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Access Remix", + "anchor": "access-remix" }, { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "depth": 3, + "title": "Compile", + "anchor": "compile" }, { "depth": 3, - "title": "API Instantiation", - "anchor": "api-instantiation" + "title": "Deploy", + "anchor": "deploy" }, { "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 2473, + "words": 363, + "headings": 4, + "estimated_token_count_total": 527 + }, + "hash": "sha256:56d730c8a6d2ccf0324caf1c3f30929a93904f80e482cfcb457541e04482dbad", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-ethers-js", + "title": "JavaScript with Ethers.js", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-ethers-js", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-ethers-js.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-ethers-js/", + "preview": "[Ethers.js](https://docs.ethers.org/v6/){target=\\_blank} provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications.", + "outline": [ + { + "depth": 3, + "title": "Setup", + "anchor": "setup" }, { "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 8957, - "words": 1156, - "headings": 6, - "estimated_token_count_total": 1987 + "chars": 6935, + "words": 767, + "headings": 4, + "estimated_token_count_total": 1490 }, - "hash": "sha256:2ca93b09d3bb9159bbf53816886a9b242bb3c13b996c51fd52962e049e2d5477", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:b0af34b460192f665ca70e7d7985e87b9f59a1a359888f6d14d651daedbcd711", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-paraspell", - "title": "ParaSpell XCM SDK", - "slug": "reference-tools-paraspell", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-foundry", + "title": "Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-foundry", "categories": [ - "Uncategorized" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md", - "html_url": "https://docs.polkadot.com/reference/tools/paraspell/", - "preview": "[ParaSpell](https://paraspell.github.io/docs/){target=\\_blank} is a comprehensive suite of open-source tools designed to simplify cross-chain interactions within the Polkadot ecosystem. At its core, ParaSpell is dedicated to enhancing the functionality of the [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} protocol by providing developers with a unified and streamlined experience for building interoperable decentralized applications (dApps).", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-foundry/", + "preview": "[Foundry](https://getfoundry.sh/){target=\\_blank} offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", "outline": [ { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Setup", + "anchor": "setup" }, { "depth": 3, - "title": "ParaSpell XCM SDK", - "anchor": "paraspell-xcm-sdk" + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 3005, - "words": 433, - "headings": 2, - "estimated_token_count_total": 669 + "chars": 2125, + "words": 276, + "headings": 6, + "estimated_token_count_total": 429 }, - "hash": "sha256:a7f9c4a03153ee637a0557d2cea0b622c849667ce793b1294bb3299cf036197d", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:f7687b9a1e80ab381cf4fb24f37cccfb98ddf139bf687e8832af99364ef0a8a9", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-polkadart", - "title": "Polkadart", - "slug": "reference-tools-polkadart", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat", + "title": "hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat", "categories": [ - "Tooling", - "Dapps" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md", - "html_url": "https://docs.polkadot.com/reference/tools/polkadart/", - "preview": "Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-hardhat/", + "preview": "[Hardhat](https://hardhat.org/){target=\\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", "outline": [ { - "depth": 2, - "title": "Installation", - "anchor": "installation" + "depth": 3, + "title": "Setup", + "anchor": "setup" }, { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "depth": 3, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" }, { "depth": 3, - "title": "Type Generation", - "anchor": "type-generation" + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { "depth": 3, - "title": "Run Generator", - "anchor": "run-generator" + "title": "Compile", + "anchor": "compile" }, { "depth": 3, - "title": "Use Generated Types", - "anchor": "use-generated-types" + "title": "Set Up Deployment", + "anchor": "set-up-deployment" }, { "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" + "title": "Deploy", + "anchor": "deploy" }, { "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 3336, + "words": 375, + "headings": 7, + "estimated_token_count_total": 672 + }, + "hash": "sha256:93ca24da15095dd0bb03657f53d27771934aee055c11af529445a50e161f79a3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-remix", + "title": "Remix IDE", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-remix", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-remix/", + "preview": "[Remix IDE](https://remix.live/){target=\\_blank} offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", + "outline": [ + { + "depth": 3, + "title": "Access Remix", + "anchor": "access-remix" }, { "depth": 3, - "title": "Subscribe to New Blocks", - "anchor": "subscribe-to-new-blocks" + "title": "Compile", + "anchor": "compile" }, { "depth": 3, - "title": "Send a Transaction", - "anchor": "send-a-transaction" + "title": "Deploy", + "anchor": "deploy" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 5178, - "words": 624, - "headings": 10, - "estimated_token_count_total": 1084 + "chars": 2473, + "words": 363, + "headings": 4, + "estimated_token_count_total": 527 }, - "hash": "sha256:7f533abe61586af8438e350c41b741d74a8edb839f9dc4139bc4619ba3748258", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:56d730c8a6d2ccf0324caf1c3f30929a93904f80e482cfcb457541e04482dbad", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-polkadot-js-api", - "title": "Polkadot.js API", - "slug": "reference-tools-polkadot-js-api", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-ethers", + "title": "Deploy a Basic Contract with Ethers.js", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-ethers", "categories": [ - "Tooling", - "Dapps" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md", - "html_url": "https://docs.polkadot.com/reference/tools/polkadot-js-api/", - "preview": "!!! warning \"Maintenance Mode Only\" The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank} (modern, type-safe API) as actively maintained alternatives.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-ethers.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/ethers/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, which provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications.", "outline": [ { "depth": 2, @@ -12823,97 +10668,126 @@ "anchor": "introduction" }, { - "depth": 3, - "title": "Dynamic API Generation", - "anchor": "dynamic-api-generation" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Available API Categories", - "anchor": "available-api-categories" + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 7370, + "words": 823, + "headings": 7, + "estimated_token_count_total": 1729 + }, + "hash": "sha256:ff8975b44870613c3aef0907df365f1ac981de74ec83019df232fe4bda6d9dbe", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-evm", + "title": "Deploy a Basic Contract to EVM", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-evm", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-evm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-evm/", + "preview": "Deploying smart contracts to the [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished using standard EVM development tools and workflows. This guide demonstrates how to deploy a basic smart contract using four popular EVM approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}, and [Foundry](https://getfoundry.sh/){ta", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Deployment options", + "anchor": "deployment-options" }, { - "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" - }, - { - "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" }, { "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 5042, - "words": 684, - "headings": 9, - "estimated_token_count_total": 1166 + "chars": 15629, + "words": 1659, + "headings": 4, + "estimated_token_count_total": 3341 }, - "hash": "sha256:ed3986f30880fefca5975fcdc847c68b4aca65862c63e3002b25391b0521781d", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:a4fd853afb897985602e0356551edacbce77db60bbc6556de3b6ae5af3fbc9e5", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-py-substrate-interface", - "title": "Python Substrate Interface", - "slug": "reference-tools-py-substrate-interface", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-foundry", + "title": "Deploy a Basic Contract with Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-foundry", "categories": [ - "Tooling", - "Dapps" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md", - "html_url": "https://docs.polkadot.com/reference/tools/py-substrate-interface/", - "preview": "The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Foundry](https://getfoundry.sh/){target=\\_blank}, which offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Configure Foundry", + "anchor": "configure-foundry" }, { - "depth": 3, - "title": "Establishing Connection", - "anchor": "establishing-connection" + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { - "depth": 3, - "title": "Reading Chain State", - "anchor": "reading-chain-state" + "depth": 2, + "title": "Compile", + "anchor": "compile" }, { - "depth": 3, - "title": "Submitting Transactions", - "anchor": "submitting-transactions" + "depth": 2, + "title": "Deploy", + "anchor": "deploy" }, { "depth": 2, @@ -12922,26 +10796,24 @@ } ], "stats": { - "chars": 4302, - "words": 541, + "chars": 2731, + "words": 355, "headings": 7, - "estimated_token_count_total": 942 + "estimated_token_count_total": 598 }, - "hash": "sha256:8987fc35cd28602054ee018031f773e2e3837425107c51d0e2ac68a94b86e9c0", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:63defd84f302f0778c90129abbe69ecd2a5d9d83c622f2b7e5c2ffc9bcb3312f", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-sidecar", - "title": "Sidecar REST API", - "slug": "reference-tools-sidecar", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", + "title": "Deploy a Basic Contract with Hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", "categories": [ - "Tooling", - "Dapps" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md", - "html_url": "https://docs.polkadot.com/reference/tools/sidecar/", - "preview": "The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Hardhat](https://hardhat.org/){target=\\_blank}, which provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", "outline": [ { "depth": 2, @@ -12955,18 +10827,33 @@ }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { "depth": 2, - "title": "Usage", - "anchor": "usage" + "title": "Configure Hardhat", + "anchor": "configure-hardhat" }, { - "depth": 3, - "title": "Endpoints", - "anchor": "endpoints" + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 2, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" }, { "depth": 2, @@ -12975,26 +10862,24 @@ } ], "stats": { - "chars": 7309, - "words": 1033, - "headings": 6, - "estimated_token_count_total": 1945 + "chars": 4051, + "words": 475, + "headings": 9, + "estimated_token_count_total": 981 }, - "hash": "sha256:0795462182cb97256bb5c2acb035855fe0d6557185de8ac99482725ecb4f94c1", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:98f5c5c1a26db913e1c4c435062d214ca8c4b5f2dbed5b64d2e54c3435f06452", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-subxt", - "title": "Subxt Rust API", - "slug": "reference-tools-subxt", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-pvm", + "title": "Deploy a Basic Contract to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-pvm", "categories": [ - "Tooling", - "Dapps" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md", - "html_url": "https://docs.polkadot.com/reference/tools/subxt/", - "preview": "Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-pvm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-pvm/", + "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", "outline": [ { "depth": 2, @@ -13003,72 +10888,139 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "JavaScript with Ethers.js", + "anchor": "javascript-with-ethersjs" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" + }, + { + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Remix IDE", + "anchor": "remix-ide" + }, + { + "depth": 3, + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Hardhat", + "anchor": "hardhat" }, { "depth": 3, - "title": "Download Chain Metadata", - "anchor": "download-chain-metadata" + "title": "Setup", + "anchor": "setup-2" }, { "depth": 3, - "title": "Generate Type-Safe Interfaces", - "anchor": "generate-type-safe-interfaces" + "title": "Configure Hardhat", + "anchor": "configure-hardhat" }, { "depth": 3, - "title": "Initialize the Subxt Client", - "anchor": "initialize-the-subxt-client" + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { "depth": 3, - "title": "Read Chain Data", - "anchor": "read-chain-data" + "title": "Compile", + "anchor": "compile-2" }, { "depth": 3, - "title": "Submit Transactions", - "anchor": "submit-transactions" + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy-2" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Foundry", + "anchor": "foundry" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup-3" + }, + { + "depth": 3, + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract-2" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile-3" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy-3" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 9174, - "words": 1175, - "headings": 10, - "estimated_token_count_total": 2187 + "chars": 13872, + "words": 1640, + "headings": 24, + "estimated_token_count_total": 3228 }, - "hash": "sha256:56269d9ea47f5b4e92cd7d5a1e65ab06d181a9c380f90bb3ef285529b12299f7", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:8f29b0f0b56f8c136206211a858cdc5bc27bcd9119eab179a6cd306182d910cb", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-xcm-tools", - "title": "XCM Tools", - "slug": "reference-tools-xcm-tools", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", + "title": "Deploy a Basic Contract with Remix IDE", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", "categories": [ - "Basics", - "Tooling", - "Dapps" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md", - "html_url": "https://docs.polkadot.com/reference/tools/xcm-tools/", - "preview": "As described in the [Interoperability](/develop/interoperability){target=\\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Remix IDE](https://remix.ethereum.org/){target=\\_blank}, which offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", "outline": [ { "depth": 2, @@ -13077,54 +11029,48 @@ }, { "depth": 2, - "title": "Popular XCM Tools", - "anchor": "popular-xcm-tools" - }, - { - "depth": 3, - "title": "Moonsong Labs XCM Tools", - "anchor": "moonsong-labs-xcm-tools" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "ParaSpell", - "anchor": "paraspell" + "depth": 2, + "title": "Access Remix", + "anchor": "access-remix" }, { - "depth": 3, - "title": "Astar XCM Tools", - "anchor": "astar-xcm-tools" + "depth": 2, + "title": "Compile", + "anchor": "compile" }, { - "depth": 3, - "title": "Chopsticks", - "anchor": "chopsticks" + "depth": 2, + "title": "Deploy", + "anchor": "deploy" }, { - "depth": 3, - "title": "Moonbeam XCM SDK", - "anchor": "moonbeam-xcm-sdk" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], - "stats": { - "chars": 7524, - "words": 1043, - "headings": 7, - "estimated_token_count_total": 1700 + "stats": { + "chars": 2978, + "words": 430, + "headings": 6, + "estimated_token_count_total": 738 }, - "hash": "sha256:47328231d6ff4dc52cd93aaf1baf5d0bc2d9fc372f3d79339d87aafa0dabd1b8", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:0c00544ba0be9c0a6fa0c54bdb38045d64e95af714785b86e57f885a03b4b17a", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-zombienet", - "title": "reference-tools-zombienet", - "slug": "reference-tools-zombienet", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic", + "title": "smart-contracts-cookbook-smart-contracts-deploy-basic", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md", - "html_url": "https://docs.polkadot.com/reference/tools/zombienet/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/", "preview": "TODO", "outline": [], "stats": { @@ -13134,29 +11080,49 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:15+00:00", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-connect", - "title": "Connect to Polkadot", - "slug": "smart-contracts-connect", + "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", + "title": "Deploy an ERC-20 to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", "categories": [ + "Basics", "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-connect.md", - "html_url": "https://docs.polkadot.com/smart-contracts/connect/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/", + "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", "outline": [ { "depth": 2, - "title": "Networks Details", - "anchor": "networks-details" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Test Tokens", - "anchor": "test-tokens" + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Interact with Your Contract", + "anchor": "interact-with-your-contract" }, { "depth": 2, @@ -13165,131 +11131,108 @@ } ], "stats": { - "chars": 3459, - "words": 476, - "headings": 3, - "estimated_token_count_total": 558 + "chars": 9109, + "words": 1260, + "headings": 7, + "estimated_token_count_total": 2182 }, - "hash": "sha256:a2490223926957381913ae0ed22e2df3611a6713ec9d77a3015d1cd6a578b3f6", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:0cb418d465a51230ece5d3a56d64754f979bc6c4ad78f2cc3df537b99739e627", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-dapps-zero-to-hero", - "title": "Zero to Hero Smart Contract DApp", - "slug": "smart-contracts-cookbook-dapps-zero-to-hero", + "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20", + "title": "Deploy an ERC-20 to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20", "categories": [ - "dApp", - "Tooling" + "Basics", + "dApps", + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/dapps/zero-to-hero/", - "preview": "Decentralized applications (dApps) are a key component of the Web3 ecosystem, enabling developers to build applications that communicate directly with blockchain networks. Polkadot Hub, a blockchain with smart contract support, serves as a robust platform for deploying and interacting with dApps.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Project Overview", - "anchor": "project-overview" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Create and Deploy the Storage Contract", - "anchor": "create-and-deploy-the-storage-contract" - }, - { - "depth": 3, - "title": "Set Up Hardhat Project", - "anchor": "set-up-hardhat-project" - }, - { - "depth": 3, - "title": "Create the Storage Contract", - "anchor": "create-the-storage-contract" - }, - { - "depth": 3, - "title": "Configure Hardhat for Polkadot Hub", - "anchor": "configure-hardhat-for-polkadot-hub" + "title": "Create the ERC-20 Contract", + "anchor": "create-the-erc-20-contract" }, { - "depth": 3, + "depth": 2, "title": "Compile the Contract", "anchor": "compile-the-contract" }, { - "depth": 3, + "depth": 2, "title": "Deploy the Contract", "anchor": "deploy-the-contract" }, - { - "depth": 3, - "title": "Export the Contract ABI", - "anchor": "export-the-contract-abi" - }, - { - "depth": 2, - "title": "Set Up the dApp Project", - "anchor": "set-up-the-dapp-project" - }, - { - "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" - }, { "depth": 2, - "title": "Connect to Polkadot Hub", - "anchor": "connect-to-polkadot-hub" - }, + "title": "Interact with Your ERC-20 Contract", + "anchor": "interact-with-your-erc-20-contract" + } + ], + "stats": { + "chars": 8926, + "words": 1207, + "headings": 6, + "estimated_token_count_total": 2107 + }, + "hash": "sha256:296cba75b1d49aefa1b8636ba95ca20c3431b7eb0e93b0658add671ef5801732", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-ethers", + "title": "Deploy an NFT to Polkadot Hub with Ethers.js", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-ethers", + "categories": [ + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-ethers.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/ethers/", + "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", + "outline": [ { "depth": 2, - "title": "Set Up the Smart Contract Interface", - "anchor": "set-up-the-smart-contract-interface" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Create the Wallet Connection Component", - "anchor": "create-the-wallet-connection-component" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Create the Read Contract Component", - "anchor": "create-the-read-contract-component" + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { "depth": 2, - "title": "Create the Write Contract Component", - "anchor": "create-the-write-contract-component" + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { "depth": 2, - "title": "How It Works", - "anchor": "how-it-works" - }, - { - "depth": 3, - "title": "Wallet Connection", - "anchor": "wallet-connection" - }, - { - "depth": 3, - "title": "Data Reads", - "anchor": "data-reads" - }, - { - "depth": 3, - "title": "Data Writes", - "anchor": "data-writes" + "title": "Compile", + "anchor": "compile" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Deploy", + "anchor": "deploy" }, { "depth": 2, @@ -13298,26 +11241,25 @@ } ], "stats": { - "chars": 31203, - "words": 3688, - "headings": 22, - "estimated_token_count_total": 6967 + "chars": 8114, + "words": 912, + "headings": 7, + "estimated_token_count_total": 2015 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:fdd65f6fe6d109043f11a26f1477e2bbbce1a440dbcb2b191eacfa79a28766e9", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-eth-dapps-uniswap-v2", - "title": "Deploying Uniswap V2 on Polkadot", - "slug": "smart-contracts-cookbook-eth-dapps-uniswap-v2", + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-foundry", + "title": "Deploy an NFT to Polkadot Hub with Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-foundry", "categories": [ - "dApps", - "Tooling" + "Basics", + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/foundry/", + "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", "outline": [ { "depth": 2, @@ -13331,73 +11273,55 @@ }, { "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { "depth": 2, - "title": "Understanding Uniswap V2 Architecture", - "anchor": "understanding-uniswap-v2-architecture" + "title": "Configure Foundry", + "anchor": "configure-foundry" }, { "depth": 2, - "title": "Test the Contracts", - "anchor": "test-the-contracts" + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { "depth": 2, - "title": "Deploy the Contracts", - "anchor": "deploy-the-contracts" + "title": "Compile", + "anchor": "compile" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 11280, - "words": 1560, - "headings": 7, - "estimated_token_count_total": 2671 - }, - "hash": "sha256:2a42198668c759f63aa602115bf2d290ec7d03bbc3a3df20e30e85027e1b1cc3", - "last_modified": "2025-10-28T14:42:15+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic", - "title": "smart-contracts-cookbook-smart-contracts-deploy-basic", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 3489, + "words": 438, + "headings": 8, + "estimated_token_count_total": 847 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:c4b410125946db479b9c262a5132a31bb7730a778501c3a95910ad9d38007cf4", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20", - "title": "Deploy an ERC-20 to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20", + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", + "title": "Deploy an NFT to Polkadot Hub with Hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", "categories": [ "Basics", - "dApps", "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/", + "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", "outline": [ { "depth": 2, @@ -13411,45 +11335,59 @@ }, { "depth": 2, - "title": "Create the ERC-20 Contract", - "anchor": "create-the-erc-20-contract" + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { "depth": 2, - "title": "Compile the Contract", - "anchor": "compile-the-contract" + "title": "Configure Hardhat", + "anchor": "configure-hardhat" }, { "depth": 2, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { "depth": 2, - "title": "Interact with Your ERC-20 Contract", - "anchor": "interact-with-your-erc-20-contract" + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 8926, - "words": 1207, - "headings": 6, - "estimated_token_count_total": 2107 + "chars": 4745, + "words": 550, + "headings": 9, + "estimated_token_count_total": 1137 }, - "hash": "sha256:296cba75b1d49aefa1b8636ba95ca20c3431b7eb0e93b0658add671ef5801732", - "last_modified": "2025-10-28T14:42:15+00:00", + "hash": "sha256:f787f9c66787c53aa5c6fccf30d622b2b617794d1292641ea256e0896d418b28", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-ethers", - "title": "Deploy an NFT to Polkadot Hub with Ethers.js", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-ethers", + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", + "title": "Deploy an NFT to Polkadot Hub with Remix", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", "categories": [ "Basics", "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-ethers.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/ethers/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/", "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", "outline": [ { @@ -13464,8 +11402,8 @@ }, { "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" + "title": "Access Remix", + "anchor": "access-remix" }, { "depth": 2, @@ -13489,13 +11427,50 @@ } ], "stats": { - "chars": 8114, - "words": 912, + "chars": 3754, + "words": 505, "headings": 7, - "estimated_token_count_total": 2015 + "estimated_token_count_total": 928 + }, + "hash": "sha256:12a8debfbc05c5ac0e2c94daa40167adab837dc4e1b2731f5b48ae8bc9bc2c93", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook", + "title": "Smart Contracts Cookbook Index", + "slug": "smart-contracts-cookbook", + "categories": [ + "Basics", + "dApps", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/", + "preview": "Welcome to the Polkadot smart contracts cookbook index.", + "outline": [ + { + "depth": 2, + "title": "Get Tokens from the Faucet", + "anchor": "get-tokens-from-the-faucet" + }, + { + "depth": 2, + "title": "EVM/PVM Smart Contracts", + "anchor": "evmpvm-smart-contracts" + }, + { + "depth": 2, + "title": "Port Ethereum DApps", + "anchor": "port-ethereum-dapps" + } + ], + "stats": { + "chars": 1586, + "words": 204, + "headings": 3, + "estimated_token_count_total": 406 }, - "hash": "sha256:4e3ac6affdbe93ce9d132cbb838be1dfaf7a629b0e1f10ce4d90cc3899d656cb", - "last_modified": "2025-10-28T14:42:16+00:00", + "hash": "sha256:ea0d085c376117436a9cf68e786da942cf88993651d4e06550f9ee03d2e810f4", "token_estimator": "heuristic-v1" }, { @@ -13516,7 +11491,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13537,7 +11511,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13614,7 +11587,6 @@ "estimated_token_count_total": 6228 }, "hash": "sha256:72e41f816f07026d96c803f399c71852aa1151c464e79cec3e1746b282d5eaae", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13635,7 +11607,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13656,7 +11627,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13677,7 +11647,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13698,7 +11667,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13719,7 +11687,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13797,7 +11764,6 @@ "estimated_token_count_total": 4190 }, "hash": "sha256:1729ad83ad381a90752540644d400c60add3555e5da296ab455442be81d32f8c", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13818,7 +11784,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13839,7 +11804,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13860,7 +11824,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13902,7 +11865,6 @@ "estimated_token_count_total": 2430 }, "hash": "sha256:e3d8b84cb2cee7010978582998b2269296a042aec53fb016388690ab6adf355e", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13923,7 +11885,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -13986,7 +11947,6 @@ "estimated_token_count_total": 1347 }, "hash": "sha256:7589fa1dbdbf5748892ab6d42fc784d833f33e254bd3f95ee58424effcd38323", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14007,7 +11967,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14028,7 +11987,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14071,7 +12029,6 @@ "estimated_token_count_total": 309 }, "hash": "sha256:93e8a3043d65583e3d66f8f5f0ed6f4ef89a908ef85da2b6ca906a1100b7dded", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14108,7 +12065,6 @@ "estimated_token_count_total": 313 }, "hash": "sha256:c609bc98cba5efa2d2a808548cf93ad9d0a06455b35a8fd9f534daf52824f506", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14176,7 +12132,6 @@ "estimated_token_count_total": 1818 }, "hash": "sha256:f50cd1177dd4aff8eb031d6f21cb640f8187a7f2dd0edcaef5c73354a378e44d", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14239,7 +12194,6 @@ "estimated_token_count_total": 1182 }, "hash": "sha256:9542f40acae725e628f4c3155ad1e7e0e18b2eb518484856ad439a1d9f86d1f3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14322,7 +12276,6 @@ "estimated_token_count_total": 1133 }, "hash": "sha256:0792e3956242eb8e08ab82e2d73964c381074cc8b1ea46f396d136856fa6cc07", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14436,7 +12389,6 @@ "estimated_token_count_total": 1046 }, "hash": "sha256:dd29fab6e3c00d720b10effa4e50373a6fe9ab4b7bfd3aea892c7fa9c84318a2", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14633,28 +12585,87 @@ "estimated_token_count_total": 9750 }, "hash": "sha256:1fb7a20bc4a799a771954720428029419ec73afa640e589590c43dd041a7e307", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { "id": "smart-contracts-for-eth-devs-migration", - "title": "smart-contracts-for-eth-devs-migration", + "title": "Migration FAQs and Considerations", "slug": "smart-contracts-for-eth-devs-migration", "categories": [ - "Uncategorized" + "Smart Contracts" ], "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md", "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/", - "preview": "TODO", - "outline": [], + "preview": "This guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Migration Considerations", + "anchor": "migration-considerations" + }, + { + "depth": 2, + "title": "Migration Checklist", + "anchor": "migration-checklist" + }, + { + "depth": 2, + "title": "Migration FAQs", + "anchor": "migration-faqs" + }, + { + "depth": 3, + "title": "Which backend should I choose?", + "anchor": "which-backend-should-i-choose" + }, + { + "depth": 3, + "title": "Do I need to rewrite my Solidity code?", + "anchor": "do-i-need-to-rewrite-my-solidity-code" + }, + { + "depth": 3, + "title": "What about factory contracts?", + "anchor": "what-about-factory-contracts" + }, + { + "depth": 3, + "title": "How do gas costs compare?", + "anchor": "how-do-gas-costs-compare" + }, + { + "depth": 3, + "title": "Which Solidity features are not supported?", + "anchor": "which-solidity-features-are-not-supported" + }, + { + "depth": 3, + "title": "How do I handle the existential deposit?", + "anchor": "how-do-i-handle-the-existential-deposit" + }, + { + "depth": 3, + "title": "Can I use my existing development tools?", + "anchor": "can-i-use-my-existing-development-tools" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } + ], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 6247, + "words": 803, + "headings": 12, + "estimated_token_count_total": 1322 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", + "hash": "sha256:bf9b21750158389c387b92f2165947e5f5cff752f5d163680ee37493710e81d7", "token_estimator": "heuristic-v1" }, { @@ -14712,7 +12723,6 @@ "estimated_token_count_total": 2840 }, "hash": "sha256:224a9f69d4613a5f1afdbc1f05379add8321fe159e32c71db003bbe08ff8e976", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14733,7 +12743,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14754,7 +12763,6 @@ "estimated_token_count_total": 0 }, "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14807,7 +12815,6 @@ "estimated_token_count_total": 1627 }, "hash": "sha256:65809486f62f60c6a6ac8109f9f027361683c23f639991a045ec5c057b665026", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14895,7 +12902,6 @@ "estimated_token_count_total": 4474 }, "hash": "sha256:c74a28d8d62369591c5734535136508db3d1f7380e486fd214f98d433cafd6e7", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -14988,7 +12994,6 @@ "estimated_token_count_total": 3891 }, "hash": "sha256:e27657e4e4a14fe86f424b96631946ec36fb90d277e6010b6cbd64c4769aba8a", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -15061,7 +13066,6 @@ "estimated_token_count_total": 3250 }, "hash": "sha256:bc771f912627fa09cad64adab1bc81c052f650d6c5a3b4f0c91883a98f6628da", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -15134,7 +13138,6 @@ "estimated_token_count_total": 3035 }, "hash": "sha256:f0d36333d0d3afff7f6374a61d0f6d1fb878c9ef4c4e4c24447745661dbe59d0", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -15187,7 +13190,6 @@ "estimated_token_count_total": 2509 }, "hash": "sha256:205892e350168b3d0da7ccc280c67c3217ad1e45e87a53d124fa1dd69661aa5e", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -15260,7 +13262,6 @@ "estimated_token_count_total": 1122 }, "hash": "sha256:ee87115c828928c82937de26f5f938cecd4c3bb1225fdb61627e8092e6ea5951", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -15272,37 +13273,36 @@ ], "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-eth-native.md", "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/eth-native/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-precompiles-staking", - "title": "smart-contracts-precompiles-staking", - "slug": "smart-contracts-precompiles-staking", - "categories": [ - "Uncategorized" + "preview": "Ethereum-native precompiles are special contract implementations that provide essential cryptographic and utility functions at the runtime level. These precompiles are available at predefined addresses and offer optimized, native implementations of commonly used operations that would be computationally expensive or impractical to implement in pure contract code.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "How to Use Precompiles", + "anchor": "how-to-use-precompiles" + }, + { + "depth": 2, + "title": "Standard Precompiles in Polkadot Hub", + "anchor": "standard-precompiles-in-polkadot-hub" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-staking.md", - "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/staking/", - "preview": "TODO", - "outline": [], "stats": { "chars": 5232, "words": 532, "headings": 4, "estimated_token_count_total": 1192 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "last_modified": "2025-10-28T14:42:16+00:00", + "hash": "sha256:f17db5daca8feae70ce428e03a5a4870ef87dfc8571b07376327cd80d057b759", "token_estimator": "heuristic-v1" }, { @@ -15368,8 +13368,43 @@ "headings": 9, "estimated_token_count_total": 2325 }, - "hash": "sha256:4856172c6356357818234a3b7f0828716bd32e6192f3609c51de0cafcc5a75e7", - "last_modified": "2025-10-28T14:42:16+00:00", + "hash": "sha256:c084190ea7d676128e7e399e8fe88598ca150f88d684db279a687ee1c3956120", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-precompiles", + "title": "Advanced Functionalities via Precompiles", + "slug": "smart-contracts-precompiles", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles.md", + "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "What are Precompiles?", + "anchor": "what-are-precompiles" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } + ], + "stats": { + "chars": 2525, + "words": 328, + "headings": 3, + "estimated_token_count_total": 412 + }, + "hash": "sha256:a40e3f34f70db22bfe39e40d68dc5a53a726ce47cb73b602d8605355c61ffd22", "token_estimator": "heuristic-v1" }, { @@ -15436,7 +13471,6 @@ "estimated_token_count_total": 2249 }, "hash": "sha256:1368f6d49bccb7ba0e642cc58ea2c97ca95ae45e390cb9fa2ab11b0b41de52f4", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -15467,9 +13501,7 @@ "headings": 2, "estimated_token_count_total": 198 }, - "hash": "sha256:96acff10be56dea76acdb5c915c1dde0eb15eb12eb95e7871eef56bab6cda273", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:467765777cace42ab4e3f1bb36c94f97e655c5d2cd570e00dd747c6a3db043f7", "token_estimator": "heuristic-v1" }, { @@ -15505,9 +13537,7 @@ "headings": 3, "estimated_token_count_total": 208 }, - "hash": "sha256:61bc251929352f2299ca1d413d05aa9c3672b914575a285d73c7ba53dbd75bff", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:3a6704a6330c6e35aa98fe8d615e2e27beb870a48c68bda02c217e6ae77274d2", "token_estimator": "heuristic-v1" }, { @@ -15568,9 +13598,7 @@ "headings": 8, "estimated_token_count_total": 2764 }, - "hash": "sha256:370ed10155cee84889a6d230d0bc3476597448f88a2a271ab87ef893a3268c18", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:a2bba0ba575bd7e3f7199282ea5994087acf2c62e828f316e6eb62c9a43449e1", "token_estimator": "heuristic-v1" }, { @@ -15596,9 +13624,7 @@ "headings": 1, "estimated_token_count_total": 12 }, - "hash": "sha256:086a87823ab67ceac102358030e316583cd733c0ec326316e7f29061fe7f6934", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:917ce0777f8ac5a4288e54ce4086432d320b127a7fc753ade5392d766a1f3c33", "token_estimator": "heuristic-v1" }, { @@ -15639,8 +13665,7 @@ "headings": 4, "estimated_token_count_total": 339 }, - "hash": "sha256:a2bba0ba575bd7e3f7199282ea5994087acf2c62e828f316e6eb62c9a43449e1", - "last_modified": "2025-10-28T14:42:16+00:00", + "hash": "sha256:9559f240b9433b496bfea92b57394a75c28bc743bb756c231f0137dfdf077e4a", "token_estimator": "heuristic-v1" }, { @@ -15722,7 +13747,6 @@ "estimated_token_count_total": 34492 }, "hash": "sha256:bef820acfe429d4a847a8de82de6c70155ac6b3ad5ebdd574a2157923b45f688", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -15753,9 +13777,7 @@ "headings": 2, "estimated_token_count_total": 125 }, - "hash": "sha256:d2f3ab658ab29514ac161b17df23e0e7c1f63a7fa4fefcef451ef80b413ab757", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:c675e4231537732f24d1dd93f2b248398248a77c9877860fe53926e255ed0710", "token_estimator": "heuristic-v1" }, { @@ -15848,7 +13870,6 @@ "estimated_token_count_total": 5338 }, "hash": "sha256:b3530f5fc5c9e916181dbc259a7fbae9c60100cb0450fc6d47bbb0d140afa075", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -15920,7 +13941,6 @@ "estimated_token_count_total": 4358 }, "hash": "sha256:87b19f6e881611329b7015e8d8187d7d85b2b2ef14b01e832c8b8e20897e3b40", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -15977,7 +13997,6 @@ "estimated_token_count_total": 2138 }, "hash": "sha256:ff2c267284959711782c0d6ecb4b439c3a6cc31f763d5e1ff2cc3b1f6efb62b2", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -16029,7 +14048,6 @@ "estimated_token_count_total": 2929 }, "hash": "sha256:df60044893f48dd7f37a11de275a16bf32adb31317ed70a789fd7fac64150e1a", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -16121,7 +14139,6 @@ "estimated_token_count_total": 4789 }, "hash": "sha256:81750202081ff24447f4e129c49230eedb315d1b44c740b677c3495a8f7adb9a", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -16203,7 +14220,6 @@ "estimated_token_count_total": 2452 }, "hash": "sha256:1eb463c6b2732ebed0d16165425cde438688d21cc302f759b40250850c2a5e83", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -16266,7 +14282,6 @@ "estimated_token_count_total": 3255 }, "hash": "sha256:fe94de6f97fb588552f6cbc6b1a4c7399e91f5f31585f61a0dee66f5f50ff8a0", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -16292,9 +14307,7 @@ "headings": 1, "estimated_token_count_total": 42 }, - "hash": "sha256:2f11054e0d31c003ebae5d990b559bd56741d190ca409f6ad060216245fa2d17", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:06acc146698c1d3224544987d7ee52da498e3179228f98a494e385c5786a3a2c", "token_estimator": "heuristic-v1" }, { @@ -16330,9 +14343,7 @@ "headings": 3, "estimated_token_count_total": 107 }, - "hash": "sha256:a6a535f4f5e145d3e2a7518739f752ee3ed37b7745483f414e21c97792331d18", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:fdd391227992c966de25b9240f5492135a9993859ec42b77952c1aa3d2e39ed9", "token_estimator": "heuristic-v1" }, { @@ -16373,9 +14384,7 @@ "headings": 4, "estimated_token_count_total": 400 }, - "hash": "sha256:3ad540d8ad636304705cccb08bc1fdf21fe2fc7dc0f99bd509b23ae96d20e0ba", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:2fc6f513fd8b269e586b754b2bdbd2af9df5178624a028fab940a385f3fee577", "token_estimator": "heuristic-v1" }, { @@ -16411,8 +14420,7 @@ "headings": 3, "estimated_token_count_total": 211 }, - "hash": "sha256:388c988338ed84589c546bb1606d08641fb931dae307d3df92aeccd2e4986080", - "last_modified": "2025-10-28T14:15:59+00:00", + "hash": "sha256:5d45ec9f8efda8c4bc2d0c21399a036d017a03540e7efab60d4710cb7eb33eb3", "token_estimator": "heuristic-v1" }, { @@ -16481,7 +14489,6 @@ "estimated_token_count_total": 2702 }, "hash": "sha256:1f8ab387f721d865a7ca75eaa2528f1f2ebd4528a7d65ffeb27c68953100a3cb", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -16550,7 +14557,6 @@ "estimated_token_count_total": 2564 }, "hash": "sha256:97dadddf4c27f469f552875461fc54d331fa151e4656401e15d6d4173115eecf", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -16581,9 +14587,7 @@ "headings": 2, "estimated_token_count_total": 80 }, - "hash": "sha256:07629376480e74afc7fe4d91df539b6ab22453df0f8143df11cc51ef9a78f736", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:1dfbb8c3cfa27f92e982b4ce705415e117c50eb38f641691129863b474741da7", "token_estimator": "heuristic-v1" }, { @@ -16619,9 +14623,7 @@ "headings": 3, "estimated_token_count_total": 256 }, - "hash": "sha256:cf9197d6909dd8865e8838cad95e3692fefaecc3d2f4773b26809a02051d620f", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:d63121126e51c785f0dfd4ae4ecd49cb71640515d39df69a0689f30a7ab8122f", "token_estimator": "heuristic-v1" }, { @@ -16647,9 +14649,7 @@ "headings": 1, "estimated_token_count_total": 12 }, - "hash": "sha256:aa6371024bb78c3eeedb6820a37859670046fd0e4f756ad417b20c39fb2983b9", - "last_modified": "2025-10-27T18:04:05+00:00", - "last_modified": "2025-10-27T18:04:05+00:00", + "hash": "sha256:94dbafb2d78b87d5f0f0c75de002501b8210ac8d66072bc07989f685837cbac5", "token_estimator": "heuristic-v1" }, { @@ -16702,7 +14702,6 @@ "estimated_token_count_total": 1760 }, "hash": "sha256:9cf70459e921b8b231a3f2e7a7c1d47a4917e45f0c4d0fe873ad4062fd540a9a", - "last_modified": "2025-10-28T14:42:16+00:00", "token_estimator": "heuristic-v1" }, { @@ -16775,7 +14774,6 @@ "estimated_token_count_total": 5118 }, "hash": "sha256:de7fde61d4cac9c28634ee496dcabe116fe44b1b87408f202103290d78247c05", - "last_modified": "2025-10-28T14:42:18+00:00", "token_estimator": "heuristic-v1" }, { @@ -16858,7 +14856,6 @@ "estimated_token_count_total": 6206 }, "hash": "sha256:cb8ddb4a61f6a62182420b69382f1c7ab2adc2f4ae643f7f68c6867680afe81f", - "last_modified": "2025-10-28T14:42:19+00:00", "token_estimator": "heuristic-v1" }, { @@ -16921,7 +14918,114 @@ "estimated_token_count_total": 4135 }, "hash": "sha256:ca1d65d450f086a0eb7b81e9589e9894e04b217fe9709a1b464f09beb3ca9dc2", - "last_modified": "2025-10-28T14:42:20+00:00", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-smart-contracts-launch-your-first-project", + "title": "Launch Your First Project", + "slug": "tutorials-smart-contracts-launch-your-first-project", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project.md", + "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Kickstart your journey into smart contract development with this comprehensive guide. Learn how to create, deploy, and interact with contracts on Polkadot. Whether you're new to smart contracts or refining your skills, these guides provide a structured approach to launching your project.", + "outline": [ + { + "depth": 2, + "title": "Development Pathway", + "anchor": "development-pathway" + }, + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 1211, + "words": 161, + "headings": 2, + "estimated_token_count_total": 77 + }, + "hash": "sha256:8d8fc5f794d4c793586cd3d412627f5e2fe76f182c75c3687abcf33deed5d65e", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-smart-contracts", + "title": "Smart Contracts", + "slug": "tutorials-smart-contracts", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts.md", + "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Get started with deploying and interacting with smart contracts on Polkadot through practical, hands-on tutorials. Whether you're a beginner or an experienced developer, these guides will help you navigate the entire development lifecycle.", + "outline": [ + { + "depth": 2, + "title": "What to Expect from These Tutorials", + "anchor": "what-to-expect-from-these-tutorials" + }, + { + "depth": 2, + "title": "Start Building", + "anchor": "start-building" + }, + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 1057, + "words": 145, + "headings": 3, + "estimated_token_count_total": 130 + }, + "hash": "sha256:66bc34a12c50539dde2ffc69fe66891f73d3e1a2da5833ada15e26744ff32209", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials", + "title": "Tutorials", + "slug": "tutorials", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials.md", + "html_url": "https://docs.polkadot.com/tutorials/", + "preview": "Welcome to the Polkadot Tutorials hub! Whether you’re building parachains, integrating system chains, or developing decentralized applications, these step-by-step guides are designed to help you achieve your goals efficiently and effectively.", + "outline": [ + { + "depth": 2, + "title": "Polkadot Zero to Hero", + "anchor": "polkadot-zero-to-hero" + }, + { + "depth": 3, + "title": "Parachain Developers", + "anchor": "parachain-developers" + }, + { + "depth": 2, + "title": "Featured Tutorials", + "anchor": "featured-tutorials" + }, + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 2501, + "words": 355, + "headings": 4, + "estimated_token_count_total": 590 + }, + "hash": "sha256:a1d7789d44e4653e98ed41b8a13ea69e7733803c598ca850c9e2fc8f27a2b410", "token_estimator": "heuristic-v1" } ] \ No newline at end of file diff --git a/llms-full.jsonl b/llms-full.jsonl index e7b3d0dd6..d53094e48 100644 --- a/llms-full.jsonl +++ b/llms-full.jsonl @@ -552,25 +552,66 @@ {"page_id": "parachains-customize-runtime-add-pallet-instances", "page_title": "Add Multiple Pallet Instances", "index": 18, "depth": 3, "title": "Interact with Both Pallet Instances", "anchor": "interact-with-both-pallet-instances", "start_char": 15206, "end_char": 16561, "estimated_token_count": 358, "token_estimator": "heuristic-v1", "text": "### Interact with Both Pallet Instances\n\nUse the Polkadot.js Apps interface to verify you can interact with both pallet instances independently.\n\nTo interact with the pallet instances:\n\n1. Navigate to [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/extrinsics){target=\\_blank}.\n2. Ensure you're connected to your local node at `ws://127.0.0.1:9944`.\n3. Go to the **Developer** > **Extrinsics** tab.\n4. In the **submit the following extrinsic** section, open the pallet dropdown. Verify that both pallet instances appear and contain the expected extrinsics.\n\n === \"Technical Committee\"\n\n Select **`technicalCommittee`** and open the extrinsics dropdown.\n\n ![](/images/parachains/customize-runtime/add-pallet-instances/add-pallet-instances-01.webp)\n\n === \"Council\"\n\n Select **`council`** and open the extrinsics dropdown.\n\n ![](/images/parachains/customize-runtime/add-pallet-instances/add-pallet-instances-02.webp)\n\nEach instance should display the following extrinsics (this is not an exhaustive list):\n\n- **`close(proposalHash, index, proposalWeightBound, lengthBound)`**: Close voting.\n- **`propose(threshold, proposal, lengthBound)`**: Submit a proposal.\n- **`setMembers(newMembers, prime, oldCount)`**: Update membership.\n- **`vote(proposal, index, approve)`**: Vote on a proposal."} {"page_id": "parachains-customize-runtime-add-pallet-instances", "page_title": "Add Multiple Pallet Instances", "index": 19, "depth": 3, "title": "Test Instance Independence", "anchor": "test-instance-independence", "start_char": 16561, "end_char": 17619, "estimated_token_count": 227, "token_estimator": "heuristic-v1", "text": "### Test Instance Independence\n\nVerify that both instances operate independently by testing their separate functionality.\n\nTo test instance independence:\n\n1. In Polkadot.js Apps, go to **Developer** > **Chain state**.\n2. Query storage for each instance:\n\n === \"Technical Committee\"\n\n Select **`technicalCommittee` > `members()`** to view technical committee members.\n\n ![](/images/parachains/customize-runtime/add-pallet-instances/add-pallet-instances-03.webp)\n\n === \"Council\"\n\n Select **`council` > `members()`** to view council members.\n\n ![](/images/parachains/customize-runtime/add-pallet-instances/add-pallet-instances-04.webp)\n\n3. Verify that:\n - Each instance maintains separate storage.\n - Changes to one instance don't affect the other.\n - Both instances can process proposals simultaneously.\n\nYou can now use both collective instances for different governance purposes in your parachain, such as technical decisions that require expertise and general governance decisions that require broader consensus."} {"page_id": "parachains-customize-runtime-add-pallet-instances", "page_title": "Add Multiple Pallet Instances", "index": 20, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 17619, "end_char": 17923, "estimated_token_count": 82, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Guide __Make a Custom Pallet__\n\n ---\n\n Learn how to create custom pallets using FRAME.\n\n [:octicons-arrow-right-24: Reference](/parachains/customize-runtime/pallet-development/create-a-pallet/)\n\n
"} -{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 36, "end_char": 704, "estimated_token_count": 118, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nWhen building your custom blockchain with the Polkadot SDK, you have the flexibility to add smart contract capabilities through specialized pallets. These pallets allow blockchain users to deploy and execute smart contracts, enhancing your chain's functionality and programmability.\n\nPolkadot SDK-based blockchains support two distinct smart contract execution environments: [EVM (Ethereum Virtual Machine)](#evm-smart-contracts) and [Wasm (WebAssembly)](#wasm-smart-contracts). Each environment allows developers to deploy and execute different types of smart contracts, providing flexibility in choosing the most suitable solution for their needs."} -{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 1, "depth": 2, "title": "EVM Smart Contracts", "anchor": "evm-smart-contracts", "start_char": 704, "end_char": 1957, "estimated_token_count": 327, "token_estimator": "heuristic-v1", "text": "## EVM Smart Contracts\n\nTo enable Ethereum-compatible smart contracts in your blockchain, you'll need to integrate [Frontier](https://github.com/polkadot-evm/frontier){target=\\_blank}, the Ethereum compatibility layer for Polkadot SDK-based chains. This requires adding two essential pallets to your runtime:\n\n- **[`pallet-evm`](https://github.com/polkadot-evm/frontier/tree/master/frame/evm){target=\\_blank}**: Provides the EVM execution environment.\n- **[`pallet-ethereum`](https://github.com/polkadot-evm/frontier/tree/master/frame/ethereum){target=\\_blank}**: Handles Ethereum-formatted transactions and RPC capabilities.\n\nFor step-by-step guidance on adding these pallets to your runtime, refer to [Add a Pallet to the Runtime](/parachains/customize-runtime/add-existing-pallets/){target=\\_blank}.\n\nFor a real-world example of how these pallets are implemented in production, you can check Moonbeam's implementation of [`pallet-evm`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L532){target=\\_blank} and [`pallet-ethereum`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L698){target=\\_blank}."} -{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 2, "depth": 2, "title": "Wasm Smart Contracts", "anchor": "wasm-smart-contracts", "start_char": 1957, "end_char": 2772, "estimated_token_count": 197, "token_estimator": "heuristic-v1", "text": "## Wasm Smart Contracts\n\nTo support Wasm-based smart contracts, you'll need to integrate:\n\n- **[`pallet-contracts`](https://docs.rs/pallet-contracts/latest/pallet_contracts/index.html#contracts-pallet){target=\\_blank}**: Provides the Wasm smart contract execution environment.\n\nThis pallet enables the deployment and execution of Wasm-based smart contracts on your blockchain. For detailed instructions on adding this pallet to your runtime, see [Add a Pallet to the Runtime](/parachains/customize-runtime/add-existing-pallets/){target=\\_blank}.\n\nFor a real-world example of how this pallet is implemented in production, you can check Astar's implementation of [`pallet-contracts`](https://github.com/AstarNetwork/Astar/blob/b6f7a408d31377130c3713ed52941a06b5436402/runtime/astar/src/lib.rs#L693){target=\\_blank}."} -{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 3, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 2772, "end_char": 3865, "estimated_token_count": 259, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nNow that you understand how to enable smart contract functionality in your blockchain, you might want to:\n\n
\n\n- Guide __Get Started with Smart Contracts__\n\n ---\n\n Learn how developers can build smart contracts on Polkadot by leveraging the PolkaVM, Wasm/ink! or EVM contracts across many parachains.\n\n [:octicons-arrow-right-24: Reference](/smart-contracts/get-started/)\n\n- Guide __Wasm (ink!) Contracts__\n\n ---\n\n Learn to build Wasm smart contracts with ink!, a Rust-based eDSL. Explore installation, contract structure, and key features.\n\n [:octicons-arrow-right-24: Reference](/smart-contracts/overview/#wasm-ink)\n \n- Guide __EVM Contracts__\n\n ---\n\n Learn how Polkadot parachains such as Moonbeam, Astar, Acala, and Manta leverage the Ethereum Virtual Machine (EVM) and integrate it into their parachains.\n\n [:octicons-arrow-right-24: Reference](/smart-contracts/overview/#parachain-contracts)\n\n
"} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 36, "end_char": 724, "estimated_token_count": 139, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nWhen building your custom blockchain with the Polkadot SDK, you can add smart contract capabilities through specialized pallets. These pallets enable users to deploy and execute smart contracts, enhancing your chain's programmability and allowing developers to build decentralized applications on your network.\n\nThis guide covers three approaches to adding smart contracts to your blockchain:\n\n- **[`pallet-revive`](#pallet-revive)**: Modern unified solution supporting both PolkaVM and EVM bytecode\n- **[Frontier](#frontier)**: Ethereum compatibility layer for Polkadot SDK-based chains\n- **[`pallet-contracts`](#pallet-contracts-legacy)**: Wasm smart contract support"} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 1, "depth": 2, "title": "pallet-revive", "anchor": "pallet-revive", "start_char": 724, "end_char": 1046, "estimated_token_count": 74, "token_estimator": "heuristic-v1", "text": "## pallet-revive\n\n[`pallet-revive`](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/frame/revive){target=\\_blank} is the modern smart contract solution for Polkadot SDK-based chains. It provides a unified execution environment that supports both PolkaVM and EVM bytecode through dual execution backends."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 2, "depth": 3, "title": "Core Components", "anchor": "core-components", "start_char": 1046, "end_char": 1841, "estimated_token_count": 230, "token_estimator": "heuristic-v1", "text": "### Core Components\n\n**Essential Pallet:**\n**[`pallet-revive`](https://github.com/paritytech/polkadot-sdk/tree/master/substrate/frame/revive){target=\\_blank}** provides the core smart contract execution environment with [PolkaVM](https://github.com/polkadot-developers/polkadot-docs/blob/71e1b51bb42ef55e20c2f3b953db86e8c26cd591/smart-contracts/for-eth-devs/dual-vm-stack.md#upgrade-to-polkavm){target=\\_blank} and [REVM](https://github.com/polkadot-developers/polkadot-docs/blob/71e1b51bb42ef55e20c2f3b953db86e8c26cd591/smart-contracts/for-eth-devs/dual-vm-stack.md#migrate-from-evm){target=\\_blank} backends.\n\n**RPC Adapter:**\n**[`pallet-revive-eth-rpc`](https://crates.io/crates/pallet-revive-eth-rpc){target=\\_blank}** adds full Ethereum RPC compatibility for Ethereum tooling integration."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 3, "depth": 3, "title": "Supported Languages and Compilers", "anchor": "supported-languages-and-compilers", "start_char": 1841, "end_char": 2463, "estimated_token_count": 196, "token_estimator": "heuristic-v1", "text": "### Supported Languages and Compilers\n\n`pallet-revive` accepts smart contracts from multiple languages and compilation paths:\n\n| Language | Compiler | Output Bytecode | Execution Backend |\n|----------|----------|-----------------|-------------------|\n| Solidity | `resolc` | PolkaVM | PolkaVM |\n| Solidity | `solc` | EVM | REVM |\n| Rust (ink!) | `cargo-contract` | PolkaVM | PolkaVM | \n\nAny language that can compile to PolkaVM bytecode and utilize `pallet-revive`'s host functions (via [`pallet-revive-uapi`](https://paritytech.github.io/polkadot-sdk/master/pallet_revive_uapi/index.html){target=\\_blank}) is supported."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 4, "depth": 3, "title": "How It Works", "anchor": "how-it-works", "start_char": 2463, "end_char": 2723, "estimated_token_count": 54, "token_estimator": "heuristic-v1", "text": "### How It Works\n\n**Dual Execution Model:**\n\n1. **PolkaVM Backend**: Executes PolkaVM bytecode with native performance optimization.\n2. **REVM Backend**: Implements EVM bytecode for compatibility with existing Ethereum contracts, ensuring seamless migration."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 5, "depth": 3, "title": "Key Benefits", "anchor": "key-benefits", "start_char": 2723, "end_char": 3199, "estimated_token_count": 106, "token_estimator": "heuristic-v1", "text": "### Key Benefits\n\n- **Unified platform**: Deploys both PolkaVM-optimized and EVM-compatible contracts using a single pallet.\n- **Performance**: PolkaVM execution provides improved performance compared to the traditional EVM, leveraging the [RISC-V](https://en.wikipedia.org/wiki/RISC-V){target=\\_blank} architecture to map instructions to the CPU and requires little transpiling.\n- **Ethereum compatibility**: Supports full integration with Ethereum tooling via RPC adapter."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 6, "depth": 3, "title": "Implementation Examples", "anchor": "implementation-examples", "start_char": 3199, "end_char": 3489, "estimated_token_count": 69, "token_estimator": "heuristic-v1", "text": "### Implementation Examples\n\nSee a real-world implementation in the [Polkadot Hub TestNet](https://github.com/paseo-network/runtimes/blob/c965c42a4e0bc9d1e9cc0a340322bc3b8e347bcf/system-parachains/asset-hub-paseo/src/lib.rs#L1122-L1157){target=\\_blank} in the Polkadot Fellows repository."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 7, "depth": 2, "title": "Frontier", "anchor": "frontier", "start_char": 3489, "end_char": 3786, "estimated_token_count": 62, "token_estimator": "heuristic-v1", "text": "## Frontier\n\n[Frontier](https://github.com/polkadot-evm/frontier){target=\\_blank} is the Ethereum compatibility layer designed for maximum compatibility with the Ethereum ecosystem. It's the ideal choice when you need seamless integration with existing Ethereum tools, dApps, and infrastructure."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 8, "depth": 3, "title": "Integration Options", "anchor": "integration-options", "start_char": 3786, "end_char": 3888, "estimated_token_count": 15, "token_estimator": "heuristic-v1", "text": "### Integration Options\n\nFrontier offers flexible integration depending on your compatibility needs:"} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 9, "depth": 3, "title": "EVM Execution Only", "anchor": "evm-execution-only", "start_char": 3888, "end_char": 4228, "estimated_token_count": 82, "token_estimator": "heuristic-v1", "text": "### EVM Execution Only\n\nFor basic EVM support using Polkadot SDK native APIs:\n\n- **[`pallet-evm`](https://github.com/polkadot-evm/frontier/tree/master/frame/evm){target=\\_blank}**: Provides the core EVM execution environment.\n\nThis configuration allows EVM contract execution but requires using Polkadot SDK-specific APIs for interaction."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 10, "depth": 3, "title": "Full Ethereum Compatibility", "anchor": "full-ethereum-compatibility", "start_char": 4228, "end_char": 4798, "estimated_token_count": 165, "token_estimator": "heuristic-v1", "text": "### Full Ethereum Compatibility\n\nFor complete Ethereum ecosystem integration with Ethereum RPC support:\n\n- **[`pallet-evm`](https://github.com/polkadot-evm/frontier/tree/master/frame/evm){target=\\_blank}**: Integrates core EVM execution environment.\n- **[`pallet-ethereum`](https://github.com/polkadot-evm/frontier/tree/master/frame/ethereum){target=\\_blank}**: Emulates Ethereum blocks and handles Ethereum-formatted transactions.\n- **[`fc-rpc`](https://github.com/polkadot-evm/frontier/tree/master/client/rpc){target=\\_blank}**: Provides Ethereum JSON-RPC endpoints."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 11, "depth": 3, "title": "Key Benefits", "anchor": "key-benefits-2", "start_char": 4798, "end_char": 5253, "estimated_token_count": 93, "token_estimator": "heuristic-v1", "text": "### Key Benefits\n\n- **Ethereum tooling compatibility**: Full compatibility with MetaMask, Hardhat, Remix, Foundry, and other Ethereum development tools.\n- **Minimal-friction migration**: Deployment of existing Ethereum dApps with minimal or no modifications.\n- **Native Ethereum formats**: Support for Ethereum transaction formats, signatures, and gas mechanics.\n- **Block emulation**: Ethereum-style block structure within Substrate's block production."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 12, "depth": 3, "title": "Implementation Examples", "anchor": "implementation-examples-2", "start_char": 5253, "end_char": 5720, "estimated_token_count": 114, "token_estimator": "heuristic-v1", "text": "### Implementation Examples\n\nProduction implementations demonstrate Frontier's capabilities:\n\n- **Moonbeam**: See their implementation of [`pallet-evm`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L532){target=\\_blank} and [`pallet-ethereum`](https://github.com/moonbeam-foundation/moonbeam/blob/9e2ddbc9ae8bf65f11701e7ccde50075e5fe2790/runtime/moonbeam/src/lib.rs#L698){target=\\_blank}."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 13, "depth": 2, "title": "pallet-contracts (Legacy)", "anchor": "pallet-contracts-legacy", "start_char": 5720, "end_char": 6051, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "## pallet-contracts (Legacy)\n\n[`pallet-contracts`](https://docs.rs/pallet-contracts/latest/pallet_contracts/index.html#contracts-pallet){target=\\_blank} is the original Wasm-based smart contract pallet for Polkadot SDK chains. While still functional, it's considered legacy as development efforts have shifted to `pallet-revive`."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 14, "depth": 3, "title": "Implementation Example", "anchor": "implementation-example", "start_char": 6051, "end_char": 6304, "estimated_token_count": 59, "token_estimator": "heuristic-v1", "text": "### Implementation Example\n\nFor reference, Astar's implementation of [`pallet-contracts`](https://github.com/AstarNetwork/Astar/blob/b6f7a408d31377130c3713ed52941a06b5436402/runtime/astar/src/lib.rs#L693){target=\\_blank} demonstrates production usage."} +{"page_id": "parachains-customize-runtime-add-smart-contract-functionality", "page_title": "Add Smart Contract Functionality", "index": 15, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 6304, "end_char": 6655, "estimated_token_count": 92, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Guide __Add a Pallet to the Runtime__\n\n ---\n\n Learn the step-by-step process for integrating Polkadot SDK pallets into your blockchain's runtime.\n\n [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/add-existing-pallets/)\n\n
"} {"page_id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "page_title": "Add Pallets to the Runtime", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 30, "end_char": 866, "estimated_token_count": 192, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nIn previous tutorials, you learned how to [create a custom pallet](/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/){target=\\_blank} and [test it](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/){target=\\_blank}. The next step is to include this pallet in your runtime, integrating it into the core logic of your blockchain.\n\nThis tutorial will guide you through adding two pallets to your runtime: the custom pallet you previously developed and the [utility pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_utility/index.html){target=\\_blank}. This standard Polkadot SDK pallet provides powerful dispatch functionality. The utility pallet offers, for example, batch dispatch, a stateless operation that enables executing multiple calls in a single transaction."} {"page_id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "page_title": "Add Pallets to the Runtime", "index": 1, "depth": 2, "title": "Add the Pallets as Dependencies", "anchor": "add-the-pallets-as-dependencies", "start_char": 866, "end_char": 8510, "estimated_token_count": 1856, "token_estimator": "heuristic-v1", "text": "## Add the Pallets as Dependencies\n\nFirst, you'll update the runtime's `Cargo.toml` file to include the Utility pallet and your custom pallets as dependencies for the runtime. Follow these steps:\n\n1. Open the `runtime/Cargo.toml` file and locate the `[dependencies]` section. Add pallet-utility as one of the features for the `polkadot-sdk` dependency with the following line:\n\n ```toml hl_lines=\"4\" title=\"runtime/Cargo.toml\"\n [dependencies]\n ...\n polkadot-sdk = { workspace = true, features = [\n \"pallet-utility\",\n ...\n ], default-features = false }\n ```\n\n2. In the same `[dependencies]` section, add the custom pallet that you built from scratch with the following line:\n\n ```toml hl_lines=\"3\" title=\"Cargo.toml\"\n [dependencies]\n ...\n custom-pallet = { path = \"../pallets/custom-pallet\", default-features = false }\n ```\n\n3. In the `[features]` section, add the custom pallet to the `std` feature list:\n\n ```toml hl_lines=\"5\" title=\"Cargo.toml\"\n [features]\n default = [\"std\"]\n std = [\n ...\n \"custom-pallet/std\",\n ...\n ]\n ```\n\n3. Save the changes and close the `Cargo.toml` file.\n\n Once you have saved your file, it should look like the following:\n\n ???- code \"runtime/Cargo.toml\"\n \n ```rust title=\"runtime/Cargo.toml\"\n [package]\n name = \"parachain-template-runtime\"\n description = \"A parachain runtime template built with Substrate and Cumulus, part of Polkadot Sdk.\"\n version = \"0.1.0\"\n license = \"Unlicense\"\n authors.workspace = true\n homepage.workspace = true\n repository.workspace = true\n edition.workspace = true\n publish = false\n\n [package.metadata.docs.rs]\n targets = [\"x86_64-unknown-linux-gnu\"]\n\n [build-dependencies]\n docify = { workspace = true }\n substrate-wasm-builder = { optional = true, workspace = true, default-features = true }\n\n [dependencies]\n codec = { features = [\"derive\"], workspace = true }\n cumulus-pallet-parachain-system.workspace = true\n docify = { workspace = true }\n hex-literal = { optional = true, workspace = true, default-features = true }\n log = { workspace = true }\n pallet-parachain-template = { path = \"../pallets/template\", default-features = false }\n polkadot-sdk = { workspace = true, features = [\n \"pallet-utility\",\n \"cumulus-pallet-aura-ext\",\n \"cumulus-pallet-session-benchmarking\",\n \"cumulus-pallet-weight-reclaim\",\n \"cumulus-pallet-xcm\",\n \"cumulus-pallet-xcmp-queue\",\n \"cumulus-primitives-aura\",\n \"cumulus-primitives-core\",\n \"cumulus-primitives-utility\",\n \"pallet-aura\",\n \"pallet-authorship\",\n \"pallet-balances\",\n \"pallet-collator-selection\",\n \"pallet-message-queue\",\n \"pallet-session\",\n \"pallet-sudo\",\n \"pallet-timestamp\",\n \"pallet-transaction-payment\",\n \"pallet-transaction-payment-rpc-runtime-api\",\n \"pallet-xcm\",\n \"parachains-common\",\n \"polkadot-parachain-primitives\",\n \"polkadot-runtime-common\",\n \"runtime\",\n \"staging-parachain-info\",\n \"staging-xcm\",\n \"staging-xcm-builder\",\n \"staging-xcm-executor\",\n ], default-features = false }\n scale-info = { features = [\"derive\"], workspace = true }\n serde_json = { workspace = true, default-features = false, features = [\n \"alloc\",\n ] }\n smallvec = { workspace = true, default-features = true }\n\n custom-pallet = { path = \"../pallets/custom-pallet\", default-features = false }\n\n [features]\n default = [\"std\"]\n std = [\n \"codec/std\",\n \"cumulus-pallet-parachain-system/std\",\n \"log/std\",\n \"pallet-parachain-template/std\",\n \"polkadot-sdk/std\",\n \"scale-info/std\",\n \"serde_json/std\",\n \"substrate-wasm-builder\",\n \"custom-pallet/std\",\n ]\n\n runtime-benchmarks = [\n \"cumulus-pallet-parachain-system/runtime-benchmarks\",\n \"hex-literal\",\n \"pallet-parachain-template/runtime-benchmarks\",\n \"polkadot-sdk/runtime-benchmarks\",\n ]\n\n try-runtime = [\n \"cumulus-pallet-parachain-system/try-runtime\",\n \"pallet-parachain-template/try-runtime\",\n \"polkadot-sdk/try-runtime\",\n ]\n\n # Enable the metadata hash generation.\n #\n # This is hidden behind a feature because it increases the compile time.\n # The wasm binary needs to be compiled twice, once to fetch the metadata,\n # generate the metadata hash and then a second time with the\n # `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash`\n # extension.\n metadata-hash = [\"substrate-wasm-builder/metadata-hash\"]\n\n # A convenience feature for enabling things when doing a build\n # for an on-chain release.\n on-chain-release-build = [\"metadata-hash\"]\n\n ```\n\nUpdate your root parachain template's `Cargo.toml` file to include your custom pallet as a dependency. Follow these steps:\n\n1. Open the `./Cargo.toml` file and locate the `[workspace]` section. \n \n Make sure the `custom-pallet` is a member of the workspace:\n\n ```toml hl_lines=\"4\" title=\"Cargo.toml\"\n [workspace]\n default-members = [\"pallets/template\", \"runtime\"]\n members = [\n \"node\", \"pallets/custom-pallet\",\n \"pallets/template\",\n \"runtime\",\n ]\n ```\n\n???- code \"./Cargo.toml\"\n\n ```rust title=\"./Cargo.toml\"\n [workspace.package]\n license = \"MIT-0\"\n authors = [\"Parity Technologies \"]\n homepage = \"https://paritytech.github.io/polkadot-sdk/\"\n repository = \"https://github.com/paritytech/polkadot-sdk-parachain-template.git\"\n edition = \"2021\"\n\n [workspace]\n default-members = [\"pallets/template\", \"runtime\"]\n members = [\n \"node\", \"pallets/custom-pallet\",\n \"pallets/template\",\n \"runtime\",\n ]\n resolver = \"2\"\n\n [workspace.dependencies]\n parachain-template-runtime = { path = \"./runtime\", default-features = false }\n pallet-parachain-template = { path = \"./pallets/template\", default-features = false }\n clap = { version = \"4.5.13\" }\n color-print = { version = \"0.3.4\" }\n docify = { version = \"0.2.9\" }\n futures = { version = \"0.3.31\" }\n jsonrpsee = { version = \"0.24.3\" }\n log = { version = \"0.4.22\", default-features = false }\n polkadot-sdk = { version = \"2503.0.1\", default-features = false }\n prometheus-endpoint = { version = \"0.17.2\", default-features = false, package = \"substrate-prometheus-endpoint\" }\n serde = { version = \"1.0.214\", default-features = false }\n codec = { version = \"3.7.4\", default-features = false, package = \"parity-scale-codec\" }\n cumulus-pallet-parachain-system = { version = \"0.20.0\", default-features = false }\n hex-literal = { version = \"0.4.1\", default-features = false }\n scale-info = { version = \"2.11.6\", default-features = false }\n serde_json = { version = \"1.0.132\", default-features = false }\n smallvec = { version = \"1.11.0\", default-features = false }\n substrate-wasm-builder = { version = \"26.0.1\", default-features = false }\n frame = { version = \"0.9.1\", default-features = false, package = \"polkadot-sdk-frame\" }\n\n [profile.release]\n opt-level = 3\n panic = \"unwind\"\n\n [profile.production]\n codegen-units = 1\n inherits = \"release\"\n lto = true\n ```"} {"page_id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "page_title": "Add Pallets to the Runtime", "index": 2, "depth": 3, "title": "Update the Runtime Configuration", "anchor": "update-the-runtime-configuration", "start_char": 8510, "end_char": 10415, "estimated_token_count": 406, "token_estimator": "heuristic-v1", "text": "### Update the Runtime Configuration\n\nConfigure the pallets by implementing their `Config` trait and update the runtime macro to include the new pallets:\n\n1. Add the `OriginCaller` import:\n\n ```rust title=\"mod.rs\" hl_lines=\"8\"\n // Local module imports\n use super::OriginCaller;\n ...\n ```\n\n2. Implement the [`Config`](https://paritytech.github.io/polkadot-sdk/master/pallet_utility/pallet/trait.Config.html){target=\\_blank} trait for both pallets at the end of the `runtime/src/config/mod.rs` file:\n\n ```rust title=\"mod.rs\" hl_lines=\"8-25\"\n ...\n /// Configure the pallet template in pallets/template.\n impl pallet_parachain_template::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type WeightInfo = pallet_parachain_template::weights::SubstrateWeight;\n }\n\n // Configure utility pallet.\n impl pallet_utility::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type RuntimeCall = RuntimeCall;\n type PalletsOrigin = OriginCaller;\n type WeightInfo = pallet_utility::weights::SubstrateWeight;\n }\n // Define counter max value runtime constant.\n parameter_types! {\n pub const CounterMaxValue: u32 = 500;\n }\n\n // Configure custom pallet.\n impl custom_pallet::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = CounterMaxValue;\n }\n ```\n\n3. Locate the `#[frame_support::runtime]` macro in the `runtime/src/lib.rs` file and add the pallets:\n\n ```rust hl_lines=\"9-14\" title=\"lib.rs\"\n #[frame_support::runtime]\n mod runtime {\n #[runtime::runtime]\n #[runtime::derive(\n ...\n )]\n pub struct Runtime;\n #[runtime::pallet_index(51)]\n pub type Utility = pallet_utility;\n\n #[runtime::pallet_index(52)]\n pub type CustomPallet = custom_pallet;\n }\n ```"} {"page_id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "page_title": "Add Pallets to the Runtime", "index": 3, "depth": 2, "title": "Recompile the Runtime", "anchor": "recompile-the-runtime", "start_char": 10415, "end_char": 10864, "estimated_token_count": 89, "token_estimator": "heuristic-v1", "text": "## Recompile the Runtime\n\nAfter adding and configuring your pallets in the runtime, the next step is to ensure everything is set up correctly. To do this, recompile the runtime with the following command (make sure you're in the project's root directory):\n\n```bash\ncargo build --release\n```\n\nThis command ensures the runtime compiles without errors, validates the pallet configurations, and prepares the build for subsequent testing or deployment."} {"page_id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "page_title": "Add Pallets to the Runtime", "index": 4, "depth": 2, "title": "Run Your Chain Locally", "anchor": "run-your-chain-locally", "start_char": 10864, "end_char": 12339, "estimated_token_count": 365, "token_estimator": "heuristic-v1", "text": "## Run Your Chain Locally\n\nLaunch your parachain locally and start producing blocks:\n\n!!!tip\n Generated chain TestNet specifications include development accounts \"Alice\" and \"Bob.\" These accounts are pre-funded with native parachain currency, allowing you to sign and send TestNet transactions. Take a look at the [Polkadot.js Accounts section](https://polkadot.js.org/apps/#/accounts){target=\\_blank} to view the development accounts for your chain.\n\n1. Create a new chain specification file with the updated runtime:\n\n ```bash\n chain-spec-builder create -t development \\\n --relay-chain paseo \\\n --para-id 1000 \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \\\n named-preset development\n ```\n\n2. Start the omni node with the generated chain specification:\n\n ```bash\n polkadot-omni-node --chain ./chain_spec.json --dev\n ```\n\n3. Verify you can interact with the new pallets using the [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/extrinsics){target=\\_blank} interface. Navigate to the **Extrinsics** tab and check that you can see both pallets:\n\n - Utility pallet\n\n ![](/images/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/add-pallets-to-runtime-01.webp)\n \n\n - Custom pallet\n\n ![](/images/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/add-pallets-to-runtime-02.webp)"} {"page_id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "page_title": "Add Pallets to the Runtime", "index": 5, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 12339, "end_char": 13091, "estimated_token_count": 183, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Tutorial __Deploy on Paseo TestNet__\n\n ---\n\n Deploy your Polkadot SDK blockchain on Paseo! Follow this step-by-step guide for a seamless journey to a successful TestNet deployment.\n\n [:octicons-arrow-right-24: Get Started](/tutorials/polkadot-sdk/parachains/zero-to-hero/deploy-to-testnet/)\n\n- Tutorial __Pallet Benchmarking (Optional)__\n\n ---\n\n Discover how to measure extrinsic costs and assign precise weights to optimize your pallet for accurate fees and runtime performance.\n\n [:octicons-arrow-right-24: Get Started](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-benchmarking/)\n\n
"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmarking FRAME Pallets", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 16, "end_char": 1205, "estimated_token_count": 235, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nBenchmarking is a critical component of developing efficient and secure blockchain runtimes. In the Polkadot ecosystem, accurately benchmarking your custom pallets ensures that each extrinsic has a precise [weight](/reference/glossary/#weight){target=\\_blank}, representing its computational and storage demands. This process is vital for maintaining the blockchain's performance and preventing potential vulnerabilities, such as Denial of Service (DoS) attacks.\n\nThe Polkadot SDK leverages the [FRAME](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_blank} benchmarking framework, offering tools to measure and assign weights to extrinsics. These weights help determine the maximum number of transactions or system-level calls processed within a block. This guide covers how to use FRAME's [benchmarking framework](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\\_blank}, from setting up your environment to writing and running benchmarks for your custom pallets. You'll understand how to generate accurate weights by the end, ensuring your runtime remains performant and secure."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmarking FRAME Pallets", "index": 1, "depth": 2, "title": "The Case for Benchmarking", "anchor": "the-case-for-benchmarking", "start_char": 1205, "end_char": 1999, "estimated_token_count": 114, "token_estimator": "heuristic-v1", "text": "## The Case for Benchmarking\n\nBenchmarking helps validate that the required execution time for different functions is within reasonable boundaries to ensure your blockchain runtime can handle transactions efficiently and securely. By accurately measuring the weight of each extrinsic, you can prevent service interruptions caused by computationally intensive calls that exceed block time limits. Without benchmarking, runtime performance could be vulnerable to DoS attacks, where malicious users exploit functions with unoptimized weights.\n\nBenchmarking also ensures predictable transaction fees. Weights derived from benchmark tests accurately reflect the resource usage of function calls, allowing fair fee calculation. This approach discourages abuse while maintaining network reliability."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmarking FRAME Pallets", "index": 2, "depth": 3, "title": "Benchmarking and Weight", "anchor": "benchmarking-and-weight", "start_char": 1999, "end_char": 3665, "estimated_token_count": 321, "token_estimator": "heuristic-v1", "text": "### Benchmarking and Weight \n\nIn Polkadot SDK-based chains, weight quantifies the computational effort needed to process transactions. This weight includes factors such as:\n\n- Computational complexity.\n- Storage complexity (proof size).\n- Database reads and writes.\n- Hardware specifications.\n\nBenchmarking uses real-world testing to simulate worst-case scenarios for extrinsics. The framework generates a linear model for weight calculation by running multiple iterations with varied parameters. These worst-case weights ensure blocks remain within execution limits, enabling the runtime to maintain throughput under varying loads. Excess fees can be refunded if a call uses fewer resources than expected, offering users a fair cost model.\n \nBecause weight is a generic unit of measurement based on computation time for a specific physical machine, the weight of any function can change based on the specifications of hardware used for benchmarking. By modeling the expected weight of each runtime function, the blockchain can calculate the number of transactions or system-level calls it can execute within a certain period.\n\nWithin FRAME, each function call that is dispatched must have a `#[pallet::weight]` annotation that can return the expected weight for the worst-case scenario execution of that function given its inputs:\n\n```rust hl_lines=\"2\"\n#[pallet::call_index(0)]\n#[pallet::weight(T::WeightInfo::do_something())]\npub fn do_something(origin: OriginFor) -> DispatchResultWithPostInfo { Ok(()) }\n```\n\nThe `WeightInfo` file is automatically generated during benchmarking. Based on these tests, this file provides accurate weights for each extrinsic."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmarking FRAME Pallets", "index": 3, "depth": 2, "title": "Benchmarking Process", "anchor": "benchmarking-process", "start_char": 3665, "end_char": 4208, "estimated_token_count": 98, "token_estimator": "heuristic-v1", "text": "## Benchmarking Process\n\nBenchmarking a pallet involves the following steps: \n\n1. Creating a `benchmarking.rs` file within your pallet's structure.\n2. Writing a benchmarking test for each extrinsic.\n3. Executing the benchmarking tool to calculate weights based on performance metrics.\n\nThe benchmarking tool runs multiple iterations to model worst-case execution times and determine the appropriate weight. By default, the benchmarking pipeline is deactivated. To activate it, compile your runtime with the `runtime-benchmarks` feature flag."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmarking FRAME Pallets", "index": 4, "depth": 3, "title": "Prepare Your Environment", "anchor": "prepare-your-environment", "start_char": 4208, "end_char": 5262, "estimated_token_count": 293, "token_estimator": "heuristic-v1", "text": "### Prepare Your Environment\n\nInstall the [`frame-omni-bencher`](https://crates.io/crates/frame-omni-bencher){target=\\_blank} command-line tool:\n\n```bash\ncargo install frame-omni-bencher\n```\n\nBefore writing benchmark tests, you need to ensure the `frame-benchmarking` crate is included in your pallet's `Cargo.toml` similar to the following:\n\n```toml title=\"Cargo.toml\"\nframe-benchmarking = { version = \"37.0.0\", default-features = false }\n```\n\nYou must also ensure that you add the `runtime-benchmarks` feature flag as follows under the `[features]` section of your pallet's `Cargo.toml`:\n\n```toml title=\"Cargo.toml\"\nruntime-benchmarks = [\n \"frame-benchmarking/runtime-benchmarks\",\n \"frame-support/runtime-benchmarks\",\n \"frame-system/runtime-benchmarks\",\n \"sp-runtime/runtime-benchmarks\",\n]\n```\n\nLastly, ensure that `frame-benchmarking` is included in `std = []`: \n\n```toml title=\"Cargo.toml\"\nstd = [\n # ...\n \"frame-benchmarking?/std\",\n # ...\n]\n```\n\nOnce complete, you have the required dependencies for writing benchmark tests for your pallet."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmarking FRAME Pallets", "index": 5, "depth": 3, "title": "Write Benchmark Tests", "anchor": "write-benchmark-tests", "start_char": 5262, "end_char": 7718, "estimated_token_count": 645, "token_estimator": "heuristic-v1", "text": "### Write Benchmark Tests\n\nCreate a `benchmarking.rs` file in your pallet's `src/`. Your directory structure should look similar to the following:\n\n```\nmy-pallet/\n├── src/\n│ ├── lib.rs # Main pallet implementation\n│ └── benchmarking.rs # Benchmarking\n└── Cargo.toml\n```\n\nWith the directory structure set, you can use the [`polkadot-sdk-parachain-template`](https://github.com/paritytech/polkadot-sdk-parachain-template/tree/master/pallets){target=\\_blank} to get started as follows:\n\n```rust title=\"benchmarking.rs (starter template)\"\n//! Benchmarking setup for pallet-template\n#![cfg(feature = \"runtime-benchmarks\")]\n\nuse super::*;\nuse frame_benchmarking::v2::*;\n\n#[benchmarks]\nmod benchmarks {\n\tuse super::*;\n\t#[cfg(test)]\n\tuse crate::pallet::Pallet as Template;\n\tuse frame_system::RawOrigin;\n\n\t#[benchmark]\n\tfn do_something() {\n\t\tlet caller: T::AccountId = whitelisted_caller();\n\t\t#[extrinsic_call]\n\t\tdo_something(RawOrigin::Signed(caller), 100);\n\n\t\tassert_eq!(Something::::get().map(|v| v.block_number), Some(100u32.into()));\n\t}\n\n\t#[benchmark]\n\tfn cause_error() {\n\t\tSomething::::put(CompositeStruct { block_number: 100u32.into() });\n\t\tlet caller: T::AccountId = whitelisted_caller();\n\t\t#[extrinsic_call]\n\t\tcause_error(RawOrigin::Signed(caller));\n\n\t\tassert_eq!(Something::::get().map(|v| v.block_number), Some(101u32.into()));\n\t}\n\n\timpl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test);\n}\n```\n\nIn your benchmarking tests, employ these best practices:\n\n- **Write custom testing functions**: The function `do_something` in the preceding example is a placeholder. Similar to writing unit tests, you must write custom functions to benchmark test your extrinsics. Access the mock runtime and use functions such as `whitelisted_caller()` to sign transactions and facilitate testing.\n- **Use the `#[extrinsic_call]` macro**: This macro is used when calling the extrinsic itself and is a required part of a benchmarking function. See the [`extrinsic_call`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html#extrinsic_call-and-block){target=\\_blank} docs for more details.\n- **Validate extrinsic behavior**: The `assert_eq` expression ensures that the extrinsic is working properly within the benchmark context.\n\nAdd the `benchmarking` module to your pallet. In the pallet `lib.rs` file add the following:\n\n```rust\n#[cfg(feature = \"runtime-benchmarks\")]\nmod benchmarking;\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmarking FRAME Pallets", "index": 6, "depth": 3, "title": "Add Benchmarks to Runtime", "anchor": "add-benchmarks-to-runtime", "start_char": 7718, "end_char": 9847, "estimated_token_count": 418, "token_estimator": "heuristic-v1", "text": "### Add Benchmarks to Runtime\n\nBefore running the benchmarking tool, you must integrate benchmarks with your runtime as follows:\n\n1. Navigate to your `runtime/src` directory and check if a `benchmarks.rs` file exists. If not, create one. This file will contain the macro that registers all pallets for benchmarking along with their respective configurations:\n\n ```rust title=\"benchmarks.rs\"\n frame_benchmarking::define_benchmarks!(\n [frame_system, SystemBench::]\n [pallet_parachain_template, TemplatePallet]\n [pallet_balances, Balances]\n [pallet_session, SessionBench::]\n [pallet_timestamp, Timestamp]\n [pallet_message_queue, MessageQueue]\n [pallet_sudo, Sudo]\n [pallet_collator_selection, CollatorSelection]\n [cumulus_pallet_parachain_system, ParachainSystem]\n [cumulus_pallet_xcmp_queue, XcmpQueue]\n );\n ```\n\n For example, to add a new pallet named `pallet_parachain_template` for benchmarking, include it in the macro as shown:\n ```rust title=\"benchmarks.rs\" hl_lines=\"3\"\n frame_benchmarking::define_benchmarks!(\n [frame_system, SystemBench::]\n [pallet_parachain_template, TemplatePallet]\n );\n ```\n\n !!!warning \"Updating `define_benchmarks!` macro is required\"\n Any pallet that needs to be benchmarked must be included in the [`define_benchmarks!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.define_benchmarks.html){target=\\_blank} macro. The CLI will only be able to access and benchmark pallets that are registered here.\n\n2. Check your runtime's `lib.rs` file to ensure the `benchmarks` module is imported. The import should look like this:\n\n ```rust title=\"lib.rs\"\n #[cfg(feature = \"runtime-benchmarks\")]\n mod benchmarks;\n ```\n\n The `runtime-benchmarks` feature gate ensures benchmark tests are isolated from production runtime code.\n\n3. Enable runtime benchmarking for your pallet in `runtime/Cargo.toml`:\n\n ```toml\n runtime-benchmarks = [\n # ...\n \"pallet_parachain_template/runtime-benchmarks\",\n ]\n\n ```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmarking FRAME Pallets", "index": 7, "depth": 3, "title": "Run Benchmarks", "anchor": "run-benchmarks", "start_char": 9847, "end_char": 14232, "estimated_token_count": 1100, "token_estimator": "heuristic-v1", "text": "### Run Benchmarks\n\nYou can now compile your runtime with the `runtime-benchmarks` feature flag. This feature flag is crucial as the benchmarking tool will look for this feature being enabled to know when it should run benchmark tests. Follow these steps to compile the runtime with benchmarking enabled:\n\n1. Run `build` with the feature flag included:\n\n ```bash\n cargo build --features runtime-benchmarks --release\n ```\n\n2. Create a `weights.rs` file in your pallet's `src/` directory. This file will store the auto-generated weight calculations:\n\n ```bash\n touch weights.rs\n ```\n\n3. Before running the benchmarking tool, you'll need a template file that defines how weight information should be formatted. Download the official template from the Polkadot SDK repository and save it in your project folders for future use:\n\n ```bash\n curl https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \\\n --output ./pallets/benchmarking/frame-weight-template.hbs\n ```\n\n4. Run the benchmarking tool to measure extrinsic weights:\n\n ```bash\n frame-omni-bencher v1 benchmark pallet \\\n --runtime INSERT_PATH_TO_WASM_RUNTIME \\\n --pallet INSERT_NAME_OF_PALLET \\\n --extrinsic \"\" \\\n --template ./frame-weight-template.hbs \\\n --output weights.rs\n ```\n\n !!! tip \"Flag definitions\"\n - **`--runtime`**: The path to your runtime's Wasm.\n - **`--pallet`**: The name of the pallet you wish to benchmark. This pallet must be configured in your runtime and defined in `define_benchmarks`.\n - **`--extrinsic`**: Which extrinsic to test. Using `\"\"` implies all extrinsics will be benchmarked.\n - **`--template`**: Defines how weight information should be formatted.\n - **`--output`**: Where the output of the auto-generated weights will reside.\n\nThe generated `weights.rs` file contains weight annotations for your extrinsics, ready to be added to your pallet. The output should be similar to the following. Some output is omitted for brevity:\n\n
\n frame-omni-bencher v1 benchmark pallet \\\n --runtime INSERT_PATH_TO_WASM_RUNTIME \\\n --pallet \"INSERT_NAME_OF_PALLET\" \\\n --extrinsic \"\" \\\n --template ./frame-weight-template.hbs \\\n --output ./weights.rs\n ...\n 2025-01-15T16:41:33.557045Z INFO polkadot_sdk_frame::benchmark::pallet: [ 0 % ] Starting benchmark: pallet_parachain_template::do_something\n 2025-01-15T16:41:33.564644Z INFO polkadot_sdk_frame::benchmark::pallet: [ 50 % ] Starting benchmark: pallet_parachain_template::cause_error\n ...\n Created file: \"weights.rs\"\n \n
\n\n#### Add Benchmark Weights to Pallet\n\nOnce the `weights.rs` is generated, you must integrate it with your pallet. \n\n1. To begin the integration, import the `weights` module and the `WeightInfo` trait, then add both to your pallet's `Config` trait. Complete the following steps to set up the configuration:\n\n ```rust title=\"lib.rs\"\n pub mod weights;\n use crate::weights::WeightInfo;\n\n /// Configure the pallet by specifying the parameters and types on which it depends.\n #[pallet::config]\n pub trait Config: frame_system::Config {\n // ...\n /// A type representing the weights required by the dispatchables of this pallet.\n type WeightInfo: WeightInfo;\n }\n ```\n\n2. Next, you must add this to the `#[pallet::weight]` annotation in all the extrinsics via the `Config` as follows:\n\n ```rust hl_lines=\"2\" title=\"lib.rs\"\n #[pallet::call_index(0)]\n #[pallet::weight(T::WeightInfo::do_something())]\n pub fn do_something(origin: OriginFor) -> DispatchResultWithPostInfo { Ok(()) }\n ```\n\n3. Finally, configure the actual weight values in your runtime. In `runtime/src/config/mod.rs`, add the following code:\n\n ```rust title=\"mod.rs\"\n // Configure pallet.\n impl pallet_parachain_template::Config for Runtime {\n // ...\n type WeightInfo = pallet_parachain_template::weights::SubstrateWeight;\n }\n ```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmarking FRAME Pallets", "index": 8, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 14232, "end_char": 14715, "estimated_token_count": 114, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n- View the Rust Docs for a more comprehensive, low-level view of the [FRAME V2 Benchmarking Suite](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=_blank}.\n- Read the [FRAME Benchmarking and Weights](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_benchmarking_weight/index.html){target=_blank} reference document, a concise guide which details how weights and benchmarking work."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 0, "end_char": 868, "estimated_token_count": 183, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nBenchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.\n\nThis guide continues the pallet development series, building on the [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet), [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime), and [Test Your Pallet](/parachains/customize-runtime/pallet-development/pallet-testing) tutorials. You'll learn how to benchmark the counter pallet extrinsics and integrate the generated weights into your runtime."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 868, "end_char": 1071, "estimated_token_count": 32, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have:\n\n- Completed the previous pallet development tutorials\n- Basic understanding of computational complexity\n- Familiarity with Rust's testing framework"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 2, "depth": 2, "title": "Why Benchmark?", "anchor": "why-benchmark", "start_char": 1071, "end_char": 1723, "estimated_token_count": 109, "token_estimator": "heuristic-v1", "text": "## Why Benchmark?\n\nIn blockchain systems, every operation consumes resources. Weight is the mechanism Polkadot SDK uses to measure and limit resource consumption. Without accurate weights:\n\n- **Security Risk**: Malicious actors could submit transactions that consume excessive resources, blocking legitimate transactions or halting the chain\n- **Inefficiency**: Over-estimated weights waste block space and reduce throughput\n- **User Experience**: Inaccurate weights lead to incorrect fee calculations\n\nBenchmarking provides empirical measurements of your extrinsics under various conditions, ensuring weights reflect real-world resource consumption."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 3, "depth": 2, "title": "Understanding Weights", "anchor": "understanding-weights", "start_char": 1723, "end_char": 2778, "estimated_token_count": 255, "token_estimator": "heuristic-v1", "text": "## Understanding Weights\n\nThe [weight system](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\\_blank} serves multiple purposes:\n\n- **DoS Protection**: Limits the computational work per block, preventing attackers from overwhelming the network\n- **Fee Calculation**: Determines transaction fees based on actual resource usage\n- **Block Production**: Helps block authors maximize throughput while staying within block limits\n\nWeights are expressed as [`Weight::from_parts(ref_time, proof_size)`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.from_parts){target=\\_blank} where:\n\n- [`ref_time`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.ref_time){target=\\_blank}: Computational time measured in picoseconds\n- [`proof_size`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.proof_size){target=\\_blank}: Storage proof size in bytes"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 4, "depth": 2, "title": "Step 1: Create the Benchmarking Module", "anchor": "step-1-create-the-benchmarking-module", "start_char": 2778, "end_char": 5474, "estimated_token_count": 728, "token_estimator": "heuristic-v1", "text": "## Step 1: Create the Benchmarking Module\n\nCreate a new file `benchmarking.rs` in your pallet's `src` directory. This module will contain all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\\_blank} for your pallet:\n\n```rust title=\"pallets/pallet-custom/src/benchmarking.rs\"\n#![cfg(feature = \"runtime-benchmarks\")]\n\nuse super::*;\nuse frame::deps::frame_benchmarking::v2::*;\nuse frame::benchmarking::prelude::RawOrigin;\n\n#[benchmarks]\nmod benchmarks {\n use super::*;\n\n #[benchmark]\n fn set_counter_value() {\n let new_value: u32 = 100;\n\n #[extrinsic_call]\n _(RawOrigin::Root, new_value);\n\n assert_eq!(CounterValue::::get(), new_value);\n }\n\n #[benchmark]\n fn increment() {\n let caller: T::AccountId = whitelisted_caller();\n let amount: u32 = 50;\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller.clone()), amount);\n\n assert_eq!(CounterValue::::get(), amount);\n assert_eq!(UserInteractions::::get(caller), 1);\n }\n\n #[benchmark]\n fn decrement() {\n // First set the counter to a non-zero value\n CounterValue::::put(100);\n\n let caller: T::AccountId = whitelisted_caller();\n let amount: u32 = 30;\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller.clone()), amount);\n\n assert_eq!(CounterValue::::get(), 70);\n assert_eq!(UserInteractions::::get(caller), 1);\n }\n\n impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);\n}\n```\n\n**Key components:**\n\n- **`#![cfg(feature = \"runtime-benchmarks\")]`**: Ensures benchmarking code only compiles when the feature is enabled\n- **[`#[benchmarks]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmarks.html){target=\\_blank}**: Marks the module containing benchmark definitions\n- **[`#[benchmark]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmark.html){target=\\_blank}**: Defines individual benchmark functions\n- **[`#[extrinsic_call]`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.extrinsic_call.html){target=\\_blank}**: Marks the actual extrinsic invocation to measure\n- **[`whitelisted_caller()`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/fn.whitelisted_caller.html){target=\\_blank}**: Generates a funded account for benchmarking\n- **[`impl_benchmark_test_suite!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.impl_benchmark_test_suite.html){target=\\_blank}**: Generates test functions to verify benchmarks work correctly"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 5, "depth": 2, "title": "Step 2: Define the Weight Trait", "anchor": "step-2-define-the-weight-trait", "start_char": 5474, "end_char": 6891, "estimated_token_count": 297, "token_estimator": "heuristic-v1", "text": "## Step 2: Define the Weight Trait\n\nThe [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. This enables you to use placeholder weights during development and testing, then switch to auto-generated benchmarked weights in production without modifying the pallet code itself.\n\nAdd a `weights` module to your pallet that defines the `WeightInfo` trait:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#[frame::pallet]\npub mod pallet {\n use frame::prelude::*;\n pub use weights::WeightInfo;\n\n pub mod weights {\n use frame::prelude::*;\n\n pub trait WeightInfo {\n fn set_counter_value() -> Weight;\n fn increment() -> Weight;\n fn decrement() -> Weight;\n }\n\n impl WeightInfo for () {\n fn set_counter_value() -> Weight {\n Weight::from_parts(10_000, 0)\n }\n fn increment() -> Weight {\n Weight::from_parts(15_000, 0)\n }\n fn decrement() -> Weight {\n Weight::from_parts(15_000, 0)\n }\n }\n }\n\n // ... rest of pallet\n}\n```\n\nThe `()` implementation provides placeholder weights for development. Later, this will be replaced with auto-generated weights from benchmarking."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 6, "depth": 2, "title": "Step 3: Add WeightInfo to Config", "anchor": "step-3-add-weightinfo-to-config", "start_char": 6891, "end_char": 7656, "estimated_token_count": 169, "token_estimator": "heuristic-v1", "text": "## Step 3: Add WeightInfo to Config\n\nBy making `WeightInfo` an associated type in the `Config` trait, you allow each runtime that uses your pallet to specify which weight implementation to use. Different deployment environments (testnets, production chains, or different hardware configurations) may have different performance characteristics and can use different weight calculations.\n\nUpdate your pallet's `Config` trait to include `WeightInfo`:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#[pallet::config]\npub trait Config: frame_system::Config {\n type RuntimeEvent: From> + IsType<::RuntimeEvent>;\n\n #[pallet::constant]\n type CounterMaxValue: Get;\n\n type WeightInfo: weights::WeightInfo;\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 7, "depth": 2, "title": "Step 4: Update Extrinsic Weight Annotations", "anchor": "step-4-update-extrinsic-weight-annotations", "start_char": 7656, "end_char": 8833, "estimated_token_count": 290, "token_estimator": "heuristic-v1", "text": "## Step 4: Update Extrinsic Weight Annotations\n\nBy calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. This allows you to easily switch between placeholder weights for testing and benchmarked weights for production without changing any pallet code.\n\nReplace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#[pallet::call]\nimpl Pallet {\n #[pallet::call_index(0)]\n #[pallet::weight(T::WeightInfo::set_counter_value())]\n pub fn set_counter_value(origin: OriginFor, new_value: u32) -> DispatchResult {\n // ... implementation\n }\n\n #[pallet::call_index(1)]\n #[pallet::weight(T::WeightInfo::increment())]\n pub fn increment(origin: OriginFor, amount: u32) -> DispatchResult {\n // ... implementation\n }\n\n #[pallet::call_index(2)]\n #[pallet::weight(T::WeightInfo::decrement())]\n pub fn decrement(origin: OriginFor, amount: u32) -> DispatchResult {\n // ... implementation\n }\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 8, "depth": 2, "title": "Step 5: Include the Benchmarking Module", "anchor": "step-5-include-the-benchmarking-module", "start_char": 8833, "end_char": 9453, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Step 5: Include the Benchmarking Module\n\nThe `#[cfg(feature = \"runtime-benchmarks\")]` attribute ensures that benchmarking code is only compiled when explicitly needed. This keeps your production runtime lean by excluding benchmarking infrastructure from normal builds, as it's only needed when generating weights.\n\nAt the top of your `lib.rs`, add the module declaration:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#![cfg_attr(not(feature = \"std\"), no_std)]\n\nextern crate alloc;\nuse alloc::vec::Vec;\n\npub use pallet::*;\n\n#[cfg(feature = \"runtime-benchmarks\")]\nmod benchmarking;\n\n// ... rest of the pallet\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 9, "depth": 2, "title": "Step 6: Configure Pallet Dependencies", "anchor": "step-6-configure-pallet-dependencies", "start_char": 9453, "end_char": 10350, "estimated_token_count": 212, "token_estimator": "heuristic-v1", "text": "## Step 6: Configure Pallet Dependencies\n\nThe feature flag system in Cargo allows you to conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds.\n\nUpdate your pallet's `Cargo.toml` to enable the benchmarking feature:\n\n```toml title=\"pallets/pallet-custom/Cargo.toml\"\n[dependencies]\ncodec = { features = [\"derive\"], workspace = true }\nscale-info = { features = [\"derive\"], workspace = true }\nframe = { features = [\"experimental\", \"runtime\"], workspace = true }\n\n[features]\ndefault = [\"std\"]\nruntime-benchmarks = [\n \"frame/runtime-benchmarks\",\n]\nstd = [\n \"codec/std\",\n \"scale-info/std\",\n \"frame/std\",\n]\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 10, "depth": 2, "title": "Step 7: Update Mock Runtime", "anchor": "step-7-update-mock-runtime", "start_char": 10350, "end_char": 10898, "estimated_token_count": 117, "token_estimator": "heuristic-v1", "text": "## Step 7: Update Mock Runtime\n\nIn your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo` since unit tests focus on verifying functional correctness rather than performance characteristics. This keeps tests fast and focused on validating logic.\n\nAdd the `WeightInfo` type to your test configuration in `mock.rs`:\n\n```rust title=\"pallets/pallet-custom/src/mock.rs\"\nimpl pallet_custom::Config for Test {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n type WeightInfo = ();\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 11, "depth": 2, "title": "Step 8: Configure Runtime Benchmarking", "anchor": "step-8-configure-runtime-benchmarking", "start_char": 10898, "end_char": 11085, "estimated_token_count": 31, "token_estimator": "heuristic-v1", "text": "## Step 8: Configure Runtime Benchmarking\n\nTo execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. This involves three configuration steps:"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 12, "depth": 3, "title": "Update Runtime Cargo.toml", "anchor": "update-runtime-cargotoml", "start_char": 11085, "end_char": 11652, "estimated_token_count": 137, "token_estimator": "heuristic-v1", "text": "### Update Runtime Cargo.toml\n\nWhen you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included.\n\nAdd your pallet to the runtime's `runtime-benchmarks` feature in `runtime/Cargo.toml`:\n\n```toml title=\"runtime/Cargo.toml\"\nruntime-benchmarks = [\n \"cumulus-pallet-parachain-system/runtime-benchmarks\",\n \"hex-literal\",\n \"pallet-parachain-template/runtime-benchmarks\",\n \"polkadot-sdk/runtime-benchmarks\",\n \"pallet-custom/runtime-benchmarks\",\n]\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 13, "depth": 3, "title": "Update Runtime Configuration", "anchor": "update-runtime-configuration", "start_char": 11652, "end_char": 12130, "estimated_token_count": 103, "token_estimator": "heuristic-v1", "text": "### Update Runtime Configuration\n\nStart with the placeholder implementation during development. After successfully running benchmarks and generating the weights file, you'll update this to use the benchmarked weights.\n\nIn `runtime/src/configs/mod.rs`, add the `WeightInfo` type:\n\n```rust title=\"runtime/src/configs/mod.rs\"\nimpl pallet_custom::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n type WeightInfo = ();\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 14, "depth": 3, "title": "Register Benchmarks", "anchor": "register-benchmarks", "start_char": 12130, "end_char": 12611, "estimated_token_count": 104, "token_estimator": "heuristic-v1", "text": "### Register Benchmarks\n\nThe `define_benchmarks!` macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks.\n\nAdd your pallet to the benchmark list in `runtime/src/benchmarks.rs`:\n\n```rust title=\"runtime/src/benchmarks.rs\"\npolkadot_sdk::frame_benchmarking::define_benchmarks!(\n [frame_system, SystemBench::]\n [pallet_balances, Balances]\n // ... other pallets\n [pallet_custom, CustomPallet]\n);\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 15, "depth": 2, "title": "Step 9: Run Benchmarks", "anchor": "step-9-run-benchmarks", "start_char": 12611, "end_char": 12638, "estimated_token_count": 7, "token_estimator": "heuristic-v1", "text": "## Step 9: Run Benchmarks"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 16, "depth": 3, "title": "Test Benchmark Compilation", "anchor": "test-benchmark-compilation", "start_char": 12638, "end_char": 13283, "estimated_token_count": 128, "token_estimator": "heuristic-v1", "text": "### Test Benchmark Compilation\n\nThe `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the full runtime.\n\nFirst, verify your benchmarks compile and run as tests:\n\n```bash\ncargo test -p pallet-custom --features runtime-benchmarks\n```\n\nYou should see your benchmark tests passing:\n\n```\ntest benchmarking::benchmarks::bench_set_counter_value ... ok\ntest benchmarking::benchmarks::bench_increment ... ok\ntest benchmarking::benchmarks::bench_decrement ... ok\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 17, "depth": 3, "title": "Build the Runtime with Benchmarks", "anchor": "build-the-runtime-with-benchmarks", "start_char": 13283, "end_char": 13996, "estimated_token_count": 132, "token_estimator": "heuristic-v1", "text": "### Build the Runtime with Benchmarks\n\nThis build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. This is a special build used only for benchmarking - you'll create a different build later for actually running your chain.\n\nCompile the runtime with benchmarking enabled to generate the WASM binary:\n\n```bash\ncargo build --release --features runtime-benchmarks\n```\n\nThis produces the runtime WASM file needed for benchmarking, typically located at:\n```\ntarget/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 18, "depth": 3, "title": "Install the Benchmarking Tool", "anchor": "install-the-benchmarking-tool", "start_char": 13996, "end_char": 14536, "estimated_token_count": 118, "token_estimator": "heuristic-v1", "text": "### Install the Benchmarking Tool\n\n[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\\_blank} is the official Polkadot SDK tool specifically designed for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system.\n\nInstall the `frame-omni-bencher` CLI tool:\n\n```bash\ncargo install frame-omni-bencher --locked\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 19, "depth": 3, "title": "Download the Weight Template", "anchor": "download-the-weight-template", "start_char": 14536, "end_char": 15301, "estimated_token_count": 155, "token_estimator": "heuristic-v1", "text": "### Download the Weight Template\n\nThe weight template is a Handlebars file that transforms raw benchmark data into a properly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow Polkadot SDK conventions and include all necessary metadata like benchmark execution parameters, storage operation counts, and hardware information.\n\nDownload the official weight template file:\n\n```bash\ncurl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \\\n--output ./pallets/pallet-custom/frame-weight-template.hbs\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 20, "depth": 3, "title": "Hardware Requirements for Benchmarking", "anchor": "hardware-requirements-for-benchmarking", "start_char": 15301, "end_char": 17789, "estimated_token_count": 432, "token_estimator": "heuristic-v1", "text": "### Hardware Requirements for Benchmarking\n\n!!! warning \"Critical: Benchmark on Production-Like Hardware\"\n Benchmarks must be executed on hardware similar to what will run your chain in production. Weight measurements are hardware-dependent, and benchmarking on different hardware can lead to dangerous under-estimation or wasteful over-estimation of weights.\n\nWeights represent the actual computational time and resources consumed by extrinsics. These measurements vary significantly across different hardware configurations:\n\n- **CPU Performance**: Different processors execute instructions at different speeds. A faster development laptop will produce lower weight values than production server hardware\n- **Storage Speed**: Database read/write performance varies between NVMe SSDs, SATA SSDs, and HDDs, affecting storage-related weights\n- **Memory Bandwidth**: RAM speed impacts how quickly data can be accessed during execution\n- **CPU Cache**: Cache size and architecture differences affect repeated operations\n\nBenchmarking on faster hardware than production leads to under-estimated weights - attackers could submit extrinsics that consume more resources than the weights suggest, potentially causing blocks to take longer than expected to produce or even halting the chain. Conversely, benchmarking on slower hardware creates over-estimated weights, resulting in unnecessarily high transaction fees and wasted block capacity.\n\n**Best practices:**\n\n1. **Match production specifications**: If your chain will run on specific validator hardware, benchmark on identical or very similar machines\n2. **Use reference hardware**: The Polkadot ecosystem often uses standardized reference hardware specifications for consistency. Consider following these standards if your chain will connect to Polkadot or Kusama\n3. **Dedicated benchmarking environment**: Run benchmarks on a machine without other heavy processes to ensure consistent measurements\n4. **Document your hardware**: The generated weight files include hardware information in comments. Review this to ensure it matches your production environment\n5. **Re-benchmark when hardware changes**: If your validator hardware specifications change, re-run benchmarks and update weights\n\nFor development and testing purposes, you can run benchmarks on any available hardware to verify that your benchmark functions work correctly. However, before deploying to production, always re-run benchmarks on production-equivalent hardware."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 21, "depth": 3, "title": "Execute Benchmarks", "anchor": "execute-benchmarks", "start_char": 17789, "end_char": 19210, "estimated_token_count": 294, "token_estimator": "heuristic-v1", "text": "### Execute Benchmarks\n\nBenchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking the WASM ensures your weight measurements reflect real-world conditions.\n\nRun benchmarks for your pallet to generate weight files:\n\n```bash\nframe-omni-bencher v1 benchmark pallet \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \\\n --pallet pallet_custom \\\n --extrinsic \"\" \\\n --template ./pallets/pallet-custom/frame-weight-template.hbs \\\n --output ./pallets/pallet-custom/src/weights.rs\n```\n\n**Command breakdown:**\n\n- `v1`: Specifies the benchmarking framework version (v2 API)\n- `benchmark pallet`: Subcommand indicating you want to benchmark pallet extrinsics\n- `--runtime`: Path to the compiled WASM runtime file that includes your pallet and benchmarks\n- `--pallet pallet_custom`: Name of the pallet to benchmark (must match the name used in `define_benchmarks!`)\n- `--extrinsic \"\"`: Empty string benchmarks all extrinsics in the pallet; you can specify a single extrinsic name to benchmark only that one\n- `--template`: Path to the Handlebars template that formats the output\n- `--output`: Destination file path for the generated weights module"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 22, "depth": 3, "title": "Advanced Options", "anchor": "advanced-options", "start_char": 19210, "end_char": 20357, "estimated_token_count": 242, "token_estimator": "heuristic-v1", "text": "### Advanced Options\n\nYou can customize benchmark execution with additional parameters for more detailed measurements:\n\n```bash\nframe-omni-bencher v1 benchmark pallet \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \\\n --pallet pallet_custom \\\n --extrinsic \"\" \\\n --steps 50 \\\n --repeat 20 \\\n --template ./pallets/pallet-custom/frame-weight-template.hbs \\\n --output ./pallets/pallet-custom/src/weights.rs\n```\n\n**Additional parameters:**\n\n- `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time\n- `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise and providing more reliable weight estimates\n- `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution\n- `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 23, "depth": 2, "title": "Step 10: Use Generated Weights", "anchor": "step-10-use-generated-weights", "start_char": 20357, "end_char": 21332, "estimated_token_count": 168, "token_estimator": "heuristic-v1", "text": "## Step 10: Use Generated Weights\n\nAfter running benchmarks, a `weights.rs` file is generated containing measured weights. The generated weights are based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. Estimates or placeholder values cannot capture these nuances and will either waste block space (over-estimation) or create security risks (under-estimation).\n\nThe file includes:\n\n- Detailed documentation about the benchmark execution environment (date, hardware, parameters)\n- The `WeightInfo` trait definition matching your benchmark functions\n- `SubstrateWeight` implementation with measured weights from your benchmarks\n- Database read/write costs calculated based on observed storage operations\n- Component complexity annotations for variable inputs (if you use linear components)\n- A fallback `()` implementation for testing environments"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 24, "depth": 3, "title": "Integrate the Generated Weights", "anchor": "integrate-the-generated-weights", "start_char": 21332, "end_char": 22065, "estimated_token_count": 189, "token_estimator": "heuristic-v1", "text": "### Integrate the Generated Weights\n\nUnlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during normal operation to calculate transaction fees and enforce block limits.\n\nAdd the weights module to your pallet's `lib.rs`:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#![cfg_attr(not(feature = \"std\"), no_std)]\n\nextern crate alloc;\nuse alloc::vec::Vec;\n\npub use pallet::*;\n\n#[cfg(feature = \"runtime-benchmarks\")]\nmod benchmarking;\n\npub mod weights;\n\n#[frame::pallet]\npub mod pallet {\n use super::*;\n use frame::prelude::*;\n use crate::weights::WeightInfo;\n // ... rest of pallet\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 25, "depth": 3, "title": "Update Runtime Configuration", "anchor": "update-runtime-configuration-2", "start_char": 22065, "end_char": 22694, "estimated_token_count": 121, "token_estimator": "heuristic-v1", "text": "### Update Runtime Configuration\n\nThis change activates your benchmarked weights in the production runtime. Now when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits.\n\nUpdate your runtime configuration to use the generated weights instead of the placeholder `()` implementation:\n\n```rust title=\"runtime/src/configs/mod.rs\"\nimpl pallet_custom::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n type WeightInfo = pallet_custom::weights::SubstrateWeight;\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 26, "depth": 3, "title": "Example Generated Weight File", "anchor": "example-generated-weight-file", "start_char": 22694, "end_char": 24357, "estimated_token_count": 450, "token_estimator": "heuristic-v1", "text": "### Example Generated Weight File\n\nThe generated `weights.rs` file will look similar to this:\n\n```rust title=\"pallets/pallet-custom/src/weights.rs\"\n//! Autogenerated weights for `pallet_custom`\n//!\n//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0\n//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`\n\n#![cfg_attr(rustfmt, rustfmt_skip)]\n#![allow(unused_parens)]\n#![allow(unused_imports)]\n#![allow(missing_docs)]\n\nuse frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};\nuse core::marker::PhantomData;\n\npub trait WeightInfo {\n fn set_counter_value() -> Weight;\n fn increment() -> Weight;\n fn decrement() -> Weight;\n}\n\npub struct SubstrateWeight(PhantomData);\nimpl WeightInfo for SubstrateWeight {\n fn set_counter_value() -> Weight {\n Weight::from_parts(8_234_000, 0)\n .saturating_add(T::DbWeight::get().reads(1))\n .saturating_add(T::DbWeight::get().writes(1))\n }\n\n fn increment() -> Weight {\n Weight::from_parts(12_456_000, 0)\n .saturating_add(T::DbWeight::get().reads(2))\n .saturating_add(T::DbWeight::get().writes(2))\n }\n\n fn decrement() -> Weight {\n Weight::from_parts(11_987_000, 0)\n .saturating_add(T::DbWeight::get().reads(2))\n .saturating_add(T::DbWeight::get().writes(2))\n }\n}\n```\n\n**Note**: The actual numbers will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\\_blank} accounts for database read and write operations."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 27, "depth": 2, "title": "Benchmarking Best Practices", "anchor": "benchmarking-best-practices", "start_char": 24357, "end_char": 24389, "estimated_token_count": 5, "token_estimator": "heuristic-v1", "text": "## Benchmarking Best Practices"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 28, "depth": 3, "title": "1. Test Worst-Case Scenarios", "anchor": "1-test-worst-case-scenarios", "start_char": 24389, "end_char": 25006, "estimated_token_count": 138, "token_estimator": "heuristic-v1", "text": "### 1. Test Worst-Case Scenarios\n\nBenchmarks should always measure maximum possible resource consumption. If you benchmark average or best-case scenarios, malicious users could craft transactions that hit worst-case paths in your code, consuming more resources than the weights indicate and potentially slowing down or halting block production.\n\n```rust\n#[benchmark]\nfn complex_operation() {\n // Set up worst-case storage state\n for i in 0..100 {\n SomeStorage::::insert(i, vec![0u8; 1000]);\n }\n\n let caller = whitelisted_caller();\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller));\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 29, "depth": 3, "title": "2. Use Linear Components for Variable Complexity", "anchor": "2-use-linear-components-for-variable-complexity", "start_char": 25006, "end_char": 25882, "estimated_token_count": 206, "token_estimator": "heuristic-v1", "text": "### 2. Use Linear Components for Variable Complexity\n\nMany extrinsics have variable costs depending on input parameters. [Linear components](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/trait.BenchmarkingSetup.html){target=\\_blank} tell the benchmarking framework to test your extrinsic with different values of `n`, measure the execution time for each, and calculate a formula like `Weight = base_weight + (n * per_item_weight)`. This produces dynamic weights that accurately reflect the actual work being done.\n\nWhen extrinsic complexity depends on input size, use linear components:\n\n```rust title=\"pallets/pallet-custom/src/benchmarking.rs\"\n#[benchmark]\nfn process_items(n: Linear<0, 100>) {\n let caller = whitelisted_caller();\n let items: Vec = (0..n).collect();\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller), items);\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 30, "depth": 3, "title": "3. Verify Results", "anchor": "3-verify-results", "start_char": 25882, "end_char": 26518, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "### 3. Verify Results\n\nAssertions ensure that your benchmark is actually testing the code path you think it's testing. If your extrinsic fails silently or takes an early return, the benchmark would measure the wrong scenario and produce inaccurate weights.\n\nAlways assert the expected state after extrinsic execution:\n\n```rust title=\"pallets/pallet-custom/src/benchmarking.rs\"\n#[benchmark]\nfn my_extrinsic() {\n let caller = whitelisted_caller();\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller.clone()));\n\n // Verify the extrinsic had the expected effect\n assert_eq!(MyStorage::::get(&caller), expected_value);\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 31, "depth": 3, "title": "4. Minimize Setup Code", "anchor": "4-minimize-setup-code", "start_char": 26518, "end_char": 27092, "estimated_token_count": 120, "token_estimator": "heuristic-v1", "text": "### 4. Minimize Setup Code\n\nWhile the benchmarking framework tries to isolate the extrinsic execution, excessive setup code can add noise to measurements. More importantly, setup code that doesn't reflect real-world pre-conditions can lead to benchmarking unrealistic scenarios.\n\nOnly include necessary setup in benchmarks:\n\n```rust title=\"pallets/pallet-custom/src/benchmarking.rs\"\n#[benchmark]\nfn efficient_benchmark() {\n // Minimal setup\n let caller = whitelisted_caller();\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller));\n\n // Minimal assertions\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 32, "depth": 2, "title": "Run Your Chain Locally", "anchor": "run-your-chain-locally", "start_char": 27092, "end_char": 27618, "estimated_token_count": 141, "token_estimator": "heuristic-v1", "text": "## Run Your Chain Locally\n\nNow that you've added the pallet to your runtime, you can launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\\_blank} guide."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 33, "depth": 3, "title": "Build the Production Runtime", "anchor": "build-the-production-runtime", "start_char": 27618, "end_char": 28821, "estimated_token_count": 223, "token_estimator": "heuristic-v1", "text": "### Build the Production Runtime\n\nThe `runtime-benchmarks` feature flag adds special host functions (like `ext_benchmarking_current_time` and `ext_benchmarking_get_read_and_written_keys`) that are only available in the benchmarking execution environment. These functions allow the benchmarking framework to precisely measure execution time and track storage operations. However, regular nodes don't provide these host functions, so a runtime compiled with benchmarking features will fail to start on a production node.\n\nBefore running your chain, rebuild the runtime **without** the `runtime-benchmarks` feature:\n\n```bash\ncargo build --release\n```\n\n!!! note \"Build Types\"\n Understanding the difference between builds is critical:\n\n - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher`\n - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your actual chain\n\nThis produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 34, "depth": 3, "title": "Generate a Chain Specification", "anchor": "generate-a-chain-specification", "start_char": 28821, "end_char": 29655, "estimated_token_count": 165, "token_estimator": "heuristic-v1", "text": "### Generate a Chain Specification\n\nThe chain specification defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. By generating a new chain spec with your updated runtime (now containing your benchmarked pallet), you ensure that nodes starting from this spec will use the correct version of your code with proper weight calculations.\n\nCreate a new chain specification file with the updated runtime:\n\n```bash\nchain-spec-builder create -t development \\\n--relay-chain paseo \\\n--para-id 1000 \\\n--runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \\\nnamed-preset development\n```\n\nThis command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 35, "depth": 3, "title": "Start the Parachain Node", "anchor": "start-the-parachain-node", "start_char": 29655, "end_char": 30074, "estimated_token_count": 84, "token_estimator": "heuristic-v1", "text": "### Start the Parachain Node\n\nLaunch the parachain using the Polkadot Omni Node with the generated chain specification by running the following command:\n\n```bash\npolkadot-omni-node --chain ./chain_spec.json --dev\n```\n\nThe node will start and display initialization information including:\n\n- The chain specification name\n- The node identity and peer ID\n- Database location\n- Network endpoints (JSON-RPC and Prometheus)"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 36, "depth": 3, "title": "Verify Block Production", "anchor": "verify-block-production", "start_char": 30074, "end_char": 30777, "estimated_token_count": 190, "token_estimator": "heuristic-v1", "text": "### Verify Block Production\n\nOnce the node is running, you should see log messages indicating successful block production:\n\n```\n[Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc)\n[Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ...\n[Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2)\n[Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ...\n[Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32)\n```\n\nThe parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\\_blank}."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 37, "depth": 2, "title": "Related Resources", "anchor": "related-resources", "start_char": 30777, "end_char": 31318, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Related Resources\n\n- [FRAME Benchmarking Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/index.html){target=\\_blank}\n- [Weight Struct Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html){target=\\_blank}\n- [Benchmarking v2 API](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\\_blank}\n- [frame-omni-bencher Tool](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\\_blank}"} {"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 26, "end_char": 847, "estimated_token_count": 167, "token_estimator": "heuristic-v1", "text": "## Introduction\n\n[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functionality with precision and flexibility. While FRAME includes a library of pre-built pallets, its true strength lies in creating custom pallets tailored to your specific needs.\n\nIn this guide, you'll learn how to build a custom counter pallet from scratch that demonstrates core pallet development concepts."} {"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 847, "end_char": 1217, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have:\n\n- [Polkadot SDK dependencies installed](/parachains/install-polkadot-sdk/){target=\\_blank}.\n- A [Polkadot SDK Parchain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\\_blank} set up locally.\n- Basic familiarity with [FRAME concepts](/parachains/customize-runtime/){target=\\_blank}."} {"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 2, "depth": 2, "title": "Core Pallet Components", "anchor": "core-pallet-components", "start_char": 1217, "end_char": 2092, "estimated_token_count": 193, "token_estimator": "heuristic-v1", "text": "## Core Pallet Components\n\nAs you build your custom pallet, you'll work with these key sections:\n\n- **Imports and dependencies**: Bring in necessary FRAME libraries and external modules.\n- **Runtime configuration trait**: Specify types and constants for pallet-runtime interaction.\n- **Runtime events**: Define signals that communicate state changes.\n- **Runtime errors**: Define error types returned from dispatchable calls.\n- **Runtime storage**: Declare on-chain storage items for your pallet's state.\n- **Genesis configuration**: Set initial blockchain state.\n- **Dispatchable functions (extrinsics)**: Create callable functions for user interactions.\n\nFor additional macros beyond those covered here, refer to the [pallet_macros](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\\_blank} section of the Polkadot SDK Docs."} @@ -591,12 +632,12 @@ {"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 17, "depth": 3, "title": "Add to Runtime Construct", "anchor": "add-to-runtime-construct", "start_char": 22324, "end_char": 23326, "estimated_token_count": 214, "token_estimator": "heuristic-v1", "text": "### Add to Runtime Construct\n\nIn the `runtime/src/lib.rs` file, locate the [`#[frame_support::runtime]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/attr.runtime.html){target=\\_blank} section and add your pallet with a unique `pallet_index`:\n\n```rust title=\"runtime/src/lib.rs\"\n#[frame_support::runtime]\nmod runtime {\n #[runtime::runtime]\n #[runtime::derive(\n RuntimeCall,\n RuntimeEvent,\n RuntimeError,\n RuntimeOrigin,\n RuntimeTask,\n RuntimeFreezeReason,\n RuntimeHoldReason,\n RuntimeSlashReason,\n RuntimeLockId,\n RuntimeViewFunction\n )]\n pub struct Runtime;\n\n #[runtime::pallet_index(0)]\n pub type System = frame_system;\n\n // ... other pallets\n\n #[runtime::pallet_index(51)]\n pub type CustomPallet = pallet_custom;\n}\n```\n\n!!!warning\n Each pallet must have a unique index. Duplicate indices will cause compilation errors. Choose an index that doesn't conflict with existing pallets."} {"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 18, "depth": 3, "title": "Configure Genesis for Your Runtime", "anchor": "configure-genesis-for-your-runtime", "start_char": 23326, "end_char": 23824, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "### Configure Genesis for Your Runtime\n\nTo set initial values for your pallet when the chain starts, you'll need to configure the genesis in your chain specification. Genesis configuration is typically done in the `node/src/chain_spec.rs` file or when generating the chain specification.\n\nFor development and testing, you can use the default values provided by the `#[derive(DefaultNoBound)]` macro. For production networks, you'll want to explicitly set these values in your chain specification."} {"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 19, "depth": 3, "title": "Verify Runtime Compilation", "anchor": "verify-runtime-compilation", "start_char": 23824, "end_char": 24047, "estimated_token_count": 41, "token_estimator": "heuristic-v1", "text": "### Verify Runtime Compilation\n\nCompile the runtime to ensure everything is configured correctly:\n\n```bash\ncargo build --release\n```\n\nThis command validates all pallet configurations and prepares the build for deployment."} -{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 20, "depth": 2, "title": "Run Your Chain Locally", "anchor": "run-your-chain-locally", "start_char": 24047, "end_char": 24235, "estimated_token_count": 47, "token_estimator": "heuristic-v1", "text": "## Run Your Chain Locally\n\nLaunch your parachain locally to test the new pallet functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\\_blank}."} -{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 21, "depth": 3, "title": "Generate a Chain Specification", "anchor": "generate-a-chain-specification", "start_char": 24235, "end_char": 24644, "estimated_token_count": 92, "token_estimator": "heuristic-v1", "text": "### Generate a Chain Specification\n\nCreate a chain specification file with the updated runtime:\n\n```bash\nchain-spec-builder create -t development \\\n--relay-chain paseo \\\n--para-id 1000 \\\n--runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \\\nnamed-preset development\n```\n\nThis command generates a `chain_spec.json` that includes your custom pallet."} -{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 22, "depth": 3, "title": "Start the Parachain Node", "anchor": "start-the-parachain-node", "start_char": 24644, "end_char": 24827, "estimated_token_count": 44, "token_estimator": "heuristic-v1", "text": "### Start the Parachain Node\n\nLaunch the parachain:\n\n```bash\npolkadot-omni-node --chain ./chain_spec.json --dev\n```\n\nVerify the node starts successfully and begins producing blocks."} -{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 23, "depth": 2, "title": "Interact with Your Pallet", "anchor": "interact-with-your-pallet", "start_char": 24827, "end_char": 25599, "estimated_token_count": 234, "token_estimator": "heuristic-v1", "text": "## Interact with Your Pallet\n\nUse the Polkadot.js Apps interface to test your pallet:\n\n1. Navigate to [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/extrinsics){target=\\_blank}.\n\n2. Ensure you're connected to your local node at `ws://127.0.0.1:9944`.\n\n3. Go to **Developer** > **Extrinsics**.\n\n4. Locate **customPallet** in the pallet dropdown.\n\n5. You should see the available extrinsics:\n\n - **`increment(amount)`**: Increase the counter by a specified amount.\n - **`decrement(amount)`**: Decrease the counter by a specified amount.\n - **`setCounterValue(newValue)`**: Set counter to a specific value (requires sudo/root).\n\n![](/images/parachains/customize-runtime/pallet-development/create-a-pallet/create-a-pallet-01.webp)"} -{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 24, "depth": 2, "title": "Key Takeaways", "anchor": "key-takeaways", "start_char": 25599, "end_char": 26322, "estimated_token_count": 129, "token_estimator": "heuristic-v1", "text": "## Key Takeaways\n\nYou've successfully created and integrated a custom pallet into a Polkadot SDK-based runtime. You have now successfully:\n\n- Defined runtime-specific types and constants via the `Config` trait.\n- Implemented on-chain state using `StorageValue` and `StorageMap`.\n- Created signals to communicate state changes to external systems.\n- Established clear error handling with descriptive error types.\n- Configured initial blockchain state for both production and testing.\n- Built callable functions with proper validation and access control.\n- Added the pallet to a runtime and tested it locally.\n\nThese components form the foundation for developing sophisticated blockchain logic in Polkadot SDK-based chains."} -{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 25, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 26322, "end_char": 26671, "estimated_token_count": 86, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Guide __Mock Your Runtime__\n\n ---\n\n Learn to create a mock runtime environment for testing your pallet in isolation before integration.\n\n [:octicons-arrow-right-24: Continue](/parachains/customize-runtime/pallet-development/mock-runtime/)\n\n
"} +{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 20, "depth": 2, "title": "Run Your Chain Locally", "anchor": "run-your-chain-locally", "start_char": 24047, "end_char": 24522, "estimated_token_count": 128, "token_estimator": "heuristic-v1", "text": "## Run Your Chain Locally\n\nLaunch your parachain locally to test the new pallet functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\\_blank} guide."} +{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 21, "depth": 3, "title": "Generate a Chain Specification", "anchor": "generate-a-chain-specification", "start_char": 24522, "end_char": 24931, "estimated_token_count": 92, "token_estimator": "heuristic-v1", "text": "### Generate a Chain Specification\n\nCreate a chain specification file with the updated runtime:\n\n```bash\nchain-spec-builder create -t development \\\n--relay-chain paseo \\\n--para-id 1000 \\\n--runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \\\nnamed-preset development\n```\n\nThis command generates a `chain_spec.json` that includes your custom pallet."} +{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 22, "depth": 3, "title": "Start the Parachain Node", "anchor": "start-the-parachain-node", "start_char": 24931, "end_char": 25114, "estimated_token_count": 44, "token_estimator": "heuristic-v1", "text": "### Start the Parachain Node\n\nLaunch the parachain:\n\n```bash\npolkadot-omni-node --chain ./chain_spec.json --dev\n```\n\nVerify the node starts successfully and begins producing blocks."} +{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 23, "depth": 2, "title": "Interact with Your Pallet", "anchor": "interact-with-your-pallet", "start_char": 25114, "end_char": 25886, "estimated_token_count": 234, "token_estimator": "heuristic-v1", "text": "## Interact with Your Pallet\n\nUse the Polkadot.js Apps interface to test your pallet:\n\n1. Navigate to [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/extrinsics){target=\\_blank}.\n\n2. Ensure you're connected to your local node at `ws://127.0.0.1:9944`.\n\n3. Go to **Developer** > **Extrinsics**.\n\n4. Locate **customPallet** in the pallet dropdown.\n\n5. You should see the available extrinsics:\n\n - **`increment(amount)`**: Increase the counter by a specified amount.\n - **`decrement(amount)`**: Decrease the counter by a specified amount.\n - **`setCounterValue(newValue)`**: Set counter to a specific value (requires sudo/root).\n\n![](/images/parachains/customize-runtime/pallet-development/create-a-pallet/create-a-pallet-01.webp)"} +{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 24, "depth": 2, "title": "Key Takeaways", "anchor": "key-takeaways", "start_char": 25886, "end_char": 26609, "estimated_token_count": 129, "token_estimator": "heuristic-v1", "text": "## Key Takeaways\n\nYou've successfully created and integrated a custom pallet into a Polkadot SDK-based runtime. You have now successfully:\n\n- Defined runtime-specific types and constants via the `Config` trait.\n- Implemented on-chain state using `StorageValue` and `StorageMap`.\n- Created signals to communicate state changes to external systems.\n- Established clear error handling with descriptive error types.\n- Configured initial blockchain state for both production and testing.\n- Built callable functions with proper validation and access control.\n- Added the pallet to a runtime and tested it locally.\n\nThese components form the foundation for developing sophisticated blockchain logic in Polkadot SDK-based chains."} +{"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 25, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 26609, "end_char": 26958, "estimated_token_count": 86, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Guide __Mock Your Runtime__\n\n ---\n\n Learn to create a mock runtime environment for testing your pallet in isolation before integration.\n\n [:octicons-arrow-right-24: Continue](/parachains/customize-runtime/pallet-development/mock-runtime/)\n\n
"} {"page_id": "parachains-customize-runtime-pallet-development-mock-runtime", "page_title": "Mock Your Runtime", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 21, "end_char": 806, "estimated_token_count": 158, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nTesting is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node.\n\nIn this guide, you'll learn how to create a mock runtime for the custom counter pallet built in the [Make a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\\_blank} guide. This mock runtime will enable you to write comprehensive unit tests that verify:\n\n- Dispatchable function behavior.\n- Storage state changes.\n- Event emission.\n- Error handling.\n- Access control and origin validation.\n- Genesis configuration."} {"page_id": "parachains-customize-runtime-pallet-development-mock-runtime", "page_title": "Mock Your Runtime", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 806, "end_char": 1203, "estimated_token_count": 108, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have:\n\n- Completed the [Make a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\\_blank} guide.\n- The custom counter pallet from the Make a Custom Pallet guide. Available in `pallets/pallet-custom`.\n- Basic understanding of [Rust testing](https://doc.rust-lang.org/book/ch11-00-testing.html){target=\\_blank}."} {"page_id": "parachains-customize-runtime-pallet-development-mock-runtime", "page_title": "Mock Your Runtime", "index": 2, "depth": 2, "title": "Understand Mock Runtimes", "anchor": "understand-mock-runtimes", "start_char": 1203, "end_char": 1737, "estimated_token_count": 90, "token_estimator": "heuristic-v1", "text": "## Understand Mock Runtimes\n\nA mock runtime is a minimal implementation of the runtime environment that:\n\n- Simulates blockchain state to provide storage and state management.\n- Satisfies your pallet's `Config` trait requirements.\n- Allows isolated testing without external dependencies.\n- Supports genesis configuration to set initial blockchain state for tests.\n- Provides instant feedback on code changes for a faster development cycle.\n\nMock runtimes are used exclusively for testing and are never deployed to a live blockchain."} @@ -1214,21 +1255,21 @@ {"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 4, "depth": 3, "title": "Create the Storage Contract", "anchor": "create-the-storage-contract", "start_char": 3094, "end_char": 3633, "estimated_token_count": 112, "token_estimator": "heuristic-v1", "text": "### Create the Storage Contract\n\nIn the `contracts` directory, create a new file called `Storage.sol` and add the following code:\n\n```solidity title=\"Storage.sol\"\n// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ncontract Storage {\n uint256 private storedNumber;\n\n event NumberStored(uint256 newNumber);\n\n function setNumber(uint256 _number) public {\n storedNumber = _number;\n emit NumberStored(_number);\n }\n}\n```\n\nThis simple contract stores a single number and provides functions to read and update it."} {"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 5, "depth": 3, "title": "Configure Hardhat for Polkadot Hub", "anchor": "configure-hardhat-for-polkadot-hub", "start_char": 3633, "end_char": 5430, "estimated_token_count": 415, "token_estimator": "heuristic-v1", "text": "### Configure Hardhat for Polkadot Hub\n\nUpdate your `hardhat.config.ts` file to include the Polkadot Hub TestNet configuration:\n\n```typescript title=\"hardhat.config.ts\" hl_lines=\"39-44\"\nimport type { HardhatUserConfig } from \"hardhat/config\";\n\nimport hardhatToolboxViemPlugin from \"@nomicfoundation/hardhat-toolbox-viem\";\nimport { configVariable } from \"hardhat/config\";\n\nconst config: HardhatUserConfig = {\n plugins: [hardhatToolboxViemPlugin],\n solidity: {\n profiles: {\n default: {\n version: \"0.8.28\",\n },\n production: {\n version: \"0.8.28\",\n settings: {\n optimizer: {\n enabled: true,\n runs: 200,\n },\n },\n },\n },\n },\n networks: {\n hardhatMainnet: {\n type: \"edr-simulated\",\n chainType: \"l1\",\n },\n hardhatOp: {\n type: \"edr-simulated\",\n chainType: \"op\",\n },\n sepolia: {\n type: \"http\",\n chainType: \"l1\",\n url: configVariable(\"SEPOLIA_RPC_URL\"),\n accounts: [configVariable(\"SEPOLIA_PRIVATE_KEY\")],\n },\n polkadotTestNet: {\n type: \"http\",\n chainType: \"l1\",\n url: 'http://127.0.0.1:8545',\n accounts: [process.env.PRIVATE_KEY || ''],\n },\n },\n};\n\nexport default config;\n```\n\nCreate a `.env` file in the root of your Hardhat project:\n\n```text title=\".env\"\nPRIVATE_KEY=INSERT_PRIVATE_KEY_HERE\n```\n\nReplace `INSERT_PRIVATE_KEY_HERE` with your actual private key. You can get this by exporting the private key from your wallet (e.g., MetaMask).\n\n!!! warning\n Never commit your private key to version control. Use environment variables or a `.env` file (and add it to `.gitignore`) to manage sensitive information. Keep your private key safe, and never share it with anyone. If it is compromised, your funds can be stolen."} {"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 6, "depth": 3, "title": "Compile the Contract", "anchor": "compile-the-contract", "start_char": 5430, "end_char": 5579, "estimated_token_count": 29, "token_estimator": "heuristic-v1", "text": "### Compile the Contract\n\nCompile your Storage contract:\n\n```bash\nnpx hardhat compile\n```\n\nYou should see output indicating successful compilation."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 7, "depth": 3, "title": "Deploy the Contract", "anchor": "deploy-the-contract", "start_char": 5579, "end_char": 7212, "estimated_token_count": 416, "token_estimator": "heuristic-v1", "text": "### Deploy the Contract\n\nCreate a deployment script in the `ignition/modules` directory called `Storage.ts`:\n\n```typescript title=\"Storage.ts\"\nimport { buildModule } from \"@nomicfoundation/hardhat-ignition/modules\";\n\nexport default buildModule(\"StorageModule\", (m) => {\n const storage = m.contract(\"Storage\");\n\n return { storage };\n});\n```\n\nDeploy the contract to Polkadot Hub TestNet:\n\n```bash\nnpx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotHub\n```\n\nYou should see output similar to:\n\n
\n npx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotTestNet\n WARNING: You are using Node.js 23.11.0 which is not supported by Hardhat.\n Please upgrade to 22.10.0 or a later LTS version (even major version number)\n ✔ Confirm deploy to network polkadotTestNet (420420420)? … yes\n Hardhat Ignition 🚀\n Deploying [ StorageModule ]\n Batch #1\n Executed StorageModule#Storage\n [ StorageModule ] successfully deployed 🚀\n Deployed Addresses\n StorageModule#Storage - 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3\n
\n\n!!! note\n Save the deployed contract address - you'll need it when building your dApp. In the following sections, we'll reference a pre-deployed contract at `0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3`, but you can use your own deployed contract address instead."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 8, "depth": 3, "title": "Export the Contract ABI", "anchor": "export-the-contract-abi", "start_char": 7212, "end_char": 7599, "estimated_token_count": 89, "token_estimator": "heuristic-v1", "text": "### Export the Contract ABI\n\nAfter deployment, you'll need the contract's Application Binary Interface (ABI) for your dApp. You can find it in the `artifacts/contracts/Storage.sol/Storage.json` file generated by Hardhat. You'll use this in the next section when setting up your dApp.\n\nNow that you have your contract deployed, you're ready to build the dApp that will interact with it!"} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 9, "depth": 2, "title": "Set Up the dApp Project", "anchor": "set-up-the-dapp-project", "start_char": 7599, "end_char": 7796, "estimated_token_count": 59, "token_estimator": "heuristic-v1", "text": "## Set Up the dApp Project\n\nNavigate to the root of the project, and create a new Next.js project called `dapp`:\n\n```bash\nnpx create-next-app dapp --ts --eslint --tailwind --app --yes\ncd dapp\n```"} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 10, "depth": 2, "title": "Install Dependencies", "anchor": "install-dependencies", "start_char": 7796, "end_char": 7955, "estimated_token_count": 50, "token_estimator": "heuristic-v1", "text": "## Install Dependencies\n\nInstall viem and related packages:\n\n```bash\nnpm install viem@2.38.5\nnpm install --save-dev typescript@5.9.3 @types/node@22.19.24\n```"} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 11, "depth": 2, "title": "Connect to Polkadot Hub", "anchor": "connect-to-polkadot-hub", "start_char": 7955, "end_char": 10052, "estimated_token_count": 509, "token_estimator": "heuristic-v1", "text": "## Connect to Polkadot Hub\n\nTo interact with Polkadot Hub, you need to set up a [Public Client](https://viem.sh/docs/clients/public#public-client){target=\\_blank} that connects to the blockchain. In this example, you will interact with the Polkadot Hub TestNet, to experiment safely. Start by creating a new file called `utils/viem.ts` and add the following code:\n\n```typescript title=\"viem.ts\"\nimport { createPublicClient, http, createWalletClient, custom } from 'viem'\nimport 'viem/window';\n\nconst transport = http('http://127.0.0.1:8545') // TODO: change to the paseo asset hub RPC URL when it's available\n\n// Configure the Polkadot Testnet Hub chain\nexport const polkadotTestnet = {\n id: 420420420,\n name: 'Polkadot Testnet',\n network: 'polkadot-testnet',\n nativeCurrency: {\n decimals: 18,\n name: 'PAS',\n symbol: 'PAS',\n },\n rpcUrls: {\n default: {\n http: ['http://127.0.0.1:8545'], // TODO: change to the paseo asset hub RPC URL\n },\n },\n} as const\n\n// Create a public client for reading data\nexport const publicClient = createPublicClient({\n chain: polkadotTestnet,\n transport\n})\n\n// Create a wallet client for signing transactions\nexport const getWalletClient = async () => {\n if (typeof window !== 'undefined' && window.ethereum) {\n const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });\n return createWalletClient({\n chain: polkadotTestnet,\n transport: custom(window.ethereum),\n account,\n });\n }\n throw new Error('No Ethereum browser provider detected');\n};\n```\n\nThis file initializes a viem client, providing helper functions for obtaining a Public Client and a [Wallet Client](https://viem.sh/docs/clients/wallet#wallet-client){target=\\_blank}. The Public Client enables reading blockchain data, while the Wallet Client allows users to sign and send transactions. Also, note that by importing `viem/window` the global `window.ethereum` will be typed as an `EIP1193Provider`, check the [`window` Polyfill](https://viem.sh/docs/typescript#window-polyfill){target=\\_blank} reference for more information."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 12, "depth": 2, "title": "Set Up the Smart Contract Interface", "anchor": "set-up-the-smart-contract-interface", "start_char": 10052, "end_char": 11943, "estimated_token_count": 415, "token_estimator": "heuristic-v1", "text": "## Set Up the Smart Contract Interface\n\nFor this dApp, you'll use a simple [Storage contract](/tutorials/smart-contracts/launch-your-first-project/create-contracts){target=\\_blank} that's already deployed in the Polkadot Hub TestNet: `0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3`. To interact with it, you need to define the contract interface.\n\nCreate a folder called `abis` at the root of your project, then create a file named `Storage.json` and paste the corresponding ABI of the Storage contract. You can copy and paste the following:\n\n```bash\ncp ./storage-contract/artifacts/contracts/Storage.sol/Storage.json ./dapp/abis/Storage.json\n```\n\nNext, create a file called `utils/contract.ts`:\n\n```typescript title=\"contract.ts\"\nimport { getContract } from 'viem';\nimport { publicClient, getWalletClient } from './viem';\nimport StorageABI from '../abis/Storage.json';\n\nexport const CONTRACT_ADDRESS = '0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3'; // TODO: change when the paseo asset hub RPC URL is available, and the contract is redeployed\nexport const CONTRACT_ABI = StorageABI.abi;\n\n// Create a function to get a contract instance for reading\nexport const getContractInstance = () => {\n return getContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n client: publicClient,\n });\n};\n\n// Create a function to get a contract instance with a signer for writing\nexport const getSignedContract = async () => {\n const walletClient = await getWalletClient();\n return getContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n client: walletClient,\n });\n};\n```\n\nThis file defines the contract address, ABI, and functions to create a viem [contract instance](https://viem.sh/docs/contract/getContract#contract-instances){target=\\_blank} for reading and writing operations. viem's contract utilities enable more efficient, type-safe interaction with smart contracts."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 13, "depth": 2, "title": "Create the Wallet Connection Component", "anchor": "create-the-wallet-connection-component", "start_char": 11943, "end_char": 17968, "estimated_token_count": 1343, "token_estimator": "heuristic-v1", "text": "## Create the Wallet Connection Component\n\nNow, let's create a component to handle wallet connections. Create a new file called `components/WalletConnect.tsx`:\n\n```typescript title=\"WalletConnect.tsx\"\n\"use client\";\n\nimport React, { useState, useEffect } from \"react\";\nimport { polkadotTestnet } from \"../utils/viem\";\n\ninterface WalletConnectProps {\n onConnect: (account: string) => void;\n}\n\nconst WalletConnect: React.FC = ({ onConnect }) => {\n const [account, setAccount] = useState(null);\n const [chainId, setChainId] = useState(null);\n const [error, setError] = useState(null);\n\n useEffect(() => {\n // Check if user already has an authorized wallet connection\n const checkConnection = async () => {\n if (typeof window !== 'undefined' && window.ethereum) {\n try {\n // eth_accounts doesn't trigger the wallet popup\n const accounts = await window.ethereum.request({\n method: 'eth_accounts',\n }) as string[];\n \n if (accounts.length > 0) {\n setAccount(accounts[0]);\n const chainIdHex = await window.ethereum.request({\n method: 'eth_chainId',\n }) as string;\n setChainId(parseInt(chainIdHex, 16));\n onConnect(accounts[0]);\n }\n } catch (err) {\n console.error('Error checking connection:', err);\n setError('Failed to check wallet connection');\n }\n }\n };\n\n checkConnection();\n\n if (typeof window !== 'undefined' && window.ethereum) {\n // Setup wallet event listeners\n window.ethereum.on('accountsChanged', (accounts: string[]) => {\n setAccount(accounts[0] || null);\n if (accounts[0]) onConnect(accounts[0]);\n });\n\n window.ethereum.on('chainChanged', (chainIdHex: string) => {\n setChainId(parseInt(chainIdHex, 16));\n });\n }\n\n return () => {\n // Cleanup event listeners\n if (typeof window !== 'undefined' && window.ethereum) {\n window.ethereum.removeListener('accountsChanged', () => {});\n window.ethereum.removeListener('chainChanged', () => {});\n }\n };\n }, [onConnect]);\n\n const connectWallet = async () => {\n if (typeof window === 'undefined' || !window.ethereum) {\n setError(\n 'MetaMask not detected! Please install MetaMask to use this dApp.'\n );\n return;\n }\n\n try {\n // eth_requestAccounts triggers the wallet popup\n const accounts = await window.ethereum.request({\n method: 'eth_requestAccounts',\n }) as string[];\n \n setAccount(accounts[0]);\n\n const chainIdHex = await window.ethereum.request({\n method: 'eth_chainId',\n }) as string;\n \n const currentChainId = parseInt(chainIdHex, 16);\n setChainId(currentChainId);\n\n // Prompt user to switch networks if needed\n if (currentChainId !== polkadotTestnet.id) {\n await switchNetwork();\n }\n\n onConnect(accounts[0]);\n } catch (err) {\n console.error('Error connecting to wallet:', err);\n setError('Failed to connect wallet');\n }\n };\n\n const switchNetwork = async () => {\n console.log('Switch network')\n try {\n await window.ethereum.request({\n method: 'wallet_switchEthereumChain',\n params: [{ chainId: `0x${polkadotTestnet.id.toString(16)}` }],\n });\n } catch (switchError: any) {\n // Error 4902 means the chain hasn't been added to MetaMask\n if (switchError.code === 4902) {\n try {\n await window.ethereum.request({\n method: 'wallet_addEthereumChain',\n params: [\n {\n chainId: `0x${polkadotTestnet.id.toString(16)}`,\n chainName: polkadotTestnet.name,\n rpcUrls: [polkadotTestnet.rpcUrls.default.http[0]],\n nativeCurrency: {\n name: polkadotTestnet.nativeCurrency.name,\n symbol: polkadotTestnet.nativeCurrency.symbol,\n decimals: polkadotTestnet.nativeCurrency.decimals,\n },\n },\n ],\n });\n } catch (addError) {\n setError('Failed to add network to wallet');\n }\n } else {\n setError('Failed to switch network');\n }\n }\n };\n\n // UI-only disconnection - MetaMask doesn't support programmatic disconnection\n const disconnectWallet = () => {\n setAccount(null);\n };\n\n return (\n
\n {error &&

{error}

}\n\n {!account ? (\n \n Connect Wallet\n \n ) : (\n
\n \n {`${account.substring(0, 6)}...${account.substring(38)}`}\n \n \n Disconnect\n \n {chainId !== polkadotTestnet.id && (\n \n Switch to Polkadot Testnet\n \n )}\n
\n )}\n
\n );\n};\n\nexport default WalletConnect;\n```\n\nThis component handles connecting to the wallet, switching networks if necessary, and keeping track of the connected account. It provides a button for users to connect their wallet and displays the connected account address once connected."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 14, "depth": 2, "title": "Create the Read Contract Component", "anchor": "create-the-read-contract-component", "start_char": 17968, "end_char": 20502, "estimated_token_count": 617, "token_estimator": "heuristic-v1", "text": "## Create the Read Contract Component\n\nNow, let's create a component to read data from the contract. Create a file called `components/ReadContract.tsx`:\n\n```typescript title=\"ReadContract.tsx\"\n'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { publicClient } from '../utils/viem';\nimport { CONTRACT_ADDRESS, CONTRACT_ABI } from '../utils/contract';\n\nconst ReadContract: React.FC = () => {\n const [storedNumber, setStoredNumber] = useState(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(null);\n\n useEffect(() => {\n // Function to read data from the blockchain\n const fetchData = async () => {\n try {\n setLoading(true);\n // Call the smart contract's storedNumber function\n const number = await publicClient.readContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n functionName: 'storedNumber',\n args: [],\n }) as bigint;\n\n setStoredNumber(number.toString());\n setError(null);\n } catch (err) {\n console.error('Error fetching stored number:', err);\n setError('Failed to fetch data from the contract');\n } finally {\n setLoading(false);\n }\n };\n\n fetchData();\n\n // Poll for updates every 10 seconds to keep UI in sync with blockchain\n const interval = setInterval(fetchData, 10000);\n\n // Clean up interval on component unmount\n return () => clearInterval(interval);\n }, []);\n\n return (\n
\n

Contract Data

\n {loading ? (\n
\n
\n
\n ) : error ? (\n

{error}

\n ) : (\n
\n

\n Stored Number: {storedNumber}\n

\n
\n )}\n
\n );\n};\n\nexport default ReadContract;\n```\n\nThis component reads the `storedNumber` value from the contract and displays it to the user. It also sets up a polling interval to refresh the data periodically, ensuring that the UI stays in sync with the blockchain state."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 15, "depth": 2, "title": "Create the Write Contract Component", "anchor": "create-the-write-contract-component", "start_char": 20502, "end_char": 28611, "estimated_token_count": 1825, "token_estimator": "heuristic-v1", "text": "## Create the Write Contract Component\n\nFinally, let's create a component that allows users to update the stored number. Create a file called `components/WriteContract.tsx`:\n\n```typescript title=\"WriteContract.tsx\"\n\"use client\";\n\nimport React, { useState, useEffect } from \"react\";\nimport { publicClient, getWalletClient } from '../utils/viem';\nimport { CONTRACT_ADDRESS, CONTRACT_ABI } from '../utils/contract';\n\ninterface WriteContractProps {\n account: string | null;\n}\n\nconst WriteContract: React.FC = ({ account }) => {\n const [newNumber, setNewNumber] = useState(\"\");\n const [status, setStatus] = useState<{\n type: string | null;\n message: string;\n }>({\n type: null,\n message: \"\",\n });\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isCorrectNetwork, setIsCorrectNetwork] = useState(true);\n\n // Check if the account is on the correct network\n useEffect(() => {\n const checkNetwork = async () => {\n if (!account) return;\n\n try {\n // Get the chainId from the public client\n const chainId = await publicClient.getChainId();\n\n // Get the user's current chainId from their wallet\n const walletClient = await getWalletClient();\n if (!walletClient) return;\n\n const walletChainId = await walletClient.getChainId();\n\n // Check if they match\n setIsCorrectNetwork(chainId === walletChainId);\n } catch (err) {\n console.error(\"Error checking network:\", err);\n setIsCorrectNetwork(false);\n }\n };\n\n checkNetwork();\n }, [account]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n // Validation checks\n if (!account) {\n setStatus({ type: \"error\", message: \"Please connect your wallet first\" });\n return;\n }\n\n if (!isCorrectNetwork) {\n setStatus({\n type: \"error\",\n message: \"Please switch to the correct network in your wallet\",\n });\n return;\n }\n\n if (!newNumber || isNaN(Number(newNumber))) {\n setStatus({ type: \"error\", message: \"Please enter a valid number\" });\n return;\n }\n\n try {\n setIsSubmitting(true);\n setStatus({ type: \"info\", message: \"Initiating transaction...\" });\n\n // Get wallet client for transaction signing\n const walletClient = await getWalletClient();\n\n if (!walletClient) {\n setStatus({ type: \"error\", message: \"Wallet client not available\" });\n return;\n }\n\n // Check if account matches\n if (\n walletClient.account?.address.toLowerCase() !== account.toLowerCase()\n ) {\n setStatus({\n type: \"error\",\n message:\n \"Connected wallet account doesn't match the selected account\",\n });\n return;\n }\n\n // Prepare transaction and wait for user confirmation in wallet\n setStatus({\n type: \"info\",\n message: \"Please confirm the transaction in your wallet...\",\n });\n\n // Simulate the contract call first\n console.log('newNumber', newNumber);\n const { request } = await publicClient.simulateContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n functionName: \"setNumber\",\n args: [BigInt(newNumber)],\n account: walletClient.account,\n });\n\n // Send the transaction with wallet client\n const hash = await walletClient.writeContract(request);\n\n // Wait for transaction to be mined\n setStatus({\n type: \"info\",\n message: \"Transaction submitted. Waiting for confirmation...\",\n });\n\n const receipt = await publicClient.waitForTransactionReceipt({\n hash,\n });\n\n setStatus({\n type: \"success\",\n message: `Transaction confirmed! Transaction hash: ${receipt.transactionHash}`,\n });\n\n setNewNumber(\"\");\n } catch (err: any) {\n console.error(\"Error updating number:\", err);\n\n // Handle specific errors\n if (err.code === 4001) {\n // User rejected transaction\n setStatus({ type: \"error\", message: \"Transaction rejected by user.\" });\n } else if (err.message?.includes(\"Account not found\")) {\n // Account not found on the network\n setStatus({\n type: \"error\",\n message:\n \"Account not found on current network. Please check your wallet is connected to the correct network.\",\n });\n } else if (err.message?.includes(\"JSON is not a valid request object\")) {\n // JSON error - specific to your current issue\n setStatus({\n type: \"error\",\n message:\n \"Invalid request format. Please try again or contact support.\",\n });\n } else {\n // Other errors\n setStatus({\n type: \"error\",\n message: `Error: ${err.message || \"Failed to send transaction\"}`,\n });\n }\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n
\n

Update Stored Number

\n\n {!isCorrectNetwork && account && (\n
\n ⚠️ You are not connected to the correct network. Please switch\n networks in your wallet.\n
\n )}\n\n {status.message && (\n \n {status.message}\n
\n )}\n\n
\n setNewNumber(e.target.value)}\n disabled={isSubmitting || !account}\n className=\"w-full p-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-pink-400\"\n />\n \n {isSubmitting ? \"Updating...\" : \"Update\"}\n \n \n\n {!account && (\n

\n Connect your wallet to update the stored number.\n

\n )}\n
\n );\n};\n\nexport default WriteContract;\n```\n\nThis component allows users to input a new number and send a transaction to update the value stored in the contract. It provides appropriate feedback during each step of the transaction process and handles error scenarios.\n\nUpdate the `app/page.tsx` file to integrate all components:\n\n```typescript title=\"page.tsx\"\n\"use client\";\n\nimport { useState } from \"react\";\nimport WalletConnect from \"./components/WalletConnect\";\nimport ReadContract from \"./components/ReadContract\";\nimport WriteContract from \"./components/WriteContract\";\n\nexport default function Home() {\n const [account, setAccount] = useState(null);\n\n const handleConnect = (connectedAccount: string) => {\n setAccount(connectedAccount);\n };\n\n return (\n
\n

\n Polkadot Hub - Zero To Hero DApp\n

\n \n \n \n
\n );\n}\n```\n\nRun the dApp:\n\n```bash\nnpm run dev\n```\n\nNavigate to `http://localhost:3000` in your browser, and you should see your dApp with the wallet connection button, the stored number displayed, and the form to update the number. You should see something like this:"} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 16, "depth": 2, "title": "How It Works", "anchor": "how-it-works", "start_char": 28611, "end_char": 28704, "estimated_token_count": 18, "token_estimator": "heuristic-v1", "text": "## How It Works\n\nThis dApp uses components to interact with the blockchain in several ways."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 17, "depth": 3, "title": "Wallet Connection", "anchor": "wallet-connection", "start_char": 28704, "end_char": 29010, "estimated_token_count": 60, "token_estimator": "heuristic-v1", "text": "### Wallet Connection \n\nThe `WalletConnect` component uses the browser's Ethereum provider (MetaMask) to connect to the user's wallet and handles network switching to ensure the user is connected to the Polkadot Hub TestNet. Once connected, it provides the user's account address to the parent component."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 18, "depth": 3, "title": "Data Reads", "anchor": "data-reads", "start_char": 29010, "end_char": 29311, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "### Data Reads\n\nThe `ReadContract` component uses viem's `readContract` function to call the `storedNumber` view function and periodically poll for updates to keep the UI in sync with the blockchain state. The component also displays a loading indicator while fetching data and handles error states."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 19, "depth": 3, "title": "Data Writes", "anchor": "data-writes", "start_char": 29311, "end_char": 29713, "estimated_token_count": 71, "token_estimator": "heuristic-v1", "text": "### Data Writes\n\nThe `WriteContract` component uses viem's `writeContract` function to send a transaction to the `setNumber` function and ensures the wallet is connected before allowing a transaction. The component shows detailed feedback during transaction submission and confirmation. After a successful transaction, the value displayed in the `ReadContract` component will update on the next poll."} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 20, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 29713, "end_char": 30610, "estimated_token_count": 178, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nCongratulations! You've successfully built a fully functional dApp that interacts with a smart contract on Polkadot Hub using viem and Next.js. Your application can now:\n\n- Create a smart contract with Hardhat and deploy it to Polkadot Hub TestNet.\n- Connect to a user's wallet and handle network switching.\n- Read data from a smart contract and keep it updated.\n- Write data to the blockchain through transactions.\n\nThese fundamental skills provide the foundation for building more complex dApps on Polkadot Hub. With this knowledge, you can extend your application to interact with more sophisticated smart contracts and create advanced user interfaces.\n\nTo get started right away with a working example, you can clone the repository and navigate to the implementation:\n\n```bash\ngit clone https://github.com/polkadot-developers/revm-hardhat-examples.git\ncd zero-to-hero-dapp\n```"} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 21, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 30610, "end_char": 31203, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Guide __Port Ethereum Projects to Polkadot Hub__\n\n ---\n\n Learn how to port an Ethereum project to Polkadot Hub using Hardhat and Viem.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/eth-dapps/)\n\n- Guide __Dive Deeper into Polkadot Precompiles__\n\n ---\n\n Learn how to use the Polkadot precompiles to interact with the blockchain.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/polkadot-precompiles/)\n
"} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 7, "depth": 3, "title": "Deploy the Contract", "anchor": "deploy-the-contract", "start_char": 5579, "end_char": 7216, "estimated_token_count": 416, "token_estimator": "heuristic-v1", "text": "### Deploy the Contract\n\nCreate a deployment script in the `ignition/modules` directory called `Storage.ts`:\n\n```typescript title=\"Storage.ts\"\nimport { buildModule } from \"@nomicfoundation/hardhat-ignition/modules\";\n\nexport default buildModule(\"StorageModule\", (m) => {\n const storage = m.contract(\"Storage\");\n\n return { storage };\n});\n```\n\nDeploy the contract to Polkadot Hub TestNet:\n\n```bash\nnpx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotTestNet\n```\n\nYou should see output similar to:\n\n
\n npx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotTestNet\n WARNING: You are using Node.js 23.11.0 which is not supported by Hardhat.\n Please upgrade to 22.10.0 or a later LTS version (even major version number)\n ✔ Confirm deploy to network polkadotTestNet (420420420)? … yes\n Hardhat Ignition 🚀\n Deploying [ StorageModule ]\n Batch #1\n Executed StorageModule#Storage\n [ StorageModule ] successfully deployed 🚀\n Deployed Addresses\n StorageModule#Storage - 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3\n
\n\n!!! note\n Save the deployed contract address - you'll need it when building your dApp. In the following sections, we'll reference a pre-deployed contract at `0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3`, but you can use your own deployed contract address instead."} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 8, "depth": 3, "title": "Export the Contract ABI", "anchor": "export-the-contract-abi", "start_char": 7216, "end_char": 7603, "estimated_token_count": 89, "token_estimator": "heuristic-v1", "text": "### Export the Contract ABI\n\nAfter deployment, you'll need the contract's Application Binary Interface (ABI) for your dApp. You can find it in the `artifacts/contracts/Storage.sol/Storage.json` file generated by Hardhat. You'll use this in the next section when setting up your dApp.\n\nNow that you have your contract deployed, you're ready to build the dApp that will interact with it!"} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 9, "depth": 2, "title": "Set Up the dApp Project", "anchor": "set-up-the-dapp-project", "start_char": 7603, "end_char": 7800, "estimated_token_count": 59, "token_estimator": "heuristic-v1", "text": "## Set Up the dApp Project\n\nNavigate to the root of the project, and create a new Next.js project called `dapp`:\n\n```bash\nnpx create-next-app dapp --ts --eslint --tailwind --app --yes\ncd dapp\n```"} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 10, "depth": 2, "title": "Install Dependencies", "anchor": "install-dependencies", "start_char": 7800, "end_char": 7959, "estimated_token_count": 50, "token_estimator": "heuristic-v1", "text": "## Install Dependencies\n\nInstall viem and related packages:\n\n```bash\nnpm install viem@2.38.5\nnpm install --save-dev typescript@5.9.3 @types/node@22.19.24\n```"} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 11, "depth": 2, "title": "Connect to Polkadot Hub", "anchor": "connect-to-polkadot-hub", "start_char": 7959, "end_char": 10056, "estimated_token_count": 509, "token_estimator": "heuristic-v1", "text": "## Connect to Polkadot Hub\n\nTo interact with Polkadot Hub, you need to set up a [Public Client](https://viem.sh/docs/clients/public#public-client){target=\\_blank} that connects to the blockchain. In this example, you will interact with the Polkadot Hub TestNet, to experiment safely. Start by creating a new file called `utils/viem.ts` and add the following code:\n\n```typescript title=\"viem.ts\"\nimport { createPublicClient, http, createWalletClient, custom } from 'viem'\nimport 'viem/window';\n\nconst transport = http('http://127.0.0.1:8545') // TODO: change to the paseo asset hub RPC URL when it's available\n\n// Configure the Polkadot Testnet Hub chain\nexport const polkadotTestnet = {\n id: 420420420,\n name: 'Polkadot Testnet',\n network: 'polkadot-testnet',\n nativeCurrency: {\n decimals: 18,\n name: 'PAS',\n symbol: 'PAS',\n },\n rpcUrls: {\n default: {\n http: ['http://127.0.0.1:8545'], // TODO: change to the paseo asset hub RPC URL\n },\n },\n} as const\n\n// Create a public client for reading data\nexport const publicClient = createPublicClient({\n chain: polkadotTestnet,\n transport\n})\n\n// Create a wallet client for signing transactions\nexport const getWalletClient = async () => {\n if (typeof window !== 'undefined' && window.ethereum) {\n const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });\n return createWalletClient({\n chain: polkadotTestnet,\n transport: custom(window.ethereum),\n account,\n });\n }\n throw new Error('No Ethereum browser provider detected');\n};\n```\n\nThis file initializes a viem client, providing helper functions for obtaining a Public Client and a [Wallet Client](https://viem.sh/docs/clients/wallet#wallet-client){target=\\_blank}. The Public Client enables reading blockchain data, while the Wallet Client allows users to sign and send transactions. Also, note that by importing `viem/window` the global `window.ethereum` will be typed as an `EIP1193Provider`, check the [`window` Polyfill](https://viem.sh/docs/typescript#window-polyfill){target=\\_blank} reference for more information."} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 12, "depth": 2, "title": "Set Up the Smart Contract Interface", "anchor": "set-up-the-smart-contract-interface", "start_char": 10056, "end_char": 11947, "estimated_token_count": 415, "token_estimator": "heuristic-v1", "text": "## Set Up the Smart Contract Interface\n\nFor this dApp, you'll use a simple [Storage contract](/tutorials/smart-contracts/launch-your-first-project/create-contracts){target=\\_blank} that's already deployed in the Polkadot Hub TestNet: `0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3`. To interact with it, you need to define the contract interface.\n\nCreate a folder called `abis` at the root of your project, then create a file named `Storage.json` and paste the corresponding ABI of the Storage contract. You can copy and paste the following:\n\n```bash\ncp ./storage-contract/artifacts/contracts/Storage.sol/Storage.json ./dapp/abis/Storage.json\n```\n\nNext, create a file called `utils/contract.ts`:\n\n```typescript title=\"contract.ts\"\nimport { getContract } from 'viem';\nimport { publicClient, getWalletClient } from './viem';\nimport StorageABI from '../abis/Storage.json';\n\nexport const CONTRACT_ADDRESS = '0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3'; // TODO: change when the paseo asset hub RPC URL is available, and the contract is redeployed\nexport const CONTRACT_ABI = StorageABI.abi;\n\n// Create a function to get a contract instance for reading\nexport const getContractInstance = () => {\n return getContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n client: publicClient,\n });\n};\n\n// Create a function to get a contract instance with a signer for writing\nexport const getSignedContract = async () => {\n const walletClient = await getWalletClient();\n return getContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n client: walletClient,\n });\n};\n```\n\nThis file defines the contract address, ABI, and functions to create a viem [contract instance](https://viem.sh/docs/contract/getContract#contract-instances){target=\\_blank} for reading and writing operations. viem's contract utilities enable more efficient, type-safe interaction with smart contracts."} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 13, "depth": 2, "title": "Create the Wallet Connection Component", "anchor": "create-the-wallet-connection-component", "start_char": 11947, "end_char": 17972, "estimated_token_count": 1343, "token_estimator": "heuristic-v1", "text": "## Create the Wallet Connection Component\n\nNow, let's create a component to handle wallet connections. Create a new file called `components/WalletConnect.tsx`:\n\n```typescript title=\"WalletConnect.tsx\"\n\"use client\";\n\nimport React, { useState, useEffect } from \"react\";\nimport { polkadotTestnet } from \"../utils/viem\";\n\ninterface WalletConnectProps {\n onConnect: (account: string) => void;\n}\n\nconst WalletConnect: React.FC = ({ onConnect }) => {\n const [account, setAccount] = useState(null);\n const [chainId, setChainId] = useState(null);\n const [error, setError] = useState(null);\n\n useEffect(() => {\n // Check if user already has an authorized wallet connection\n const checkConnection = async () => {\n if (typeof window !== 'undefined' && window.ethereum) {\n try {\n // eth_accounts doesn't trigger the wallet popup\n const accounts = await window.ethereum.request({\n method: 'eth_accounts',\n }) as string[];\n \n if (accounts.length > 0) {\n setAccount(accounts[0]);\n const chainIdHex = await window.ethereum.request({\n method: 'eth_chainId',\n }) as string;\n setChainId(parseInt(chainIdHex, 16));\n onConnect(accounts[0]);\n }\n } catch (err) {\n console.error('Error checking connection:', err);\n setError('Failed to check wallet connection');\n }\n }\n };\n\n checkConnection();\n\n if (typeof window !== 'undefined' && window.ethereum) {\n // Setup wallet event listeners\n window.ethereum.on('accountsChanged', (accounts: string[]) => {\n setAccount(accounts[0] || null);\n if (accounts[0]) onConnect(accounts[0]);\n });\n\n window.ethereum.on('chainChanged', (chainIdHex: string) => {\n setChainId(parseInt(chainIdHex, 16));\n });\n }\n\n return () => {\n // Cleanup event listeners\n if (typeof window !== 'undefined' && window.ethereum) {\n window.ethereum.removeListener('accountsChanged', () => {});\n window.ethereum.removeListener('chainChanged', () => {});\n }\n };\n }, [onConnect]);\n\n const connectWallet = async () => {\n if (typeof window === 'undefined' || !window.ethereum) {\n setError(\n 'MetaMask not detected! Please install MetaMask to use this dApp.'\n );\n return;\n }\n\n try {\n // eth_requestAccounts triggers the wallet popup\n const accounts = await window.ethereum.request({\n method: 'eth_requestAccounts',\n }) as string[];\n \n setAccount(accounts[0]);\n\n const chainIdHex = await window.ethereum.request({\n method: 'eth_chainId',\n }) as string;\n \n const currentChainId = parseInt(chainIdHex, 16);\n setChainId(currentChainId);\n\n // Prompt user to switch networks if needed\n if (currentChainId !== polkadotTestnet.id) {\n await switchNetwork();\n }\n\n onConnect(accounts[0]);\n } catch (err) {\n console.error('Error connecting to wallet:', err);\n setError('Failed to connect wallet');\n }\n };\n\n const switchNetwork = async () => {\n console.log('Switch network')\n try {\n await window.ethereum.request({\n method: 'wallet_switchEthereumChain',\n params: [{ chainId: `0x${polkadotTestnet.id.toString(16)}` }],\n });\n } catch (switchError: any) {\n // Error 4902 means the chain hasn't been added to MetaMask\n if (switchError.code === 4902) {\n try {\n await window.ethereum.request({\n method: 'wallet_addEthereumChain',\n params: [\n {\n chainId: `0x${polkadotTestnet.id.toString(16)}`,\n chainName: polkadotTestnet.name,\n rpcUrls: [polkadotTestnet.rpcUrls.default.http[0]],\n nativeCurrency: {\n name: polkadotTestnet.nativeCurrency.name,\n symbol: polkadotTestnet.nativeCurrency.symbol,\n decimals: polkadotTestnet.nativeCurrency.decimals,\n },\n },\n ],\n });\n } catch (addError) {\n setError('Failed to add network to wallet');\n }\n } else {\n setError('Failed to switch network');\n }\n }\n };\n\n // UI-only disconnection - MetaMask doesn't support programmatic disconnection\n const disconnectWallet = () => {\n setAccount(null);\n };\n\n return (\n
\n {error &&

{error}

}\n\n {!account ? (\n \n Connect Wallet\n \n ) : (\n
\n \n {`${account.substring(0, 6)}...${account.substring(38)}`}\n \n \n Disconnect\n \n {chainId !== polkadotTestnet.id && (\n \n Switch to Polkadot Testnet\n \n )}\n
\n )}\n
\n );\n};\n\nexport default WalletConnect;\n```\n\nThis component handles connecting to the wallet, switching networks if necessary, and keeping track of the connected account. It provides a button for users to connect their wallet and displays the connected account address once connected."} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 14, "depth": 2, "title": "Create the Read Contract Component", "anchor": "create-the-read-contract-component", "start_char": 17972, "end_char": 20506, "estimated_token_count": 617, "token_estimator": "heuristic-v1", "text": "## Create the Read Contract Component\n\nNow, let's create a component to read data from the contract. Create a file called `components/ReadContract.tsx`:\n\n```typescript title=\"ReadContract.tsx\"\n'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport { publicClient } from '../utils/viem';\nimport { CONTRACT_ADDRESS, CONTRACT_ABI } from '../utils/contract';\n\nconst ReadContract: React.FC = () => {\n const [storedNumber, setStoredNumber] = useState(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(null);\n\n useEffect(() => {\n // Function to read data from the blockchain\n const fetchData = async () => {\n try {\n setLoading(true);\n // Call the smart contract's storedNumber function\n const number = await publicClient.readContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n functionName: 'storedNumber',\n args: [],\n }) as bigint;\n\n setStoredNumber(number.toString());\n setError(null);\n } catch (err) {\n console.error('Error fetching stored number:', err);\n setError('Failed to fetch data from the contract');\n } finally {\n setLoading(false);\n }\n };\n\n fetchData();\n\n // Poll for updates every 10 seconds to keep UI in sync with blockchain\n const interval = setInterval(fetchData, 10000);\n\n // Clean up interval on component unmount\n return () => clearInterval(interval);\n }, []);\n\n return (\n
\n

Contract Data

\n {loading ? (\n
\n
\n
\n ) : error ? (\n

{error}

\n ) : (\n
\n

\n Stored Number: {storedNumber}\n

\n
\n )}\n
\n );\n};\n\nexport default ReadContract;\n```\n\nThis component reads the `storedNumber` value from the contract and displays it to the user. It also sets up a polling interval to refresh the data periodically, ensuring that the UI stays in sync with the blockchain state."} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 15, "depth": 2, "title": "Create the Write Contract Component", "anchor": "create-the-write-contract-component", "start_char": 20506, "end_char": 28615, "estimated_token_count": 1825, "token_estimator": "heuristic-v1", "text": "## Create the Write Contract Component\n\nFinally, let's create a component that allows users to update the stored number. Create a file called `components/WriteContract.tsx`:\n\n```typescript title=\"WriteContract.tsx\"\n\"use client\";\n\nimport React, { useState, useEffect } from \"react\";\nimport { publicClient, getWalletClient } from '../utils/viem';\nimport { CONTRACT_ADDRESS, CONTRACT_ABI } from '../utils/contract';\n\ninterface WriteContractProps {\n account: string | null;\n}\n\nconst WriteContract: React.FC = ({ account }) => {\n const [newNumber, setNewNumber] = useState(\"\");\n const [status, setStatus] = useState<{\n type: string | null;\n message: string;\n }>({\n type: null,\n message: \"\",\n });\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isCorrectNetwork, setIsCorrectNetwork] = useState(true);\n\n // Check if the account is on the correct network\n useEffect(() => {\n const checkNetwork = async () => {\n if (!account) return;\n\n try {\n // Get the chainId from the public client\n const chainId = await publicClient.getChainId();\n\n // Get the user's current chainId from their wallet\n const walletClient = await getWalletClient();\n if (!walletClient) return;\n\n const walletChainId = await walletClient.getChainId();\n\n // Check if they match\n setIsCorrectNetwork(chainId === walletChainId);\n } catch (err) {\n console.error(\"Error checking network:\", err);\n setIsCorrectNetwork(false);\n }\n };\n\n checkNetwork();\n }, [account]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n // Validation checks\n if (!account) {\n setStatus({ type: \"error\", message: \"Please connect your wallet first\" });\n return;\n }\n\n if (!isCorrectNetwork) {\n setStatus({\n type: \"error\",\n message: \"Please switch to the correct network in your wallet\",\n });\n return;\n }\n\n if (!newNumber || isNaN(Number(newNumber))) {\n setStatus({ type: \"error\", message: \"Please enter a valid number\" });\n return;\n }\n\n try {\n setIsSubmitting(true);\n setStatus({ type: \"info\", message: \"Initiating transaction...\" });\n\n // Get wallet client for transaction signing\n const walletClient = await getWalletClient();\n\n if (!walletClient) {\n setStatus({ type: \"error\", message: \"Wallet client not available\" });\n return;\n }\n\n // Check if account matches\n if (\n walletClient.account?.address.toLowerCase() !== account.toLowerCase()\n ) {\n setStatus({\n type: \"error\",\n message:\n \"Connected wallet account doesn't match the selected account\",\n });\n return;\n }\n\n // Prepare transaction and wait for user confirmation in wallet\n setStatus({\n type: \"info\",\n message: \"Please confirm the transaction in your wallet...\",\n });\n\n // Simulate the contract call first\n console.log('newNumber', newNumber);\n const { request } = await publicClient.simulateContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n functionName: \"setNumber\",\n args: [BigInt(newNumber)],\n account: walletClient.account,\n });\n\n // Send the transaction with wallet client\n const hash = await walletClient.writeContract(request);\n\n // Wait for transaction to be mined\n setStatus({\n type: \"info\",\n message: \"Transaction submitted. Waiting for confirmation...\",\n });\n\n const receipt = await publicClient.waitForTransactionReceipt({\n hash,\n });\n\n setStatus({\n type: \"success\",\n message: `Transaction confirmed! Transaction hash: ${receipt.transactionHash}`,\n });\n\n setNewNumber(\"\");\n } catch (err: any) {\n console.error(\"Error updating number:\", err);\n\n // Handle specific errors\n if (err.code === 4001) {\n // User rejected transaction\n setStatus({ type: \"error\", message: \"Transaction rejected by user.\" });\n } else if (err.message?.includes(\"Account not found\")) {\n // Account not found on the network\n setStatus({\n type: \"error\",\n message:\n \"Account not found on current network. Please check your wallet is connected to the correct network.\",\n });\n } else if (err.message?.includes(\"JSON is not a valid request object\")) {\n // JSON error - specific to your current issue\n setStatus({\n type: \"error\",\n message:\n \"Invalid request format. Please try again or contact support.\",\n });\n } else {\n // Other errors\n setStatus({\n type: \"error\",\n message: `Error: ${err.message || \"Failed to send transaction\"}`,\n });\n }\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n
\n

Update Stored Number

\n\n {!isCorrectNetwork && account && (\n
\n ⚠️ You are not connected to the correct network. Please switch\n networks in your wallet.\n
\n )}\n\n {status.message && (\n \n {status.message}\n
\n )}\n\n
\n setNewNumber(e.target.value)}\n disabled={isSubmitting || !account}\n className=\"w-full p-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-pink-400\"\n />\n \n {isSubmitting ? \"Updating...\" : \"Update\"}\n \n \n\n {!account && (\n

\n Connect your wallet to update the stored number.\n

\n )}\n
\n );\n};\n\nexport default WriteContract;\n```\n\nThis component allows users to input a new number and send a transaction to update the value stored in the contract. It provides appropriate feedback during each step of the transaction process and handles error scenarios.\n\nUpdate the `app/page.tsx` file to integrate all components:\n\n```typescript title=\"page.tsx\"\n\"use client\";\n\nimport { useState } from \"react\";\nimport WalletConnect from \"./components/WalletConnect\";\nimport ReadContract from \"./components/ReadContract\";\nimport WriteContract from \"./components/WriteContract\";\n\nexport default function Home() {\n const [account, setAccount] = useState(null);\n\n const handleConnect = (connectedAccount: string) => {\n setAccount(connectedAccount);\n };\n\n return (\n
\n

\n Polkadot Hub - Zero To Hero DApp\n

\n \n \n \n
\n );\n}\n```\n\nRun the dApp:\n\n```bash\nnpm run dev\n```\n\nNavigate to `http://localhost:3000` in your browser, and you should see your dApp with the wallet connection button, the stored number displayed, and the form to update the number. You should see something like this:"} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 16, "depth": 2, "title": "How It Works", "anchor": "how-it-works", "start_char": 28615, "end_char": 28708, "estimated_token_count": 18, "token_estimator": "heuristic-v1", "text": "## How It Works\n\nThis dApp uses components to interact with the blockchain in several ways."} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 17, "depth": 3, "title": "Wallet Connection", "anchor": "wallet-connection", "start_char": 28708, "end_char": 29014, "estimated_token_count": 60, "token_estimator": "heuristic-v1", "text": "### Wallet Connection \n\nThe `WalletConnect` component uses the browser's Ethereum provider (MetaMask) to connect to the user's wallet and handles network switching to ensure the user is connected to the Polkadot Hub TestNet. Once connected, it provides the user's account address to the parent component."} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 18, "depth": 3, "title": "Data Reads", "anchor": "data-reads", "start_char": 29014, "end_char": 29315, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "### Data Reads\n\nThe `ReadContract` component uses viem's `readContract` function to call the `storedNumber` view function and periodically poll for updates to keep the UI in sync with the blockchain state. The component also displays a loading indicator while fetching data and handles error states."} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 19, "depth": 3, "title": "Data Writes", "anchor": "data-writes", "start_char": 29315, "end_char": 29717, "estimated_token_count": 71, "token_estimator": "heuristic-v1", "text": "### Data Writes\n\nThe `WriteContract` component uses viem's `writeContract` function to send a transaction to the `setNumber` function and ensures the wallet is connected before allowing a transaction. The component shows detailed feedback during transaction submission and confirmation. After a successful transaction, the value displayed in the `ReadContract` component will update on the next poll."} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 20, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 29717, "end_char": 30614, "estimated_token_count": 178, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nCongratulations! You've successfully built a fully functional dApp that interacts with a smart contract on Polkadot Hub using viem and Next.js. Your application can now:\n\n- Create a smart contract with Hardhat and deploy it to Polkadot Hub TestNet.\n- Connect to a user's wallet and handle network switching.\n- Read data from a smart contract and keep it updated.\n- Write data to the blockchain through transactions.\n\nThese fundamental skills provide the foundation for building more complex dApps on Polkadot Hub. With this knowledge, you can extend your application to interact with more sophisticated smart contracts and create advanced user interfaces.\n\nTo get started right away with a working example, you can clone the repository and navigate to the implementation:\n\n```bash\ngit clone https://github.com/polkadot-developers/revm-hardhat-examples.git\ncd zero-to-hero-dapp\n```"} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 21, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 30614, "end_char": 31207, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Guide __Port Ethereum Projects to Polkadot Hub__\n\n ---\n\n Learn how to port an Ethereum project to Polkadot Hub using Hardhat and Viem.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/eth-dapps/)\n\n- Guide __Dive Deeper into Polkadot Precompiles__\n\n ---\n\n Learn how to use the Polkadot precompiles to interact with the blockchain.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/polkadot-precompiles/)\n
"} {"page_id": "smart-contracts-cookbook-eth-dapps-uniswap-v2", "page_title": "Deploying Uniswap V2 on Polkadot", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 191, "end_char": 857, "estimated_token_count": 131, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nDecentralized exchanges (DEXs) are a cornerstone of the DeFi ecosystem, allowing for permissionless token swaps without intermediaries. [Uniswap V2](https://docs.uniswap.org/contracts/v2/overview){target=\\_blank}, with its Automated Market Maker (AMM) model, revolutionized DEXs by enabling liquidity provision for any ERC-20 token pair.\n\nThis tutorial will guide you through how Uniswap V2 works so you can take advantage of it in your projects deployed to Polkadot Hub. By understanding these contracts, you'll gain hands-on experience with one of the most influential DeFi protocols and understand how it functions across blockchain ecosystems."} {"page_id": "smart-contracts-cookbook-eth-dapps-uniswap-v2", "page_title": "Deploying Uniswap V2 on Polkadot", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 857, "end_char": 1357, "estimated_token_count": 124, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore starting, make sure you have:\n\n- Node.js (v16.0.0 or later) and npm installed.\n- Basic understanding of Solidity and JavaScript.\n- Familiarity with [`hardhat-polkadot`](/smart-contracts/dev-environments/hardhat/get-started/){target=\\_blank} development environment.\n- Some PAS test tokens to cover transaction fees (obtained from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank}).\n- Basic understanding of how AMMs and liquidity pools work."} {"page_id": "smart-contracts-cookbook-eth-dapps-uniswap-v2", "page_title": "Deploying Uniswap V2 on Polkadot", "index": 2, "depth": 2, "title": "Set Up the Project", "anchor": "set-up-the-project", "start_char": 1357, "end_char": 3682, "estimated_token_count": 570, "token_estimator": "heuristic-v1", "text": "## Set Up the Project\n\nLet's start by cloning the Uniswap V2 project:\n\n1. Clone the Uniswap V2 repository:\n\n ```\n git clone https://github.com/polkadot-developers/polkavm-hardhat-examples.git -b v0.0.6\n cd polkavm-hardhat-examples/uniswap-v2-polkadot/\n ```\n\n2. Install the required dependencies:\n\n ```bash\n npm install\n ```\n\n3. Update the `hardhat.config.js` file so the paths for the Substrate node and the ETH-RPC adapter match with the paths on your machine. For more info, check the [Testing your Contract](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank} section in the Hardhat guide.\n\n ```js title=\"hardhat.config.js\"\n hardhat: {\n polkavm: true,\n nodeConfig: {\n nodeBinaryPath: '../bin/substrate-node',\n rpcPort: 8000,\n dev: true,\n },\n adapterConfig: {\n adapterBinaryPath: '../bin/eth-rpc',\n dev: true,\n },\n },\n ```\n\n4. Create a `.env` file in your project root to store your private keys (you can use as an example the `env.example` file):\n\n ```text title=\".env\"\n LOCAL_PRIV_KEY=\"INSERT_LOCAL_PRIVATE_KEY\"\n AH_PRIV_KEY=\"INSERT_AH_PRIVATE_KEY\"\n ```\n\n Ensure to replace `\"INSERT_LOCAL_PRIVATE_KEY\"` with a private key available in the local environment (you can get them from this [file](https://github.com/paritytech/hardhat-polkadot/blob/main/packages/hardhat-polkadot-node/src/constants.ts#L22){target=\\_blank}). And `\"INSERT_AH_PRIVATE_KEY\"` with the account's private key you want to use to deploy the contracts. You can get this by exporting the private key from your wallet (e.g., MetaMask).\n\n !!!warning\n Keep your private key safe, and never share it with anyone. If it is compromised, your funds can be stolen.\n\n5. Compile the contracts:\n\n ```bash\n npx hardhat compile\n ```\n\nIf the compilation is successful, you should see the following output:\n\n
\n npx hardhat compile\n Compiling 12 Solidity files\n Successfully compiled 12 Solidity files\n
\n\nAfter running the above command, you should see the compiled contracts in the `artifacts-pvm` directory. This directory contains the ABI and bytecode of your contracts."} @@ -1525,6 +1566,18 @@ {"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 32, "depth": 3, "title": "debug_traceCall", "anchor": "debug_tracecall", "start_char": 28867, "end_char": 31324, "estimated_token_count": 767, "token_estimator": "heuristic-v1", "text": "### debug_traceCall\n\nExecutes a new message call and returns a detailed execution trace without creating a transaction on the blockchain.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object, similar to `eth_call` parameters.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options (e.g., `tracer: \"callTracer\"`).\n\n**Example**:\n\n```bash title=\"debug_traceCall\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceCall\",\n \"params\":[{\n \"from\": \"INSERT_SENDER_ADDRESS\",\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_CALL\"\n }, \"INSERT_BLOCK_VALUE\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value.\n\n---"} {"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 33, "depth": 2, "title": "Response Format", "anchor": "response-format", "start_char": 31324, "end_char": 31507, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "## Response Format\n\nAll responses follow the standard JSON-RPC 2.0 format:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"result\": ... // The return value varies by method\n}\n```"} {"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 34, "depth": 2, "title": "Error Handling", "anchor": "error-handling", "start_char": 31507, "end_char": 31726, "estimated_token_count": 64, "token_estimator": "heuristic-v1", "text": "## Error Handling\n\nIf an error occurs, the response will include an error object:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"error\": {\n \"code\": -32000,\n \"message\": \"Error message here\"\n }\n}\n```"} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 37, "end_char": 303, "estimated_token_count": 40, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThis guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 1, "depth": 2, "title": "Migration Considerations", "anchor": "migration-considerations", "start_char": 303, "end_char": 645, "estimated_token_count": 62, "token_estimator": "heuristic-v1", "text": "## Migration Considerations\n\nTake into account the following considerations before migrating your contracts:\n\n- Standard ERC-20, ERC-721, ERC-1155 tokens work without changes.\n- DeFi protocols, DEXs, and AMMs migrate seamlessly.\n- DAOs and governance contracts are fully compatible.\n- Most Solidity contracts deploy identically to Ethereum."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 2, "depth": 2, "title": "Migration Checklist", "anchor": "migration-checklist", "start_char": 645, "end_char": 1058, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "## Migration Checklist\n\nBefore migrating your contracts, review this checklist:\n\n- Factory contracts using PVM bytecode need pre-uploaded dependencies.\n- Contracts using `EXTCODECOPY` for runtime manipulation require review (for projects that will use PVM bytecode, not EVM bytecode).\n- Replace `transfer()` and `send()` with proper reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode)."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 3, "depth": 2, "title": "Migration FAQs", "anchor": "migration-faqs", "start_char": 1058, "end_char": 1077, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Migration FAQs"} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 4, "depth": 3, "title": "Which backend should I choose?", "anchor": "which-backend-should-i-choose", "start_char": 1077, "end_char": 1706, "estimated_token_count": 107, "token_estimator": "heuristic-v1", "text": "### Which backend should I choose?\n\n- Choose REVM if you want:\n\n - Zero-modification deployment of existing Ethereum contracts.\n - Exact EVM behavior for audited code.\n - Compatibility with tools that inspect EVM bytecode.\n - Rapid deployment without optimization.\n\n- Choose PolkaVM if you want:\n\n - Better performance for computation-heavy applications.\n - Lower execution costs for intensive operations.\n - Access to next-generation smart contract features.\n\nIf you are unsure which to choose, start with REVM for immediate compatibility, then consider PolkaVM for performance optimization once deployed."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 5, "depth": 3, "title": "Do I need to rewrite my Solidity code?", "anchor": "do-i-need-to-rewrite-my-solidity-code", "start_char": 1706, "end_char": 1825, "estimated_token_count": 26, "token_estimator": "heuristic-v1", "text": "### Do I need to rewrite my Solidity code?\n\nNo, for most contracts. Standard Solidity patterns work on both backends."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 6, "depth": 3, "title": "What about factory contracts?", "anchor": "what-about-factory-contracts", "start_char": 1825, "end_char": 3177, "estimated_token_count": 244, "token_estimator": "heuristic-v1", "text": "### What about factory contracts?\n\n- **REVM**: Factory contracts work identically to Ethereum with no changes needed. \n \n The original factory pattern is:\n\n ```solidity\n contract TokenFactory {\n function createToken(string memory name) public returns (address) {\n // Creates new contract at runtime\n Token newToken = new Token(name);\n return address(newToken);\n }\n }\n ```\n\n- **PolkaVM**: Factory contracts require pre-uploading dependent contracts. \n\n Here's how to adapt the original factory pattern:\n\n ```solidity\n contract TokenFactory {\n // Reference pre-uploaded Token contract by hash\n bytes32 public tokenCodeHash;\n \n constructor(bytes32 _tokenCodeHash) {\n tokenCodeHash = _tokenCodeHash;\n }\n \n function createToken(string memory name) public returns (address) {\n // Instantiate from pre-uploaded code\n Token newToken = new Token{salt: keccak256(abi.encode(name))}(name);\n return address(newToken);\n }\n }\n ```\n\nThe deployment steps for PolkaVM factories are:\n\n1. Upload the contract code to the chain.\n2. Note the returned code hash.\n3. Deploy the Factory contract with the contract code hash.\n4. Factory can now instantiate contracts using the pre-uploaded code."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 7, "depth": 3, "title": "How do gas costs compare?", "anchor": "how-do-gas-costs-compare", "start_char": 3177, "end_char": 3328, "estimated_token_count": 47, "token_estimator": "heuristic-v1", "text": "### How do gas costs compare?\n\nFor more information on gas costs, see the [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\\_blank} page."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 8, "depth": 3, "title": "Which Solidity features are not supported?", "anchor": "which-solidity-features-are-not-supported", "start_char": 3328, "end_char": 3915, "estimated_token_count": 133, "token_estimator": "heuristic-v1", "text": "### Which Solidity features are not supported?\n\nFor REVM, any Solidity feature will function smoothly without requiring changes or adaptations. For PVM, there are considerations, as was mentioned above. \n\nFor PolkaVM, there are some considerations:\n\n- `EXTCODECOPY`: Only works in constructor code.\n- Runtime code modification: Use on-chain constructors instead.\n- **Gas stipends**: `address.send()` and `address.transfer()` don't provide reentrancy protection.\n- **Unsupported operations**: `pc`, `extcodecopy`, `selfdestruct`, `blobhash`, and `blobbasefee` (blob-related operations)."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 9, "depth": 3, "title": "How do I handle the existential deposit?", "anchor": "how-do-i-handle-the-existential-deposit", "start_char": 3915, "end_char": 4518, "estimated_token_count": 121, "token_estimator": "heuristic-v1", "text": "### How do I handle the existential deposit?\n\nPolkadot requires accounts to maintain a minimum balance (existential deposit or ED) to remain active.\n\nThis is handled automatically for you:\n\n- Balance queries via Ethereum RPC automatically deduct the ED.\n- New account transfers include ED in transaction fees.\n- Contract-to-contract transfers draw ED from the transaction signer.\n\nYou typically don't need to do anything special, but be aware:\n\n- Accounts below ED threshold are automatically deleted.\n- ED is around 0.01 DOT (varies by network).\n- Your contracts don't need to manage this explicitly."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 10, "depth": 3, "title": "Can I use my existing development tools?", "anchor": "can-i-use-my-existing-development-tools", "start_char": 4518, "end_char": 5499, "estimated_token_count": 304, "token_estimator": "heuristic-v1", "text": "### Can I use my existing development tools?\n\nYes. Both backends support:\n\n- **Wallets**: [MetaMask](https://metamask.io/){target=\\_blank}, [Talisman](https://talisman.xyz/){target=\\_blank}, [SubWallet](https://www.subwallet.app/){target=\\_blank}\n- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\\_blank}, [Foundry](/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/){target=\\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\\_blank} (just consider that for PVM bytecode, you will use the Polkadot version of the tooling)\n- **Libraries**: [ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank}, [web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank}, [viem](/smart-contracts/libraries/viem/){target=\\_blank}\n- **Testing tools**: Your existing test suites work\n\nConnect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 11, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 5499, "end_char": 6247, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nMost Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance.\n\nThere are a few key points to keep in mind during migration:\n\n- Replace `transfer()` and `send()` with `.call{value}(\"\")` and use reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode).\n- PolkaVM factory contracts using PVM bytecode need pre-uploaded dependencies.\n- Don't hardcode gas values.\n- Test thoroughly on [TestNet](/smart-contracts/connect/#__tabbed_1_1){target=\\_blank} before mainnet deployment.\n\nYour existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns."} {"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 0, "depth": 2, "title": "Quick Starts", "anchor": "quick-starts", "start_char": 173, "end_char": 1843, "estimated_token_count": 456, "token_estimator": "heuristic-v1", "text": "## Quick Starts\n\nKick off development fast with curated links for connecting, funding, exploring, and deploying your first contract.\n\n| Quick Start | Tools | Description |\n| :-------------------------------------------------------------------------------------------------: | :-------------------: | :-------------------------------------------------------------: |\n| [Connect to Polkadot](/smart-contracts/connect/){target=\\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer |\n| [Get Test Tokens](/smart-contracts/faucets/){target=\\_blank} | - | Request test funds to deploy and interact with contracts |\n| [Explore Transactions](/smart-contracts/explorers/){target=\\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state |\n| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\\_blank} | Remix | One‑click browser deployment to Polkadot Hub |\n| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\\_blank} | Foundry | Scripted deployments and testing from the CLI |\n| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank} | Hardhat | Project scaffolding, testing, and deployments |"} {"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 1, "depth": 2, "title": "Build and Test Locally", "anchor": "build-and-test-locally", "start_char": 1843, "end_char": 4050, "estimated_token_count": 596, "token_estimator": "heuristic-v1", "text": "## Build and Test Locally\n\nSet up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying.\n\n| Build and Test Locally | Tools | Description |\n| :--------------------------------------------------------------------------------------------------------: | :---------------: | :--------------------------------------------------: |\n| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\\_blank} | Polkadot SDK node | Spin up a local node for iterative development |\n| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts |\n| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\\_blank} | Remix | Publish verified source on explorers |\n| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\\_blank} | Foundry | Install toolchain and configure networks |\n| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\\_blank} | Foundry | Write and run Solidity tests locally |\n| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\\_blank} | Foundry | Verify deployed bytecode and metadata |\n| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank} | Hardhat | Initialize a project and configure networks |\n| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank} | Hardhat | Unit test contracts and run scripts |\n| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\\_blank} | Hardhat | Verify deployments on explorers |"} {"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 2, "depth": 2, "title": "Ethereum Developer Resources", "anchor": "ethereum-developer-resources", "start_char": 4050, "end_char": 5794, "estimated_token_count": 488, "token_estimator": "heuristic-v1", "text": "## Ethereum Developer Resources\n\nBridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment.\n\n| Ethereum Developer Guides | Description |\n| :-------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------: |\n| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts |\n| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\\_blank} | Transaction types, fees, and multi‑dimensional metering |\n| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\\_blank} | Gas vs. weight, proof size, and storage deposits |\n| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\\_blank} | Deployment patterns and best practices on Polkadot Hub |\n| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\\_blank} | Supported Ethereum JSON‑RPC methods and examples |\n| [Migration](/smart-contracts/for-eth-devs/migration/){target=\\_blank} | Port existing apps and tooling to Polkadot Hub |\n| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\\_blank} | Overview of EVM and native execution on the Hub |"} diff --git a/llms.txt b/llms.txt index 3ba08e18f..370da25f6 100644 --- a/llms.txt +++ b/llms.txt @@ -10,6 +10,7 @@ This directory lists URLs for raw Markdown pages that complement the rendered pa - Categories: 12 ## Docs +This section lists documentation pages by category. Each entry links to a raw markdown version of the page and includes a short description. A page may appear in multiple categories. Docs: Basics - [Register a Local Asset](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md): Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. @@ -95,6 +96,7 @@ Docs: Smart Contracts - [Block Explorers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-explorers.md): Access PolkaVM explorers like Subscan, BlockScout, and Routescan to track transactions, analyze contracts, and view on-chain data from smart contracts. - [Faucet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-faucet.md): Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. - [Contract Deployment](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-contract-deployment.md): Compare deployment flows for REVM and PVM-based smart contracts on the Polkadot Hub. Includes single-step REVM flows and PVM’s two-step deployment model. +- [Migration FAQs and Considerations](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md): Learn how to migrate your existing Ethereum contracts to the Polkadot Hub using REVM and PolkaVM by following these considerations. - [Get Started with Smart Contracts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md): Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. - [Wallets for Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md): Comprehensive guide to connecting and managing wallets for Polkadot Hub, covering step-by-step instructions for interacting with the ecosystem. - [Deploy Contracts to Polkadot Hub with Ethers.js](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-ethers-js.md): Learn how to interact with Polkadot Hub using Ethers.js, from compiling and deploying Solidity contracts to interacting with deployed smart contracts. @@ -118,9 +120,9 @@ Docs: Parachains - [Write Tests](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet-write-tests.md): Write and execute tests for blockchain networks with Zombienet's DSL. Learn to evaluate metrics, logs, events, and more for robust validation. - [Add an Existing Pallet to the Runtime](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-existing-pallets.md): Learn how to include and configure pallets in a Polkadot SDK-based runtime, from adding dependencies to implementing necessary traits. - [Add Multiple Pallet Instances](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-pallet-instances.md): Learn how to implement multiple instances of the same pallet in your Polkadot SDK-based runtime, from adding dependencies to configuring unique instances. -- [Add Smart Contract Functionality](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md): Add smart contract capabilities to your Polkadot SDK-based blockchain. Explore EVM and Wasm integration for enhanced chain functionality. +- [Add Smart Contract Functionality](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md): Add smart contract capabilities to your Polkadot SDK-based blockchain. Explore PVM, EVM, and Wasm integration for enhanced chain functionality. - [Add Pallets to the Runtime](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-add-pallet-to-runtime.md): Add pallets to your runtime for custom functionality. Learn to configure and integrate pallets in Polkadot SDK-based blockchains. -- [Benchmarking FRAME Pallets](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md): Learn how to use FRAME's benchmarking framework to measure extrinsic execution costs and provide accurate weights for on-chain computations. +- [Benchmark Your Pallet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md): Learn how to benchmark your custom pallet extrinsics to generate accurate weight calculations for production use. - [Create a Custom Pallet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md): Learn how to create custom pallets using FRAME, allowing for flexible, modular, and scalable blockchain development. Follow the step-by-step guide. - [Mock Your Runtime](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md): Learn how to create a mock runtime environment for testing your custom pallets in isolation, enabling comprehensive unit testing before runtime integration. - [Pallet Testing](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md): Learn how to efficiently test pallets in the Polkadot SDK, ensuring the reliability and security of your pallets operations. @@ -353,7 +355,6 @@ Docs: Uncategorized - [ParaSpell XCM SDK](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md): A powerful open-source library that simplifies XCM integration, enabling developers to easily build interoperable dApps on Polkadot. - [reference-tools-zombienet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md): No description available. - [reference](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md): No description available. -- [smart-contracts-cookbook-dapps-zero-to-hero](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md): No description available. - [smart-contracts-cookbook-smart-contracts-deploy-basic](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic.md): No description available. - [smart-contracts-dev-environments-foundry-compile-and-test](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-compile-and-test.md): No description available. - [smart-contracts-dev-environments-foundry-deploy-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-deploy-a-contract.md): No description available. @@ -370,7 +371,6 @@ Docs: Uncategorized - [smart-contracts-dev-environments-remix-troubleshooting](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md): No description available. - [smart-contracts-dev-environments-remix-verify-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md): No description available. - [Gas Model on the Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-gas-model.md): Learn how gas estimation, pricing, and weight mapping work in the Polkadot Hub. -- [smart-contracts-for-eth-devs-migration](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md): No description available. - [smart-contracts-integrations-indexers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-indexers.md): No description available. - [smart-contracts-integrations-oracles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-oracles.md): No description available. - [Advanced Functionalities via Precompiles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles.md): Explores how Polkadot integrates precompiles to run essential functions natively, improving the speed and efficiency of smart contracts on the Hub. diff --git a/parachains/customize-runtime/pallet-development/benchmark-pallet.md b/parachains/customize-runtime/pallet-development/benchmark-pallet.md index dd02ee0b4..9eae75314 100644 --- a/parachains/customize-runtime/pallet-development/benchmark-pallet.md +++ b/parachains/customize-runtime/pallet-development/benchmark-pallet.md @@ -1,215 +1,681 @@ --- -title: Benchmarking FRAME Pallets -description: Learn how to use FRAME's benchmarking framework to measure extrinsic execution costs and provide accurate weights for on-chain computations. +title: Benchmark Your Pallet +description: Learn how to benchmark your custom pallet extrinsics to generate accurate weight calculations for production use. categories: Parachains --- -# Benchmarking - ## Introduction -Benchmarking is a critical component of developing efficient and secure blockchain runtimes. In the Polkadot ecosystem, accurately benchmarking your custom pallets ensures that each extrinsic has a precise [weight](/reference/glossary/#weight){target=\_blank}, representing its computational and storage demands. This process is vital for maintaining the blockchain's performance and preventing potential vulnerabilities, such as Denial of Service (DoS) attacks. +Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks. + +This guide continues the pallet development series, building on the [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet), [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime), and [Test Your Pallet](/parachains/customize-runtime/pallet-development/pallet-testing) tutorials. You'll learn how to benchmark the counter pallet extrinsics and integrate the generated weights into your runtime. + +## Prerequisites + +Before you begin, ensure you have: + +- Completed the previous pallet development tutorials +- Basic understanding of computational complexity +- Familiarity with Rust's testing framework + +## Why Benchmark? + +In blockchain systems, every operation consumes resources. Weight is the mechanism Polkadot SDK uses to measure and limit resource consumption. Without accurate weights: + +- **Security Risk**: Malicious actors could submit transactions that consume excessive resources, blocking legitimate transactions or halting the chain +- **Inefficiency**: Over-estimated weights waste block space and reduce throughput +- **User Experience**: Inaccurate weights lead to incorrect fee calculations + +Benchmarking provides empirical measurements of your extrinsics under various conditions, ensuring weights reflect real-world resource consumption. + +## Understanding Weights + +The [weight system](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank} serves multiple purposes: + +- **DoS Protection**: Limits the computational work per block, preventing attackers from overwhelming the network +- **Fee Calculation**: Determines transaction fees based on actual resource usage +- **Block Production**: Helps block authors maximize throughput while staying within block limits + +Weights are expressed as [`Weight::from_parts(ref_time, proof_size)`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.from_parts){target=\_blank} where: + +- [`ref_time`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.ref_time){target=\_blank}: Computational time measured in picoseconds +- [`proof_size`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.proof_size){target=\_blank}: Storage proof size in bytes + +## Step 1: Create the Benchmarking Module + +Create a new file `benchmarking.rs` in your pallet's `src` directory. This module will contain all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} for your pallet: + +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use frame::deps::frame_benchmarking::v2::*; +use frame::benchmarking::prelude::RawOrigin; + +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn set_counter_value() { + let new_value: u32 = 100; + + #[extrinsic_call] + _(RawOrigin::Root, new_value); + + assert_eq!(CounterValue::::get(), new_value); + } + + #[benchmark] + fn increment() { + let caller: T::AccountId = whitelisted_caller(); + let amount: u32 = 50; + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), amount); + + assert_eq!(CounterValue::::get(), amount); + assert_eq!(UserInteractions::::get(caller), 1); + } + + #[benchmark] + fn decrement() { + // First set the counter to a non-zero value + CounterValue::::put(100); + + let caller: T::AccountId = whitelisted_caller(); + let amount: u32 = 30; + + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone()), amount); + + assert_eq!(CounterValue::::get(), 70); + assert_eq!(UserInteractions::::get(caller), 1); + } + + impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test); +} +``` + +**Key components:** + +- **`#![cfg(feature = "runtime-benchmarks")]`**: Ensures benchmarking code only compiles when the feature is enabled +- **[`#[benchmarks]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmarks.html){target=\_blank}**: Marks the module containing benchmark definitions +- **[`#[benchmark]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmark.html){target=\_blank}**: Defines individual benchmark functions +- **[`#[extrinsic_call]`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.extrinsic_call.html){target=\_blank}**: Marks the actual extrinsic invocation to measure +- **[`whitelisted_caller()`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/fn.whitelisted_caller.html){target=\_blank}**: Generates a funded account for benchmarking +- **[`impl_benchmark_test_suite!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.impl_benchmark_test_suite.html){target=\_blank}**: Generates test functions to verify benchmarks work correctly + +## Step 2: Define the Weight Trait + +The [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. This enables you to use placeholder weights during development and testing, then switch to auto-generated benchmarked weights in production without modifying the pallet code itself. + +Add a `weights` module to your pallet that defines the `WeightInfo` trait: + +```rust title="pallets/pallet-custom/src/lib.rs" +#[frame::pallet] +pub mod pallet { + use frame::prelude::*; + pub use weights::WeightInfo; + + pub mod weights { + use frame::prelude::*; + + pub trait WeightInfo { + fn set_counter_value() -> Weight; + fn increment() -> Weight; + fn decrement() -> Weight; + } + + impl WeightInfo for () { + fn set_counter_value() -> Weight { + Weight::from_parts(10_000, 0) + } + fn increment() -> Weight { + Weight::from_parts(15_000, 0) + } + fn decrement() -> Weight { + Weight::from_parts(15_000, 0) + } + } + } + + // ... rest of pallet +} +``` + +The `()` implementation provides placeholder weights for development. Later, this will be replaced with auto-generated weights from benchmarking. + +## Step 3: Add WeightInfo to Config + +By making `WeightInfo` an associated type in the `Config` trait, you allow each runtime that uses your pallet to specify which weight implementation to use. Different deployment environments (testnets, production chains, or different hardware configurations) may have different performance characteristics and can use different weight calculations. -The Polkadot SDK leverages the [FRAME](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank} benchmarking framework, offering tools to measure and assign weights to extrinsics. These weights help determine the maximum number of transactions or system-level calls processed within a block. This guide covers how to use FRAME's [benchmarking framework](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank}, from setting up your environment to writing and running benchmarks for your custom pallets. You'll understand how to generate accurate weights by the end, ensuring your runtime remains performant and secure. +Update your pallet's `Config` trait to include `WeightInfo`: -## The Case for Benchmarking +```rust title="pallets/pallet-custom/src/lib.rs" +#[pallet::config] +pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; -Benchmarking helps validate that the required execution time for different functions is within reasonable boundaries to ensure your blockchain runtime can handle transactions efficiently and securely. By accurately measuring the weight of each extrinsic, you can prevent service interruptions caused by computationally intensive calls that exceed block time limits. Without benchmarking, runtime performance could be vulnerable to DoS attacks, where malicious users exploit functions with unoptimized weights. + #[pallet::constant] + type CounterMaxValue: Get; -Benchmarking also ensures predictable transaction fees. Weights derived from benchmark tests accurately reflect the resource usage of function calls, allowing fair fee calculation. This approach discourages abuse while maintaining network reliability. + type WeightInfo: weights::WeightInfo; +} +``` + +## Step 4: Update Extrinsic Weight Annotations + +By calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. This allows you to easily switch between placeholder weights for testing and benchmarked weights for production without changing any pallet code. + +Replace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait: + +```rust title="pallets/pallet-custom/src/lib.rs" +#[pallet::call] +impl Pallet { + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::set_counter_value())] + pub fn set_counter_value(origin: OriginFor, new_value: u32) -> DispatchResult { + // ... implementation + } + + #[pallet::call_index(1)] + #[pallet::weight(T::WeightInfo::increment())] + pub fn increment(origin: OriginFor, amount: u32) -> DispatchResult { + // ... implementation + } + + #[pallet::call_index(2)] + #[pallet::weight(T::WeightInfo::decrement())] + pub fn decrement(origin: OriginFor, amount: u32) -> DispatchResult { + // ... implementation + } +} +``` + +## Step 5: Include the Benchmarking Module + +The `#[cfg(feature = "runtime-benchmarks")]` attribute ensures that benchmarking code is only compiled when explicitly needed. This keeps your production runtime lean by excluding benchmarking infrastructure from normal builds, as it's only needed when generating weights. + +At the top of your `lib.rs`, add the module declaration: + +```rust title="pallets/pallet-custom/src/lib.rs" +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +use alloc::vec::Vec; + +pub use pallet::*; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +// ... rest of the pallet +``` + +## Step 6: Configure Pallet Dependencies + +The feature flag system in Cargo allows you to conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds. + +Update your pallet's `Cargo.toml` to enable the benchmarking feature: + +```toml title="pallets/pallet-custom/Cargo.toml" +[dependencies] +codec = { features = ["derive"], workspace = true } +scale-info = { features = ["derive"], workspace = true } +frame = { features = ["experimental", "runtime"], workspace = true } -### Benchmarking and Weight +[features] +default = ["std"] +runtime-benchmarks = [ + "frame/runtime-benchmarks", +] +std = [ + "codec/std", + "scale-info/std", + "frame/std", +] +``` + +## Step 7: Update Mock Runtime + +In your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo` since unit tests focus on verifying functional correctness rather than performance characteristics. This keeps tests fast and focused on validating logic. + +Add the `WeightInfo` type to your test configuration in `mock.rs`: + +```rust title="pallets/pallet-custom/src/mock.rs" +impl pallet_custom::Config for Test { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = (); +} +``` + +## Step 8: Configure Runtime Benchmarking + +To execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. This involves three configuration steps: + +### Update Runtime Cargo.toml -In Polkadot SDK-based chains, weight quantifies the computational effort needed to process transactions. This weight includes factors such as: +When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. -- Computational complexity. -- Storage complexity (proof size). -- Database reads and writes. -- Hardware specifications. +Add your pallet to the runtime's `runtime-benchmarks` feature in `runtime/Cargo.toml`: -Benchmarking uses real-world testing to simulate worst-case scenarios for extrinsics. The framework generates a linear model for weight calculation by running multiple iterations with varied parameters. These worst-case weights ensure blocks remain within execution limits, enabling the runtime to maintain throughput under varying loads. Excess fees can be refunded if a call uses fewer resources than expected, offering users a fair cost model. - -Because weight is a generic unit of measurement based on computation time for a specific physical machine, the weight of any function can change based on the specifications of hardware used for benchmarking. By modeling the expected weight of each runtime function, the blockchain can calculate the number of transactions or system-level calls it can execute within a certain period. +```toml title="runtime/Cargo.toml" +runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "hex-literal", + "pallet-parachain-template/runtime-benchmarks", + "polkadot-sdk/runtime-benchmarks", + "pallet-custom/runtime-benchmarks", +] +``` + +### Update Runtime Configuration + +Start with the placeholder implementation during development. After successfully running benchmarks and generating the weights file, you'll update this to use the benchmarked weights. -Within FRAME, each function call that is dispatched must have a `#[pallet::weight]` annotation that can return the expected weight for the worst-case scenario execution of that function given its inputs: +In `runtime/src/configs/mod.rs`, add the `WeightInfo` type: -```rust hl_lines="2" ---8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/dispatchable-pallet-weight.rs' +```rust title="runtime/src/configs/mod.rs" +impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = (); +} ``` -The `WeightInfo` file is automatically generated during benchmarking. Based on these tests, this file provides accurate weights for each extrinsic. +### Register Benchmarks -## Benchmarking Process +The `define_benchmarks!` macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks. -Benchmarking a pallet involves the following steps: +Add your pallet to the benchmark list in `runtime/src/benchmarks.rs`: + +```rust title="runtime/src/benchmarks.rs" +polkadot_sdk::frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + // ... other pallets + [pallet_custom, CustomPallet] +); +``` -1. Creating a `benchmarking.rs` file within your pallet's structure. -2. Writing a benchmarking test for each extrinsic. -3. Executing the benchmarking tool to calculate weights based on performance metrics. +## Step 9: Run Benchmarks -The benchmarking tool runs multiple iterations to model worst-case execution times and determine the appropriate weight. By default, the benchmarking pipeline is deactivated. To activate it, compile your runtime with the `runtime-benchmarks` feature flag. +### Test Benchmark Compilation -### Prepare Your Environment +The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the full runtime. -Install the [`frame-omni-bencher`](https://crates.io/crates/frame-omni-bencher){target=\_blank} command-line tool: +First, verify your benchmarks compile and run as tests: ```bash -cargo install frame-omni-bencher +cargo test -p pallet-custom --features runtime-benchmarks ``` -Before writing benchmark tests, you need to ensure the `frame-benchmarking` crate is included in your pallet's `Cargo.toml` similar to the following: +You should see your benchmark tests passing: -```toml title="Cargo.toml" ---8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/cargo.toml::1' ``` +test benchmarking::benchmarks::bench_set_counter_value ... ok +test benchmarking::benchmarks::bench_increment ... ok +test benchmarking::benchmarks::bench_decrement ... ok +``` + +### Build the Runtime with Benchmarks + +This build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. This is a special build used only for benchmarking - you'll create a different build later for actually running your chain. + +Compile the runtime with benchmarking enabled to generate the WASM binary: -You must also ensure that you add the `runtime-benchmarks` feature flag as follows under the `[features]` section of your pallet's `Cargo.toml`: +```bash +cargo build --release --features runtime-benchmarks +``` -```toml title="Cargo.toml" ---8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/cargo.toml:2:7' +This produces the runtime WASM file needed for benchmarking, typically located at: +``` +target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm ``` -Lastly, ensure that `frame-benchmarking` is included in `std = []`: +### Install the Benchmarking Tool + +[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} is the official Polkadot SDK tool specifically designed for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system. + +Install the `frame-omni-bencher` CLI tool: -```toml title="Cargo.toml" ---8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/cargo.toml:8:12' +```bash +cargo install frame-omni-bencher --locked ``` -Once complete, you have the required dependencies for writing benchmark tests for your pallet. +### Download the Weight Template -### Write Benchmark Tests +The weight template is a Handlebars file that transforms raw benchmark data into a properly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow Polkadot SDK conventions and include all necessary metadata like benchmark execution parameters, storage operation counts, and hardware information. -Create a `benchmarking.rs` file in your pallet's `src/`. Your directory structure should look similar to the following: +Download the official weight template file: +```bash +curl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \ +--output ./pallets/pallet-custom/frame-weight-template.hbs ``` -my-pallet/ -├── src/ -│ ├── lib.rs # Main pallet implementation -│ └── benchmarking.rs # Benchmarking -└── Cargo.toml + +### Hardware Requirements for Benchmarking + +!!! warning "Critical: Benchmark on Production-Like Hardware" + Benchmarks must be executed on hardware similar to what will run your chain in production. Weight measurements are hardware-dependent, and benchmarking on different hardware can lead to dangerous under-estimation or wasteful over-estimation of weights. + +Weights represent the actual computational time and resources consumed by extrinsics. These measurements vary significantly across different hardware configurations: + +- **CPU Performance**: Different processors execute instructions at different speeds. A faster development laptop will produce lower weight values than production server hardware +- **Storage Speed**: Database read/write performance varies between NVMe SSDs, SATA SSDs, and HDDs, affecting storage-related weights +- **Memory Bandwidth**: RAM speed impacts how quickly data can be accessed during execution +- **CPU Cache**: Cache size and architecture differences affect repeated operations + +Benchmarking on faster hardware than production leads to under-estimated weights - attackers could submit extrinsics that consume more resources than the weights suggest, potentially causing blocks to take longer than expected to produce or even halting the chain. Conversely, benchmarking on slower hardware creates over-estimated weights, resulting in unnecessarily high transaction fees and wasted block capacity. + +**Best practices:** + +1. **Match production specifications**: If your chain will run on specific validator hardware, benchmark on identical or very similar machines +2. **Use reference hardware**: The Polkadot ecosystem often uses standardized reference hardware specifications for consistency. Consider following these standards if your chain will connect to Polkadot or Kusama +3. **Dedicated benchmarking environment**: Run benchmarks on a machine without other heavy processes to ensure consistent measurements +4. **Document your hardware**: The generated weight files include hardware information in comments. Review this to ensure it matches your production environment +5. **Re-benchmark when hardware changes**: If your validator hardware specifications change, re-run benchmarks and update weights + +For development and testing purposes, you can run benchmarks on any available hardware to verify that your benchmark functions work correctly. However, before deploying to production, always re-run benchmarks on production-equivalent hardware. + +### Execute Benchmarks + +Benchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking the WASM ensures your weight measurements reflect real-world conditions. + +Run benchmarks for your pallet to generate weight files: + +```bash +frame-omni-bencher v1 benchmark pallet \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ + --pallet pallet_custom \ + --extrinsic "" \ + --template ./pallets/pallet-custom/frame-weight-template.hbs \ + --output ./pallets/pallet-custom/src/weights.rs ``` -With the directory structure set, you can use the [`polkadot-sdk-parachain-template`](https://github.com/paritytech/polkadot-sdk-parachain-template/tree/master/pallets){target=\_blank} to get started as follows: +**Command breakdown:** + +- `v1`: Specifies the benchmarking framework version (v2 API) +- `benchmark pallet`: Subcommand indicating you want to benchmark pallet extrinsics +- `--runtime`: Path to the compiled WASM runtime file that includes your pallet and benchmarks +- `--pallet pallet_custom`: Name of the pallet to benchmark (must match the name used in `define_benchmarks!`) +- `--extrinsic ""`: Empty string benchmarks all extrinsics in the pallet; you can specify a single extrinsic name to benchmark only that one +- `--template`: Path to the Handlebars template that formats the output +- `--output`: Destination file path for the generated weights module + +### Advanced Options -```rust title="benchmarking.rs (starter template)" ---8<-- 'https://raw.githubusercontent.com/paritytech/polkadot-sdk-parachain-template/refs/tags/v0.0.2/pallets/template/src/benchmarking.rs' +You can customize benchmark execution with additional parameters for more detailed measurements: + +```bash +frame-omni-bencher v1 benchmark pallet \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ + --pallet pallet_custom \ + --extrinsic "" \ + --steps 50 \ + --repeat 20 \ + --template ./pallets/pallet-custom/frame-weight-template.hbs \ + --output ./pallets/pallet-custom/src/weights.rs ``` -In your benchmarking tests, employ these best practices: +**Additional parameters:** -- **Write custom testing functions**: The function `do_something` in the preceding example is a placeholder. Similar to writing unit tests, you must write custom functions to benchmark test your extrinsics. Access the mock runtime and use functions such as `whitelisted_caller()` to sign transactions and facilitate testing. -- **Use the `#[extrinsic_call]` macro**: This macro is used when calling the extrinsic itself and is a required part of a benchmarking function. See the [`extrinsic_call`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html#extrinsic_call-and-block){target=\_blank} docs for more details. -- **Validate extrinsic behavior**: The `assert_eq` expression ensures that the extrinsic is working properly within the benchmark context. +- `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time +- `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise and providing more reliable weight estimates +- `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution +- `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions -Add the `benchmarking` module to your pallet. In the pallet `lib.rs` file add the following: +## Step 10: Use Generated Weights + +After running benchmarks, a `weights.rs` file is generated containing measured weights. The generated weights are based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. Estimates or placeholder values cannot capture these nuances and will either waste block space (over-estimation) or create security risks (under-estimation). + +The file includes: + +- Detailed documentation about the benchmark execution environment (date, hardware, parameters) +- The `WeightInfo` trait definition matching your benchmark functions +- `SubstrateWeight` implementation with measured weights from your benchmarks +- Database read/write costs calculated based on observed storage operations +- Component complexity annotations for variable inputs (if you use linear components) +- A fallback `()` implementation for testing environments + +### Integrate the Generated Weights + +Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during normal operation to calculate transaction fees and enforce block limits. + +Add the weights module to your pallet's `lib.rs`: + +```rust title="pallets/pallet-custom/src/lib.rs" +#![cfg_attr(not(feature = "std"), no_std)] + +extern crate alloc; +use alloc::vec::Vec; + +pub use pallet::*; -```rust #[cfg(feature = "runtime-benchmarks")] mod benchmarking; + +pub mod weights; + +#[frame::pallet] +pub mod pallet { + use super::*; + use frame::prelude::*; + use crate::weights::WeightInfo; + // ... rest of pallet +} ``` -### Add Benchmarks to Runtime +### Update Runtime Configuration -Before running the benchmarking tool, you must integrate benchmarks with your runtime as follows: +This change activates your benchmarked weights in the production runtime. Now when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits. -1. Navigate to your `runtime/src` directory and check if a `benchmarks.rs` file exists. If not, create one. This file will contain the macro that registers all pallets for benchmarking along with their respective configurations: +Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation: - ```rust title="benchmarks.rs" - --8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/frame-benchmark-macro.rs' - ``` +```rust title="runtime/src/configs/mod.rs" +impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = pallet_custom::weights::SubstrateWeight; +} +``` - For example, to add a new pallet named `pallet_parachain_template` for benchmarking, include it in the macro as shown: - ```rust title="benchmarks.rs" hl_lines="3" - --8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/frame-benchmark-macro.rs::3' - ); - ``` +### Example Generated Weight File + +The generated `weights.rs` file will look similar to this: + +```rust title="pallets/pallet-custom/src/weights.rs" +//! Autogenerated weights for `pallet_custom` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20` + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use core::marker::PhantomData; + +pub trait WeightInfo { + fn set_counter_value() -> Weight; + fn increment() -> Weight; + fn decrement() -> Weight; +} + +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + fn set_counter_value() -> Weight { + Weight::from_parts(8_234_000, 0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + + fn increment() -> Weight { + Weight::from_parts(12_456_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + + fn decrement() -> Weight { + Weight::from_parts(11_987_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} +``` - !!!warning "Updating `define_benchmarks!` macro is required" - Any pallet that needs to be benchmarked must be included in the [`define_benchmarks!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.define_benchmarks.html){target=\_blank} macro. The CLI will only be able to access and benchmark pallets that are registered here. +**Note**: The actual numbers will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} accounts for database read and write operations. -2. Check your runtime's `lib.rs` file to ensure the `benchmarks` module is imported. The import should look like this: +## Benchmarking Best Practices - ```rust title="lib.rs" - #[cfg(feature = "runtime-benchmarks")] - mod benchmarks; - ``` +### 1. Test Worst-Case Scenarios - The `runtime-benchmarks` feature gate ensures benchmark tests are isolated from production runtime code. +Benchmarks should always measure maximum possible resource consumption. If you benchmark average or best-case scenarios, malicious users could craft transactions that hit worst-case paths in your code, consuming more resources than the weights indicate and potentially slowing down or halting block production. -3. Enable runtime benchmarking for your pallet in `runtime/Cargo.toml`: +```rust +#[benchmark] +fn complex_operation() { + // Set up worst-case storage state + for i in 0..100 { + SomeStorage::::insert(i, vec![0u8; 1000]); + } + + let caller = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller)); +} +``` - ```toml - --8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/runtime-cargo.toml' - ``` +### 2. Use Linear Components for Variable Complexity -### Run Benchmarks +Many extrinsics have variable costs depending on input parameters. [Linear components](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/trait.BenchmarkingSetup.html){target=\_blank} tell the benchmarking framework to test your extrinsic with different values of `n`, measure the execution time for each, and calculate a formula like `Weight = base_weight + (n * per_item_weight)`. This produces dynamic weights that accurately reflect the actual work being done. -You can now compile your runtime with the `runtime-benchmarks` feature flag. This feature flag is crucial as the benchmarking tool will look for this feature being enabled to know when it should run benchmark tests. Follow these steps to compile the runtime with benchmarking enabled: +When extrinsic complexity depends on input size, use linear components: -1. Run `build` with the feature flag included: +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#[benchmark] +fn process_items(n: Linear<0, 100>) { + let caller = whitelisted_caller(); + let items: Vec = (0..n).collect(); - ```bash - cargo build --features runtime-benchmarks --release - ``` + #[extrinsic_call] + _(RawOrigin::Signed(caller), items); +} +``` -2. Create a `weights.rs` file in your pallet's `src/` directory. This file will store the auto-generated weight calculations: +### 3. Verify Results - ```bash - touch weights.rs - ``` +Assertions ensure that your benchmark is actually testing the code path you think it's testing. If your extrinsic fails silently or takes an early return, the benchmark would measure the wrong scenario and produce inaccurate weights. -3. Before running the benchmarking tool, you'll need a template file that defines how weight information should be formatted. Download the official template from the Polkadot SDK repository and save it in your project folders for future use: +Always assert the expected state after extrinsic execution: - ```bash - curl https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \ - --output ./pallets/benchmarking/frame-weight-template.hbs - ``` +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#[benchmark] +fn my_extrinsic() { + let caller = whitelisted_caller(); -4. Run the benchmarking tool to measure extrinsic weights: + #[extrinsic_call] + _(RawOrigin::Signed(caller.clone())); - ```bash - frame-omni-bencher v1 benchmark pallet \ - --runtime INSERT_PATH_TO_WASM_RUNTIME \ - --pallet INSERT_NAME_OF_PALLET \ - --extrinsic "" \ - --template ./frame-weight-template.hbs \ - --output weights.rs - ``` + // Verify the extrinsic had the expected effect + assert_eq!(MyStorage::::get(&caller), expected_value); +} +``` + +### 4. Minimize Setup Code + +While the benchmarking framework tries to isolate the extrinsic execution, excessive setup code can add noise to measurements. More importantly, setup code that doesn't reflect real-world pre-conditions can lead to benchmarking unrealistic scenarios. + +Only include necessary setup in benchmarks: + +```rust title="pallets/pallet-custom/src/benchmarking.rs" +#[benchmark] +fn efficient_benchmark() { + // Minimal setup + let caller = whitelisted_caller(); + + #[extrinsic_call] + _(RawOrigin::Signed(caller)); + + // Minimal assertions +} +``` + +## Run Your Chain Locally + +Now that you've added the pallet to your runtime, you can launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide. - !!! tip "Flag definitions" - - **`--runtime`**: The path to your runtime's Wasm. - - **`--pallet`**: The name of the pallet you wish to benchmark. This pallet must be configured in your runtime and defined in `define_benchmarks`. - - **`--extrinsic`**: Which extrinsic to test. Using `""` implies all extrinsics will be benchmarked. - - **`--template`**: Defines how weight information should be formatted. - - **`--output`**: Where the output of the auto-generated weights will reside. +### Build the Production Runtime -The generated `weights.rs` file contains weight annotations for your extrinsics, ready to be added to your pallet. The output should be similar to the following. Some output is omitted for brevity: +The `runtime-benchmarks` feature flag adds special host functions (like `ext_benchmarking_current_time` and `ext_benchmarking_get_read_and_written_keys`) that are only available in the benchmarking execution environment. These functions allow the benchmarking framework to precisely measure execution time and track storage operations. However, regular nodes don't provide these host functions, so a runtime compiled with benchmarking features will fail to start on a production node. ---8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/benchmark-output.html' +Before running your chain, rebuild the runtime **without** the `runtime-benchmarks` feature: -#### Add Benchmark Weights to Pallet +```bash +cargo build --release +``` + +!!! note "Build Types" + Understanding the difference between builds is critical: + + - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher` + - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your actual chain + +This produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. + +### Generate a Chain Specification + +The chain specification defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. By generating a new chain spec with your updated runtime (now containing your benchmarked pallet), you ensure that nodes starting from this spec will use the correct version of your code with proper weight calculations. + +Create a new chain specification file with the updated runtime: + +```bash +chain-spec-builder create -t development \ +--relay-chain paseo \ +--para-id 1000 \ +--runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ +named-preset development +``` + +This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime. -Once the `weights.rs` is generated, you must integrate it with your pallet. +### Start the Parachain Node -1. To begin the integration, import the `weights` module and the `WeightInfo` trait, then add both to your pallet's `Config` trait. Complete the following steps to set up the configuration: +Launch the parachain using the Polkadot Omni Node with the generated chain specification by running the following command: - ```rust title="lib.rs" - --8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/weight-config.rs' - ``` +```bash +polkadot-omni-node --chain ./chain_spec.json --dev +``` -2. Next, you must add this to the `#[pallet::weight]` annotation in all the extrinsics via the `Config` as follows: +The node will start and display initialization information including: - ```rust hl_lines="2" title="lib.rs" - --8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/dispatchable-pallet-weight.rs' - ``` +- The chain specification name +- The node identity and peer ID +- Database location +- Network endpoints (JSON-RPC and Prometheus) -3. Finally, configure the actual weight values in your runtime. In `runtime/src/config/mod.rs`, add the following code: +### Verify Block Production + +Once the node is running, you should see log messages indicating successful block production: + +``` +[Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc) +[Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ... +[Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2) +[Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ... +[Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32) +``` - ```rust title="mod.rs" - --8<-- 'code/parachains/customize-runtime/pallet-development/benchmark-pallet/runtime-pallet-config.rs' - ``` +The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. -## Where to Go Next +## Related Resources -- View the Rust Docs for a more comprehensive, low-level view of the [FRAME V2 Benchmarking Suite](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=_blank}. -- Read the [FRAME Benchmarking and Weights](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_benchmarking_weight/index.html){target=_blank} reference document, a concise guide which details how weights and benchmarking work. +- [FRAME Benchmarking Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/index.html){target=\_blank} +- [Weight Struct Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html){target=\_blank} +- [Benchmarking v2 API](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} +- [frame-omni-bencher Tool](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} diff --git a/parachains/customize-runtime/pallet-development/create-a-pallet.md b/parachains/customize-runtime/pallet-development/create-a-pallet.md index 26d75c2b8..f86b7b83b 100644 --- a/parachains/customize-runtime/pallet-development/create-a-pallet.md +++ b/parachains/customize-runtime/pallet-development/create-a-pallet.md @@ -340,7 +340,7 @@ This command validates all pallet configurations and prepares the build for depl ## Run Your Chain Locally -Launch your parachain locally to test the new pallet functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. +Launch your parachain locally to test the new pallet functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide. ### Generate a Chain Specification From 6b7cbecb07b54aab6ecc95e1aa69796372febaf3 Mon Sep 17 00:00:00 2001 From: DAWN KELLY Date: Tue, 18 Nov 2025 13:37:00 -0500 Subject: [PATCH 02/12] cleanup and grammarly --- .../pallet-development/.nav.yml | 2 +- .../pallet-development/benchmark-pallet.md | 590 +++++++----------- .../pallet-development/pallet-testing.md | 4 +- 3 files changed, 212 insertions(+), 384 deletions(-) diff --git a/parachains/customize-runtime/pallet-development/.nav.yml b/parachains/customize-runtime/pallet-development/.nav.yml index a6c7e9399..43f919978 100644 --- a/parachains/customize-runtime/pallet-development/.nav.yml +++ b/parachains/customize-runtime/pallet-development/.nav.yml @@ -1,6 +1,6 @@ nav: - 'Create a Custom Pallet': create-a-pallet.md - 'Mock Your Runtime': mock-runtime.md - - 'Pallet Unit Testing': pallet-testing.md + - 'Unit Test Pallets': pallet-testing.md - 'Add a Custom Pallet to Your Runtime': add-pallet-to-runtime.md - 'Benchmark a Custom Pallet': benchmark-pallet.md \ No newline at end of file diff --git a/parachains/customize-runtime/pallet-development/benchmark-pallet.md b/parachains/customize-runtime/pallet-development/benchmark-pallet.md index 9eae75314..092b8d6e1 100644 --- a/parachains/customize-runtime/pallet-development/benchmark-pallet.md +++ b/parachains/customize-runtime/pallet-development/benchmark-pallet.md @@ -8,42 +8,23 @@ categories: Parachains Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks. -This guide continues the pallet development series, building on the [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet), [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime), and [Test Your Pallet](/parachains/customize-runtime/pallet-development/pallet-testing) tutorials. You'll learn how to benchmark the counter pallet extrinsics and integrate the generated weights into your runtime. +This guide continues building on what you've learned through the pallet development series. You'll learn how to benchmark the custom counter pallet extrinsics and integrate the generated weights into your runtime. ## Prerequisites Before you begin, ensure you have: -- Completed the previous pallet development tutorials -- Basic understanding of computational complexity -- Familiarity with Rust's testing framework +- Completed the previous pallet development tutorials: + - [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\_blank} + - [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\_blank} + - [Unit Test Pallets](/parachains/customize-runtime/pallet-development/pallet-testing/){target=\_blank} +- Basic understanding of [computational complexity](https://en.wikipedia.org/wiki/Computational_complexity){target=\_blank}. +- Familiarity with [Rust's testing framework](https://doc.rust-lang.org/book/ch11-00-testing.html){target=\_blank}. +- Familiarity setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}. Refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide for instructions if needed. -## Why Benchmark? +## Create the Benchmarking Module -In blockchain systems, every operation consumes resources. Weight is the mechanism Polkadot SDK uses to measure and limit resource consumption. Without accurate weights: - -- **Security Risk**: Malicious actors could submit transactions that consume excessive resources, blocking legitimate transactions or halting the chain -- **Inefficiency**: Over-estimated weights waste block space and reduce throughput -- **User Experience**: Inaccurate weights lead to incorrect fee calculations - -Benchmarking provides empirical measurements of your extrinsics under various conditions, ensuring weights reflect real-world resource consumption. - -## Understanding Weights - -The [weight system](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank} serves multiple purposes: - -- **DoS Protection**: Limits the computational work per block, preventing attackers from overwhelming the network -- **Fee Calculation**: Determines transaction fees based on actual resource usage -- **Block Production**: Helps block authors maximize throughput while staying within block limits - -Weights are expressed as [`Weight::from_parts(ref_time, proof_size)`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.from_parts){target=\_blank} where: - -- [`ref_time`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.ref_time){target=\_blank}: Computational time measured in picoseconds -- [`proof_size`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.proof_size){target=\_blank}: Storage proof size in bytes - -## Step 1: Create the Benchmarking Module - -Create a new file `benchmarking.rs` in your pallet's `src` directory. This module will contain all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} for your pallet: +Create a new file `benchmarking.rs` in your pallet's `src` directory and add the following code: ```rust title="pallets/pallet-custom/src/benchmarking.rs" #![cfg(feature = "runtime-benchmarks")] @@ -80,7 +61,7 @@ mod benchmarks { #[benchmark] fn decrement() { - // First set the counter to a non-zero value + // First, set the counter to a non-zero value CounterValue::::put(100); let caller: T::AccountId = whitelisted_caller(); @@ -97,20 +78,11 @@ mod benchmarks { } ``` -**Key components:** +This module contains all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} for your pallet. -- **`#![cfg(feature = "runtime-benchmarks")]`**: Ensures benchmarking code only compiles when the feature is enabled -- **[`#[benchmarks]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmarks.html){target=\_blank}**: Marks the module containing benchmark definitions -- **[`#[benchmark]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmark.html){target=\_blank}**: Defines individual benchmark functions -- **[`#[extrinsic_call]`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.extrinsic_call.html){target=\_blank}**: Marks the actual extrinsic invocation to measure -- **[`whitelisted_caller()`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/fn.whitelisted_caller.html){target=\_blank}**: Generates a funded account for benchmarking -- **[`impl_benchmark_test_suite!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.impl_benchmark_test_suite.html){target=\_blank}**: Generates test functions to verify benchmarks work correctly +## Define the Weight Trait -## Step 2: Define the Weight Trait - -The [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. This enables you to use placeholder weights during development and testing, then switch to auto-generated benchmarked weights in production without modifying the pallet code itself. - -Add a `weights` module to your pallet that defines the `WeightInfo` trait: +Add a `weights` module to your pallet that defines the `WeightInfo` trait using the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #[frame::pallet] @@ -144,13 +116,11 @@ pub mod pallet { } ``` -The `()` implementation provides placeholder weights for development. Later, this will be replaced with auto-generated weights from benchmarking. +The `()` implementation provides placeholder weights for development. -## Step 3: Add WeightInfo to Config +## Add WeightInfo to Config -By making `WeightInfo` an associated type in the `Config` trait, you allow each runtime that uses your pallet to specify which weight implementation to use. Different deployment environments (testnets, production chains, or different hardware configurations) may have different performance characteristics and can use different weight calculations. - -Update your pallet's `Config` trait to include `WeightInfo`: +Update your pallet's `Config` trait to include `WeightInfo` by adding the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #[pallet::config] @@ -164,11 +134,11 @@ pub trait Config: frame_system::Config { } ``` -## Step 4: Update Extrinsic Weight Annotations +The [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. By making `WeightInfo` an associated type in the `Config` trait, you will enable each runtime that uses your pallet to specify which weight implementation to use. -By calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. This allows you to easily switch between placeholder weights for testing and benchmarked weights for production without changing any pallet code. +## Update Extrinsic Weight Annotations -Replace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait: +Replace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait by adding the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #[pallet::call] @@ -193,11 +163,11 @@ impl Pallet { } ``` -## Step 5: Include the Benchmarking Module +By calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. You can switch between placeholder weights for testing and benchmarked weights for production easily, without changing any pallet code. -The `#[cfg(feature = "runtime-benchmarks")]` attribute ensures that benchmarking code is only compiled when explicitly needed. This keeps your production runtime lean by excluding benchmarking infrastructure from normal builds, as it's only needed when generating weights. +## Include the Benchmarking Module -At the top of your `lib.rs`, add the module declaration: +At the top of your `lib.rs`, add the module declaration by adding the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #![cfg_attr(not(feature = "std"), no_std)] @@ -210,14 +180,14 @@ pub use pallet::*; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -// ... rest of the pallet +// Additional pallet code ``` -## Step 6: Configure Pallet Dependencies +The `#[cfg(feature = "runtime-benchmarks")]` attribute ensures that benchmarking code is only compiled when explicitly needed to keep your production runtime efficient. -The feature flag system in Cargo allows you to conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds. +## Configure Pallet Dependencies -Update your pallet's `Cargo.toml` to enable the benchmarking feature: +Update your pallet's `Cargo.toml` to enable the benchmarking feature by adding the following code: ```toml title="pallets/pallet-custom/Cargo.toml" [dependencies] @@ -237,11 +207,11 @@ std = [ ] ``` -## Step 7: Update Mock Runtime +The Cargo feature flag system lets you conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds. -In your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo` since unit tests focus on verifying functional correctness rather than performance characteristics. This keeps tests fast and focused on validating logic. +## Update Mock Runtime -Add the `WeightInfo` type to your test configuration in `mock.rs`: +Add the `WeightInfo` type to your test configuration in `mock.rs` by adding the following code: ```rust title="pallets/pallet-custom/src/mock.rs" impl pallet_custom::Config for Test { @@ -251,427 +221,285 @@ impl pallet_custom::Config for Test { } ``` -## Step 8: Configure Runtime Benchmarking - -To execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. This involves three configuration steps: +In your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo`, since unit tests focus on verifying functional correctness rather than performance. -### Update Runtime Cargo.toml +## Configure Runtime Benchmarking -When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. +To execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. Follow these steps to update the runtime configuration: -Add your pallet to the runtime's `runtime-benchmarks` feature in `runtime/Cargo.toml`: - -```toml title="runtime/Cargo.toml" -runtime-benchmarks = [ - "cumulus-pallet-parachain-system/runtime-benchmarks", - "hex-literal", - "pallet-parachain-template/runtime-benchmarks", - "polkadot-sdk/runtime-benchmarks", - "pallet-custom/runtime-benchmarks", -] -``` +1. **Update `runtime/Cargo.toml`**: Add your pallet to the runtime's `runtime-benchmarks` feature as follows: -### Update Runtime Configuration + ```toml title="runtime/Cargo.toml" + runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "hex-literal", + "pallet-parachain-template/runtime-benchmarks", + "polkadot-sdk/runtime-benchmarks", + "pallet-custom/runtime-benchmarks", + ] + ``` -Start with the placeholder implementation during development. After successfully running benchmarks and generating the weights file, you'll update this to use the benchmarked weights. + When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. -In `runtime/src/configs/mod.rs`, add the `WeightInfo` type: +2. **Update runtime configuration**: Run development benchmarks with the placeholder implementation and use the resulting weights file to update benchmark weights as follows: -```rust title="runtime/src/configs/mod.rs" -impl pallet_custom::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type CounterMaxValue = ConstU32<1000>; - type WeightInfo = (); -} -``` - -### Register Benchmarks - -The `define_benchmarks!` macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks. - -Add your pallet to the benchmark list in `runtime/src/benchmarks.rs`: + ```rust title="runtime/src/configs/mod.rs" + impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = (); + } + ``` -```rust title="runtime/src/benchmarks.rs" -polkadot_sdk::frame_benchmarking::define_benchmarks!( - [frame_system, SystemBench::] - [pallet_balances, Balances] - // ... other pallets - [pallet_custom, CustomPallet] -); -``` +3. **Register benchmarks**: Add your pallet to the benchmark list in `runtime/src/benchmarks.rs` as follows: -## Step 9: Run Benchmarks + ```rust title="runtime/src/benchmarks.rs" + polkadot_sdk::frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + // ... other pallets + [pallet_custom, CustomPallet] + ); + ``` -### Test Benchmark Compilation + The [`define_benchmarks!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.define_benchmarks.html){target=\_blank} macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks. -The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the full runtime. +## Test Benchmark Compilation -First, verify your benchmarks compile and run as tests: +Run the following command to verify your benchmarks compile and run as tests: ```bash cargo test -p pallet-custom --features runtime-benchmarks ``` -You should see your benchmark tests passing: +You will see terminal output similar to the following as your benchmark tests pass: -``` -test benchmarking::benchmarks::bench_set_counter_value ... ok -test benchmarking::benchmarks::bench_increment ... ok -test benchmarking::benchmarks::bench_decrement ... ok -``` +
+ cargo test -p pallet-custom --features runtime-benchmarks + test benchmarking::benchmarks::bench_set_counter_value ... ok + test benchmarking::benchmarks::bench_increment ... ok + test benchmarking::benchmarks::bench_decrement ... ok + +
-### Build the Runtime with Benchmarks +The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the entire runtime. -This build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. This is a special build used only for benchmarking - you'll create a different build later for actually running your chain. +## Build the Runtime with Benchmarks -Compile the runtime with benchmarking enabled to generate the WASM binary: +Compile the runtime with benchmarking enabled to generate the WASM binary using the following command: ```bash cargo build --release --features runtime-benchmarks ``` -This produces the runtime WASM file needed for benchmarking, typically located at: -``` -target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm -``` +This command produces the runtime WASM file needed for benchmarking, typically located at: `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm` -### Install the Benchmarking Tool +The build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. You'll create a different build later for operating your chain in production. -[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} is the official Polkadot SDK tool specifically designed for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system. +## Install the Benchmarking Tool -Install the `frame-omni-bencher` CLI tool: +Install the `frame-omni-bencher` CLI tool using the following command: ```bash cargo install frame-omni-bencher --locked ``` -### Download the Weight Template +[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} is the official Polkadot SDK tool designed explicitly for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system. -The weight template is a Handlebars file that transforms raw benchmark data into a properly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow Polkadot SDK conventions and include all necessary metadata like benchmark execution parameters, storage operation counts, and hardware information. +## Download the Weight Template -Download the official weight template file: +Download the official weight template file using the following commands: ```bash curl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \ --output ./pallets/pallet-custom/frame-weight-template.hbs ``` -### Hardware Requirements for Benchmarking - -!!! warning "Critical: Benchmark on Production-Like Hardware" - Benchmarks must be executed on hardware similar to what will run your chain in production. Weight measurements are hardware-dependent, and benchmarking on different hardware can lead to dangerous under-estimation or wasteful over-estimation of weights. - -Weights represent the actual computational time and resources consumed by extrinsics. These measurements vary significantly across different hardware configurations: - -- **CPU Performance**: Different processors execute instructions at different speeds. A faster development laptop will produce lower weight values than production server hardware -- **Storage Speed**: Database read/write performance varies between NVMe SSDs, SATA SSDs, and HDDs, affecting storage-related weights -- **Memory Bandwidth**: RAM speed impacts how quickly data can be accessed during execution -- **CPU Cache**: Cache size and architecture differences affect repeated operations - -Benchmarking on faster hardware than production leads to under-estimated weights - attackers could submit extrinsics that consume more resources than the weights suggest, potentially causing blocks to take longer than expected to produce or even halting the chain. Conversely, benchmarking on slower hardware creates over-estimated weights, resulting in unnecessarily high transaction fees and wasted block capacity. - -**Best practices:** - -1. **Match production specifications**: If your chain will run on specific validator hardware, benchmark on identical or very similar machines -2. **Use reference hardware**: The Polkadot ecosystem often uses standardized reference hardware specifications for consistency. Consider following these standards if your chain will connect to Polkadot or Kusama -3. **Dedicated benchmarking environment**: Run benchmarks on a machine without other heavy processes to ensure consistent measurements -4. **Document your hardware**: The generated weight files include hardware information in comments. Review this to ensure it matches your production environment -5. **Re-benchmark when hardware changes**: If your validator hardware specifications change, re-run benchmarks and update weights - -For development and testing purposes, you can run benchmarks on any available hardware to verify that your benchmark functions work correctly. However, before deploying to production, always re-run benchmarks on production-equivalent hardware. - -### Execute Benchmarks - -Benchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking the WASM ensures your weight measurements reflect real-world conditions. - -Run benchmarks for your pallet to generate weight files: - -```bash -frame-omni-bencher v1 benchmark pallet \ - --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ - --pallet pallet_custom \ - --extrinsic "" \ - --template ./pallets/pallet-custom/frame-weight-template.hbs \ - --output ./pallets/pallet-custom/src/weights.rs -``` - -**Command breakdown:** - -- `v1`: Specifies the benchmarking framework version (v2 API) -- `benchmark pallet`: Subcommand indicating you want to benchmark pallet extrinsics -- `--runtime`: Path to the compiled WASM runtime file that includes your pallet and benchmarks -- `--pallet pallet_custom`: Name of the pallet to benchmark (must match the name used in `define_benchmarks!`) -- `--extrinsic ""`: Empty string benchmarks all extrinsics in the pallet; you can specify a single extrinsic name to benchmark only that one -- `--template`: Path to the Handlebars template that formats the output -- `--output`: Destination file path for the generated weights module +The weight template is a Handlebars file that transforms raw benchmark data into a correctly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow the Polkadot SDK conventions and include all necessary metadata, such as benchmark execution parameters, storage operation counts, and hardware information. -### Advanced Options +## Execute Benchmarks -You can customize benchmark execution with additional parameters for more detailed measurements: +Run benchmarks for your pallet to generate weight files using the following commands: ```bash frame-omni-bencher v1 benchmark pallet \ --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ --pallet pallet_custom \ --extrinsic "" \ - --steps 50 \ - --repeat 20 \ --template ./pallets/pallet-custom/frame-weight-template.hbs \ --output ./pallets/pallet-custom/src/weights.rs ``` -**Additional parameters:** +Benchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking against the WASM ensures your weight measurements reflect real-world conditions. -- `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time -- `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise and providing more reliable weight estimates -- `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution -- `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions +??? note "Additional customization" -## Step 10: Use Generated Weights + You can customize benchmark execution with additional parameters for more detailed measurements, as shown in the sample code below: -After running benchmarks, a `weights.rs` file is generated containing measured weights. The generated weights are based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. Estimates or placeholder values cannot capture these nuances and will either waste block space (over-estimation) or create security risks (under-estimation). + ```bash + frame-omni-bencher v1 benchmark pallet \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ + --pallet pallet_custom \ + --extrinsic "" \ + --steps 50 \ + --repeat 20 \ + --template ./pallets/pallet-custom/frame-weight-template.hbs \ + --output ./pallets/pallet-custom/src/weights.rs + ``` + + - `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time. + - `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise, and providing more reliable weight estimates. + - `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution. + - `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions. -The file includes: +## Use Generated Weights -- Detailed documentation about the benchmark execution environment (date, hardware, parameters) -- The `WeightInfo` trait definition matching your benchmark functions -- `SubstrateWeight` implementation with measured weights from your benchmarks -- Database read/write costs calculated based on observed storage operations -- Component complexity annotations for variable inputs (if you use linear components) -- A fallback `()` implementation for testing environments +After running benchmarks, a `weights.rs` file is generated containing measured weights based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. -### Integrate the Generated Weights +Follow these steps to use the generated weights with your pallet: -Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during normal operation to calculate transaction fees and enforce block limits. +1. Integrate the generated weights by adding the weights module to your pallet's `lib.rs` as follows: -Add the weights module to your pallet's `lib.rs`: - -```rust title="pallets/pallet-custom/src/lib.rs" -#![cfg_attr(not(feature = "std"), no_std)] + ```rust title="pallets/pallet-custom/src/lib.rs" + #![cfg_attr(not(feature = "std"), no_std)] -extern crate alloc; -use alloc::vec::Vec; + extern crate alloc; + use alloc::vec::Vec; -pub use pallet::*; + pub use pallet::*; -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; + #[cfg(feature = "runtime-benchmarks")] + mod benchmarking; -pub mod weights; + pub mod weights; -#[frame::pallet] -pub mod pallet { - use super::*; - use frame::prelude::*; - use crate::weights::WeightInfo; - // ... rest of pallet -} -``` - -### Update Runtime Configuration - -This change activates your benchmarked weights in the production runtime. Now when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits. - -Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation: - -```rust title="runtime/src/configs/mod.rs" -impl pallet_custom::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type CounterMaxValue = ConstU32<1000>; - type WeightInfo = pallet_custom::weights::SubstrateWeight; -} -``` - -### Example Generated Weight File - -The generated `weights.rs` file will look similar to this: - -```rust title="pallets/pallet-custom/src/weights.rs" -//! Autogenerated weights for `pallet_custom` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20` - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -pub trait WeightInfo { - fn set_counter_value() -> Weight; - fn increment() -> Weight; - fn decrement() -> Weight; -} - -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - fn set_counter_value() -> Weight { - Weight::from_parts(8_234_000, 0) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - - fn increment() -> Weight { - Weight::from_parts(12_456_000, 0) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } - - fn decrement() -> Weight { - Weight::from_parts(11_987_000, 0) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + #[frame::pallet] + pub mod pallet { + use super::*; + use frame::prelude::*; + use crate::weights::WeightInfo; + // ... rest of pallet } -} -``` - -**Note**: The actual numbers will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} accounts for database read and write operations. + ``` -## Benchmarking Best Practices + Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during regular operation to calculate transaction fees and enforce block limits. -### 1. Test Worst-Case Scenarios +2. Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation by adding the following code: -Benchmarks should always measure maximum possible resource consumption. If you benchmark average or best-case scenarios, malicious users could craft transactions that hit worst-case paths in your code, consuming more resources than the weights indicate and potentially slowing down or halting block production. - -```rust -#[benchmark] -fn complex_operation() { - // Set up worst-case storage state - for i in 0..100 { - SomeStorage::::insert(i, vec![0u8; 1000]); + ```rust title="runtime/src/configs/mod.rs" + impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = pallet_custom::weights::SubstrateWeight; } + ``` - let caller = whitelisted_caller(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller)); -} -``` - -### 2. Use Linear Components for Variable Complexity + This change activates your benchmarked weights in the production runtime. Now, when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits. -Many extrinsics have variable costs depending on input parameters. [Linear components](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/trait.BenchmarkingSetup.html){target=\_blank} tell the benchmarking framework to test your extrinsic with different values of `n`, measure the execution time for each, and calculate a formula like `Weight = base_weight + (n * per_item_weight)`. This produces dynamic weights that accurately reflect the actual work being done. +??? code "Example generated weight file" + + The generated `weights.rs` file will look similar to this: -When extrinsic complexity depends on input size, use linear components: + ```rust title="pallets/pallet-custom/src/weights.rs" + //! Autogenerated weights for `pallet_custom` + //! + //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 + //! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20` -```rust title="pallets/pallet-custom/src/benchmarking.rs" -#[benchmark] -fn process_items(n: Linear<0, 100>) { - let caller = whitelisted_caller(); - let items: Vec = (0..n).collect(); + #![cfg_attr(rustfmt, rustfmt_skip)] + #![allow(unused_parens)] + #![allow(unused_imports)] + #![allow(missing_docs)] - #[extrinsic_call] - _(RawOrigin::Signed(caller), items); -} -``` + use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; + use core::marker::PhantomData; -### 3. Verify Results - -Assertions ensure that your benchmark is actually testing the code path you think it's testing. If your extrinsic fails silently or takes an early return, the benchmark would measure the wrong scenario and produce inaccurate weights. - -Always assert the expected state after extrinsic execution: - -```rust title="pallets/pallet-custom/src/benchmarking.rs" -#[benchmark] -fn my_extrinsic() { - let caller = whitelisted_caller(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller.clone())); - - // Verify the extrinsic had the expected effect - assert_eq!(MyStorage::::get(&caller), expected_value); -} -``` - -### 4. Minimize Setup Code - -While the benchmarking framework tries to isolate the extrinsic execution, excessive setup code can add noise to measurements. More importantly, setup code that doesn't reflect real-world pre-conditions can lead to benchmarking unrealistic scenarios. + pub trait WeightInfo { + fn set_counter_value() -> Weight; + fn increment() -> Weight; + fn decrement() -> Weight; + } -Only include necessary setup in benchmarks: + pub struct SubstrateWeight(PhantomData); + impl WeightInfo for SubstrateWeight { + fn set_counter_value() -> Weight { + Weight::from_parts(8_234_000, 0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } -```rust title="pallets/pallet-custom/src/benchmarking.rs" -#[benchmark] -fn efficient_benchmark() { - // Minimal setup - let caller = whitelisted_caller(); + fn increment() -> Weight { + Weight::from_parts(12_456_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } - #[extrinsic_call] - _(RawOrigin::Signed(caller)); + fn decrement() -> Weight { + Weight::from_parts(11_987_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + } + ``` - // Minimal assertions -} -``` + The actual numbers in your `weights.rs` file will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} accounts for database read and write operations. ## Run Your Chain Locally -Now that you've added the pallet to your runtime, you can launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide. - -### Build the Production Runtime - -The `runtime-benchmarks` feature flag adds special host functions (like `ext_benchmarking_current_time` and `ext_benchmarking_get_read_and_written_keys`) that are only available in the benchmarking execution environment. These functions allow the benchmarking framework to precisely measure execution time and track storage operations. However, regular nodes don't provide these host functions, so a runtime compiled with benchmarking features will fail to start on a production node. - -Before running your chain, rebuild the runtime **without** the `runtime-benchmarks` feature: - -```bash -cargo build --release -``` - -!!! note "Build Types" - Understanding the difference between builds is critical: - - - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher` - - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your actual chain +Now that you've added the pallet to your runtime, you can follow these steps to launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}: -This produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. +1. Before running your chain, rebuild the production runtime without the `runtime-benchmarks` feature using the following command: -### Generate a Chain Specification + ```bash + cargo build --release + ``` -The chain specification defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. By generating a new chain spec with your updated runtime (now containing your benchmarked pallet), you ensure that nodes starting from this spec will use the correct version of your code with proper weight calculations. + The `runtime-benchmarks` feature flag adds special host functions that are only available in the benchmarking execution environment. A runtime compiled with benchmarking features will fail to start on a production node. -Create a new chain specification file with the updated runtime: + This build produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. -```bash -chain-spec-builder create -t development \ ---relay-chain paseo \ ---para-id 1000 \ ---runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ -named-preset development -``` + !!! note "Compare build types" + - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher`. + - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your chain in production. -This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime. +2. Generate a new chain specification file with the updated runtime using the following commands: -### Start the Parachain Node + ```bash + chain-spec-builder create -t development \ + --relay-chain paseo \ + --para-id 1000 \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ + named-preset development + ``` -Launch the parachain using the Polkadot Omni Node with the generated chain specification by running the following command: + This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime, which defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. Generating this new chain spec with your updated runtime ensures nodes starting from this spec will use the correct version of your code with proper weight calculations. -```bash -polkadot-omni-node --chain ./chain_spec.json --dev -``` +3. Start the parachain node using the Polkadot Omni Node with the generated chain specification by running the following command: -The node will start and display initialization information including: + ```bash + polkadot-omni-node --chain ./chain_spec.json --dev + ``` -- The chain specification name -- The node identity and peer ID -- Database location -- Network endpoints (JSON-RPC and Prometheus) + The node will start and display initialization information, including: -### Verify Block Production + - The chain specification name + - The node identity and peer ID + - Database location + - Network endpoints (JSON-RPC and Prometheus) -Once the node is running, you should see log messages indicating successful block production: +4. Once the node is running, you will see log messages confirming successful production of blocks similar to the following: -``` -[Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc) -[Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ... -[Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2) -[Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ... -[Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32) -``` +
+ polkadot-omni-node --chain ./chain_spec.json --dev + [Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc) + [Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ... + [Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2) + [Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ... + [Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32) + +
-The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. + The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. ## Related Resources diff --git a/parachains/customize-runtime/pallet-development/pallet-testing.md b/parachains/customize-runtime/pallet-development/pallet-testing.md index 6dc75eb5e..816a2401a 100644 --- a/parachains/customize-runtime/pallet-development/pallet-testing.md +++ b/parachains/customize-runtime/pallet-development/pallet-testing.md @@ -1,10 +1,10 @@ --- -title: Pallet Testing +title: Unit Test Pallets description: Learn how to efficiently test pallets in the Polkadot SDK, ensuring the reliability and security of your pallets operations. categories: Parachains --- -# Pallet Testing +# Unit Test Pallets ## Introduction From c876bcef289d1157019a3a9c6cf48fd5dac70647 Mon Sep 17 00:00:00 2001 From: DAWN KELLY Date: Tue, 18 Nov 2025 13:42:01 -0500 Subject: [PATCH 03/12] fresh llms --- .ai/categories/parachains.md | 868 +++++++----------- ...ime-pallet-development-benchmark-pallet.md | 590 +++++------- ...ntime-pallet-development-pallet-testing.md | 4 +- llms-full.jsonl | 70 +- llms.txt | 2 +- 5 files changed, 585 insertions(+), 949 deletions(-) diff --git a/.ai/categories/parachains.md b/.ai/categories/parachains.md index 94700e0e8..309865038 100644 --- a/.ai/categories/parachains.md +++ b/.ai/categories/parachains.md @@ -1336,42 +1336,23 @@ Page Title: Benchmark Your Pallet Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks. -This guide continues the pallet development series, building on the [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet), [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime), and [Test Your Pallet](/parachains/customize-runtime/pallet-development/pallet-testing) tutorials. You'll learn how to benchmark the counter pallet extrinsics and integrate the generated weights into your runtime. +This guide continues building on what you've learned through the pallet development series. You'll learn how to benchmark the custom counter pallet extrinsics and integrate the generated weights into your runtime. ## Prerequisites Before you begin, ensure you have: -- Completed the previous pallet development tutorials -- Basic understanding of computational complexity -- Familiarity with Rust's testing framework +- Completed the previous pallet development tutorials: + - [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\_blank} + - [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\_blank} + - [Unit Test Pallets](/parachains/customize-runtime/pallet-development/pallet-testing/){target=\_blank} +- Basic understanding of [computational complexity](https://en.wikipedia.org/wiki/Computational_complexity){target=\_blank}. +- Familiarity with [Rust's testing framework](https://doc.rust-lang.org/book/ch11-00-testing.html){target=\_blank}. +- Familiarity setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}. Refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide for instructions if needed. -## Why Benchmark? +## Create the Benchmarking Module -In blockchain systems, every operation consumes resources. Weight is the mechanism Polkadot SDK uses to measure and limit resource consumption. Without accurate weights: - -- **Security Risk**: Malicious actors could submit transactions that consume excessive resources, blocking legitimate transactions or halting the chain -- **Inefficiency**: Over-estimated weights waste block space and reduce throughput -- **User Experience**: Inaccurate weights lead to incorrect fee calculations - -Benchmarking provides empirical measurements of your extrinsics under various conditions, ensuring weights reflect real-world resource consumption. - -## Understanding Weights - -The [weight system](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank} serves multiple purposes: - -- **DoS Protection**: Limits the computational work per block, preventing attackers from overwhelming the network -- **Fee Calculation**: Determines transaction fees based on actual resource usage -- **Block Production**: Helps block authors maximize throughput while staying within block limits - -Weights are expressed as [`Weight::from_parts(ref_time, proof_size)`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.from_parts){target=\_blank} where: - -- [`ref_time`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.ref_time){target=\_blank}: Computational time measured in picoseconds -- [`proof_size`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.proof_size){target=\_blank}: Storage proof size in bytes - -## Step 1: Create the Benchmarking Module - -Create a new file `benchmarking.rs` in your pallet's `src` directory. This module will contain all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} for your pallet: +Create a new file `benchmarking.rs` in your pallet's `src` directory and add the following code: ```rust title="pallets/pallet-custom/src/benchmarking.rs" #![cfg(feature = "runtime-benchmarks")] @@ -1408,7 +1389,7 @@ mod benchmarks { #[benchmark] fn decrement() { - // First set the counter to a non-zero value + // First, set the counter to a non-zero value CounterValue::::put(100); let caller: T::AccountId = whitelisted_caller(); @@ -1425,20 +1406,11 @@ mod benchmarks { } ``` -**Key components:** - -- **`#![cfg(feature = "runtime-benchmarks")]`**: Ensures benchmarking code only compiles when the feature is enabled -- **[`#[benchmarks]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmarks.html){target=\_blank}**: Marks the module containing benchmark definitions -- **[`#[benchmark]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmark.html){target=\_blank}**: Defines individual benchmark functions -- **[`#[extrinsic_call]`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.extrinsic_call.html){target=\_blank}**: Marks the actual extrinsic invocation to measure -- **[`whitelisted_caller()`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/fn.whitelisted_caller.html){target=\_blank}**: Generates a funded account for benchmarking -- **[`impl_benchmark_test_suite!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.impl_benchmark_test_suite.html){target=\_blank}**: Generates test functions to verify benchmarks work correctly +This module contains all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} for your pallet. -## Step 2: Define the Weight Trait +## Define the Weight Trait -The [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. This enables you to use placeholder weights during development and testing, then switch to auto-generated benchmarked weights in production without modifying the pallet code itself. - -Add a `weights` module to your pallet that defines the `WeightInfo` trait: +Add a `weights` module to your pallet that defines the `WeightInfo` trait using the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #[frame::pallet] @@ -1472,13 +1444,11 @@ pub mod pallet { } ``` -The `()` implementation provides placeholder weights for development. Later, this will be replaced with auto-generated weights from benchmarking. - -## Step 3: Add WeightInfo to Config +The `()` implementation provides placeholder weights for development. -By making `WeightInfo` an associated type in the `Config` trait, you allow each runtime that uses your pallet to specify which weight implementation to use. Different deployment environments (testnets, production chains, or different hardware configurations) may have different performance characteristics and can use different weight calculations. +## Add WeightInfo to Config -Update your pallet's `Config` trait to include `WeightInfo`: +Update your pallet's `Config` trait to include `WeightInfo` by adding the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #[pallet::config] @@ -1492,11 +1462,11 @@ pub trait Config: frame_system::Config { } ``` -## Step 4: Update Extrinsic Weight Annotations +The [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. By making `WeightInfo` an associated type in the `Config` trait, you will enable each runtime that uses your pallet to specify which weight implementation to use. -By calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. This allows you to easily switch between placeholder weights for testing and benchmarked weights for production without changing any pallet code. +## Update Extrinsic Weight Annotations -Replace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait: +Replace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait by adding the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #[pallet::call] @@ -1521,11 +1491,11 @@ impl Pallet { } ``` -## Step 5: Include the Benchmarking Module +By calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. You can switch between placeholder weights for testing and benchmarked weights for production easily, without changing any pallet code. -The `#[cfg(feature = "runtime-benchmarks")]` attribute ensures that benchmarking code is only compiled when explicitly needed. This keeps your production runtime lean by excluding benchmarking infrastructure from normal builds, as it's only needed when generating weights. +## Include the Benchmarking Module -At the top of your `lib.rs`, add the module declaration: +At the top of your `lib.rs`, add the module declaration by adding the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #![cfg_attr(not(feature = "std"), no_std)] @@ -1538,14 +1508,14 @@ pub use pallet::*; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -// ... rest of the pallet +// Additional pallet code ``` -## Step 6: Configure Pallet Dependencies +The `#[cfg(feature = "runtime-benchmarks")]` attribute ensures that benchmarking code is only compiled when explicitly needed to keep your production runtime efficient. -The feature flag system in Cargo allows you to conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds. +## Configure Pallet Dependencies -Update your pallet's `Cargo.toml` to enable the benchmarking feature: +Update your pallet's `Cargo.toml` to enable the benchmarking feature by adding the following code: ```toml title="pallets/pallet-custom/Cargo.toml" [dependencies] @@ -1565,11 +1535,11 @@ std = [ ] ``` -## Step 7: Update Mock Runtime +The Cargo feature flag system lets you conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds. -In your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo` since unit tests focus on verifying functional correctness rather than performance characteristics. This keeps tests fast and focused on validating logic. +## Update Mock Runtime -Add the `WeightInfo` type to your test configuration in `mock.rs`: +Add the `WeightInfo` type to your test configuration in `mock.rs` by adding the following code: ```rust title="pallets/pallet-custom/src/mock.rs" impl pallet_custom::Config for Test { @@ -1579,427 +1549,285 @@ impl pallet_custom::Config for Test { } ``` -## Step 8: Configure Runtime Benchmarking +In your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo`, since unit tests focus on verifying functional correctness rather than performance. -To execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. This involves three configuration steps: +## Configure Runtime Benchmarking -### Update Runtime Cargo.toml +To execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. Follow these steps to update the runtime configuration: -When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. +1. **Update `runtime/Cargo.toml`**: Add your pallet to the runtime's `runtime-benchmarks` feature as follows: -Add your pallet to the runtime's `runtime-benchmarks` feature in `runtime/Cargo.toml`: - -```toml title="runtime/Cargo.toml" -runtime-benchmarks = [ - "cumulus-pallet-parachain-system/runtime-benchmarks", - "hex-literal", - "pallet-parachain-template/runtime-benchmarks", - "polkadot-sdk/runtime-benchmarks", - "pallet-custom/runtime-benchmarks", -] -``` - -### Update Runtime Configuration - -Start with the placeholder implementation during development. After successfully running benchmarks and generating the weights file, you'll update this to use the benchmarked weights. - -In `runtime/src/configs/mod.rs`, add the `WeightInfo` type: - -```rust title="runtime/src/configs/mod.rs" -impl pallet_custom::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type CounterMaxValue = ConstU32<1000>; - type WeightInfo = (); -} -``` + ```toml title="runtime/Cargo.toml" + runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "hex-literal", + "pallet-parachain-template/runtime-benchmarks", + "polkadot-sdk/runtime-benchmarks", + "pallet-custom/runtime-benchmarks", + ] + ``` -### Register Benchmarks + When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. -The `define_benchmarks!` macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks. +2. **Update runtime configuration**: Run development benchmarks with the placeholder implementation and use the resulting weights file to update benchmark weights as follows: -Add your pallet to the benchmark list in `runtime/src/benchmarks.rs`: + ```rust title="runtime/src/configs/mod.rs" + impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = (); + } + ``` -```rust title="runtime/src/benchmarks.rs" -polkadot_sdk::frame_benchmarking::define_benchmarks!( - [frame_system, SystemBench::] - [pallet_balances, Balances] - // ... other pallets - [pallet_custom, CustomPallet] -); -``` +3. **Register benchmarks**: Add your pallet to the benchmark list in `runtime/src/benchmarks.rs` as follows: -## Step 9: Run Benchmarks + ```rust title="runtime/src/benchmarks.rs" + polkadot_sdk::frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + // ... other pallets + [pallet_custom, CustomPallet] + ); + ``` -### Test Benchmark Compilation + The [`define_benchmarks!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.define_benchmarks.html){target=\_blank} macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks. -The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the full runtime. +## Test Benchmark Compilation -First, verify your benchmarks compile and run as tests: +Run the following command to verify your benchmarks compile and run as tests: ```bash cargo test -p pallet-custom --features runtime-benchmarks ``` -You should see your benchmark tests passing: +You will see terminal output similar to the following as your benchmark tests pass: -``` -test benchmarking::benchmarks::bench_set_counter_value ... ok -test benchmarking::benchmarks::bench_increment ... ok -test benchmarking::benchmarks::bench_decrement ... ok -``` +
+ cargo test -p pallet-custom --features runtime-benchmarks + test benchmarking::benchmarks::bench_set_counter_value ... ok + test benchmarking::benchmarks::bench_increment ... ok + test benchmarking::benchmarks::bench_decrement ... ok + +
-### Build the Runtime with Benchmarks +The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the entire runtime. -This build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. This is a special build used only for benchmarking - you'll create a different build later for actually running your chain. +## Build the Runtime with Benchmarks -Compile the runtime with benchmarking enabled to generate the WASM binary: +Compile the runtime with benchmarking enabled to generate the WASM binary using the following command: ```bash cargo build --release --features runtime-benchmarks ``` -This produces the runtime WASM file needed for benchmarking, typically located at: -``` -target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm -``` +This command produces the runtime WASM file needed for benchmarking, typically located at: `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm` -### Install the Benchmarking Tool +The build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. You'll create a different build later for operating your chain in production. -[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} is the official Polkadot SDK tool specifically designed for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system. +## Install the Benchmarking Tool -Install the `frame-omni-bencher` CLI tool: +Install the `frame-omni-bencher` CLI tool using the following command: ```bash cargo install frame-omni-bencher --locked ``` -### Download the Weight Template +[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} is the official Polkadot SDK tool designed explicitly for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system. -The weight template is a Handlebars file that transforms raw benchmark data into a properly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow Polkadot SDK conventions and include all necessary metadata like benchmark execution parameters, storage operation counts, and hardware information. +## Download the Weight Template -Download the official weight template file: +Download the official weight template file using the following commands: ```bash curl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \ --output ./pallets/pallet-custom/frame-weight-template.hbs ``` -### Hardware Requirements for Benchmarking - -!!! warning "Critical: Benchmark on Production-Like Hardware" - Benchmarks must be executed on hardware similar to what will run your chain in production. Weight measurements are hardware-dependent, and benchmarking on different hardware can lead to dangerous under-estimation or wasteful over-estimation of weights. - -Weights represent the actual computational time and resources consumed by extrinsics. These measurements vary significantly across different hardware configurations: - -- **CPU Performance**: Different processors execute instructions at different speeds. A faster development laptop will produce lower weight values than production server hardware -- **Storage Speed**: Database read/write performance varies between NVMe SSDs, SATA SSDs, and HDDs, affecting storage-related weights -- **Memory Bandwidth**: RAM speed impacts how quickly data can be accessed during execution -- **CPU Cache**: Cache size and architecture differences affect repeated operations - -Benchmarking on faster hardware than production leads to under-estimated weights - attackers could submit extrinsics that consume more resources than the weights suggest, potentially causing blocks to take longer than expected to produce or even halting the chain. Conversely, benchmarking on slower hardware creates over-estimated weights, resulting in unnecessarily high transaction fees and wasted block capacity. - -**Best practices:** - -1. **Match production specifications**: If your chain will run on specific validator hardware, benchmark on identical or very similar machines -2. **Use reference hardware**: The Polkadot ecosystem often uses standardized reference hardware specifications for consistency. Consider following these standards if your chain will connect to Polkadot or Kusama -3. **Dedicated benchmarking environment**: Run benchmarks on a machine without other heavy processes to ensure consistent measurements -4. **Document your hardware**: The generated weight files include hardware information in comments. Review this to ensure it matches your production environment -5. **Re-benchmark when hardware changes**: If your validator hardware specifications change, re-run benchmarks and update weights - -For development and testing purposes, you can run benchmarks on any available hardware to verify that your benchmark functions work correctly. However, before deploying to production, always re-run benchmarks on production-equivalent hardware. - -### Execute Benchmarks - -Benchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking the WASM ensures your weight measurements reflect real-world conditions. - -Run benchmarks for your pallet to generate weight files: - -```bash -frame-omni-bencher v1 benchmark pallet \ - --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ - --pallet pallet_custom \ - --extrinsic "" \ - --template ./pallets/pallet-custom/frame-weight-template.hbs \ - --output ./pallets/pallet-custom/src/weights.rs -``` - -**Command breakdown:** - -- `v1`: Specifies the benchmarking framework version (v2 API) -- `benchmark pallet`: Subcommand indicating you want to benchmark pallet extrinsics -- `--runtime`: Path to the compiled WASM runtime file that includes your pallet and benchmarks -- `--pallet pallet_custom`: Name of the pallet to benchmark (must match the name used in `define_benchmarks!`) -- `--extrinsic ""`: Empty string benchmarks all extrinsics in the pallet; you can specify a single extrinsic name to benchmark only that one -- `--template`: Path to the Handlebars template that formats the output -- `--output`: Destination file path for the generated weights module +The weight template is a Handlebars file that transforms raw benchmark data into a correctly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow the Polkadot SDK conventions and include all necessary metadata, such as benchmark execution parameters, storage operation counts, and hardware information. -### Advanced Options +## Execute Benchmarks -You can customize benchmark execution with additional parameters for more detailed measurements: +Run benchmarks for your pallet to generate weight files using the following commands: ```bash frame-omni-bencher v1 benchmark pallet \ --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ --pallet pallet_custom \ --extrinsic "" \ - --steps 50 \ - --repeat 20 \ --template ./pallets/pallet-custom/frame-weight-template.hbs \ --output ./pallets/pallet-custom/src/weights.rs ``` -**Additional parameters:** - -- `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time -- `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise and providing more reliable weight estimates -- `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution -- `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions - -## Step 10: Use Generated Weights - -After running benchmarks, a `weights.rs` file is generated containing measured weights. The generated weights are based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. Estimates or placeholder values cannot capture these nuances and will either waste block space (over-estimation) or create security risks (under-estimation). - -The file includes: - -- Detailed documentation about the benchmark execution environment (date, hardware, parameters) -- The `WeightInfo` trait definition matching your benchmark functions -- `SubstrateWeight` implementation with measured weights from your benchmarks -- Database read/write costs calculated based on observed storage operations -- Component complexity annotations for variable inputs (if you use linear components) -- A fallback `()` implementation for testing environments +Benchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking against the WASM ensures your weight measurements reflect real-world conditions. -### Integrate the Generated Weights +??? note "Additional customization" -Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during normal operation to calculate transaction fees and enforce block limits. + You can customize benchmark execution with additional parameters for more detailed measurements, as shown in the sample code below: -Add the weights module to your pallet's `lib.rs`: - -```rust title="pallets/pallet-custom/src/lib.rs" -#![cfg_attr(not(feature = "std"), no_std)] - -extern crate alloc; -use alloc::vec::Vec; - -pub use pallet::*; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; + ```bash + frame-omni-bencher v1 benchmark pallet \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ + --pallet pallet_custom \ + --extrinsic "" \ + --steps 50 \ + --repeat 20 \ + --template ./pallets/pallet-custom/frame-weight-template.hbs \ + --output ./pallets/pallet-custom/src/weights.rs + ``` + + - `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time. + - `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise, and providing more reliable weight estimates. + - `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution. + - `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions. -pub mod weights; +## Use Generated Weights -#[frame::pallet] -pub mod pallet { - use super::*; - use frame::prelude::*; - use crate::weights::WeightInfo; - // ... rest of pallet -} -``` +After running benchmarks, a `weights.rs` file is generated containing measured weights based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. -### Update Runtime Configuration +Follow these steps to use the generated weights with your pallet: -This change activates your benchmarked weights in the production runtime. Now when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits. +1. Integrate the generated weights by adding the weights module to your pallet's `lib.rs` as follows: -Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation: + ```rust title="pallets/pallet-custom/src/lib.rs" + #![cfg_attr(not(feature = "std"), no_std)] -```rust title="runtime/src/configs/mod.rs" -impl pallet_custom::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type CounterMaxValue = ConstU32<1000>; - type WeightInfo = pallet_custom::weights::SubstrateWeight; -} -``` + extern crate alloc; + use alloc::vec::Vec; -### Example Generated Weight File + pub use pallet::*; -The generated `weights.rs` file will look similar to this: + #[cfg(feature = "runtime-benchmarks")] + mod benchmarking; -```rust title="pallets/pallet-custom/src/weights.rs" -//! Autogenerated weights for `pallet_custom` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20` + pub mod weights; -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] + #[frame::pallet] + pub mod pallet { + use super::*; + use frame::prelude::*; + use crate::weights::WeightInfo; + // ... rest of pallet + } + ``` -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; + Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during regular operation to calculate transaction fees and enforce block limits. -pub trait WeightInfo { - fn set_counter_value() -> Weight; - fn increment() -> Weight; - fn decrement() -> Weight; -} +2. Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation by adding the following code: -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - fn set_counter_value() -> Weight { - Weight::from_parts(8_234_000, 0) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) + ```rust title="runtime/src/configs/mod.rs" + impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = pallet_custom::weights::SubstrateWeight; } + ``` - fn increment() -> Weight { - Weight::from_parts(12_456_000, 0) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } + This change activates your benchmarked weights in the production runtime. Now, when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits. - fn decrement() -> Weight { - Weight::from_parts(11_987_000, 0) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) +??? code "Example generated weight file" + + The generated `weights.rs` file will look similar to this: + + ```rust title="pallets/pallet-custom/src/weights.rs" + //! Autogenerated weights for `pallet_custom` + //! + //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 + //! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20` + + #![cfg_attr(rustfmt, rustfmt_skip)] + #![allow(unused_parens)] + #![allow(unused_imports)] + #![allow(missing_docs)] + + use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; + use core::marker::PhantomData; + + pub trait WeightInfo { + fn set_counter_value() -> Weight; + fn increment() -> Weight; + fn decrement() -> Weight; } -} -``` - -**Note**: The actual numbers will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} accounts for database read and write operations. -## Benchmarking Best Practices - -### 1. Test Worst-Case Scenarios + pub struct SubstrateWeight(PhantomData); + impl WeightInfo for SubstrateWeight { + fn set_counter_value() -> Weight { + Weight::from_parts(8_234_000, 0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } -Benchmarks should always measure maximum possible resource consumption. If you benchmark average or best-case scenarios, malicious users could craft transactions that hit worst-case paths in your code, consuming more resources than the weights indicate and potentially slowing down or halting block production. + fn increment() -> Weight { + Weight::from_parts(12_456_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } -```rust -#[benchmark] -fn complex_operation() { - // Set up worst-case storage state - for i in 0..100 { - SomeStorage::::insert(i, vec![0u8; 1000]); + fn decrement() -> Weight { + Weight::from_parts(11_987_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } } + ``` - let caller = whitelisted_caller(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller)); -} -``` - -### 2. Use Linear Components for Variable Complexity - -Many extrinsics have variable costs depending on input parameters. [Linear components](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/trait.BenchmarkingSetup.html){target=\_blank} tell the benchmarking framework to test your extrinsic with different values of `n`, measure the execution time for each, and calculate a formula like `Weight = base_weight + (n * per_item_weight)`. This produces dynamic weights that accurately reflect the actual work being done. - -When extrinsic complexity depends on input size, use linear components: - -```rust title="pallets/pallet-custom/src/benchmarking.rs" -#[benchmark] -fn process_items(n: Linear<0, 100>) { - let caller = whitelisted_caller(); - let items: Vec = (0..n).collect(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller), items); -} -``` - -### 3. Verify Results - -Assertions ensure that your benchmark is actually testing the code path you think it's testing. If your extrinsic fails silently or takes an early return, the benchmark would measure the wrong scenario and produce inaccurate weights. - -Always assert the expected state after extrinsic execution: - -```rust title="pallets/pallet-custom/src/benchmarking.rs" -#[benchmark] -fn my_extrinsic() { - let caller = whitelisted_caller(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller.clone())); - - // Verify the extrinsic had the expected effect - assert_eq!(MyStorage::::get(&caller), expected_value); -} -``` - -### 4. Minimize Setup Code - -While the benchmarking framework tries to isolate the extrinsic execution, excessive setup code can add noise to measurements. More importantly, setup code that doesn't reflect real-world pre-conditions can lead to benchmarking unrealistic scenarios. - -Only include necessary setup in benchmarks: - -```rust title="pallets/pallet-custom/src/benchmarking.rs" -#[benchmark] -fn efficient_benchmark() { - // Minimal setup - let caller = whitelisted_caller(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller)); - - // Minimal assertions -} -``` + The actual numbers in your `weights.rs` file will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} accounts for database read and write operations. ## Run Your Chain Locally -Now that you've added the pallet to your runtime, you can launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide. - -### Build the Production Runtime - -The `runtime-benchmarks` feature flag adds special host functions (like `ext_benchmarking_current_time` and `ext_benchmarking_get_read_and_written_keys`) that are only available in the benchmarking execution environment. These functions allow the benchmarking framework to precisely measure execution time and track storage operations. However, regular nodes don't provide these host functions, so a runtime compiled with benchmarking features will fail to start on a production node. - -Before running your chain, rebuild the runtime **without** the `runtime-benchmarks` feature: +Now that you've added the pallet to your runtime, you can follow these steps to launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}: -```bash -cargo build --release -``` +1. Before running your chain, rebuild the production runtime without the `runtime-benchmarks` feature using the following command: -!!! note "Build Types" - Understanding the difference between builds is critical: - - - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher` - - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your actual chain - -This produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. + ```bash + cargo build --release + ``` -### Generate a Chain Specification + The `runtime-benchmarks` feature flag adds special host functions that are only available in the benchmarking execution environment. A runtime compiled with benchmarking features will fail to start on a production node. -The chain specification defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. By generating a new chain spec with your updated runtime (now containing your benchmarked pallet), you ensure that nodes starting from this spec will use the correct version of your code with proper weight calculations. + This build produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. -Create a new chain specification file with the updated runtime: + !!! note "Compare build types" + - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher`. + - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your chain in production. -```bash -chain-spec-builder create -t development \ ---relay-chain paseo \ ---para-id 1000 \ ---runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ -named-preset development -``` +2. Generate a new chain specification file with the updated runtime using the following commands: -This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime. - -### Start the Parachain Node + ```bash + chain-spec-builder create -t development \ + --relay-chain paseo \ + --para-id 1000 \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ + named-preset development + ``` -Launch the parachain using the Polkadot Omni Node with the generated chain specification by running the following command: + This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime, which defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. Generating this new chain spec with your updated runtime ensures nodes starting from this spec will use the correct version of your code with proper weight calculations. -```bash -polkadot-omni-node --chain ./chain_spec.json --dev -``` +3. Start the parachain node using the Polkadot Omni Node with the generated chain specification by running the following command: -The node will start and display initialization information including: + ```bash + polkadot-omni-node --chain ./chain_spec.json --dev + ``` -- The chain specification name -- The node identity and peer ID -- Database location -- Network endpoints (JSON-RPC and Prometheus) + The node will start and display initialization information, including: -### Verify Block Production + - The chain specification name + - The node identity and peer ID + - Database location + - Network endpoints (JSON-RPC and Prometheus) -Once the node is running, you should see log messages indicating successful block production: +4. Once the node is running, you will see log messages confirming successful production of blocks similar to the following: -``` -[Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc) -[Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ... -[Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2) -[Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ... -[Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32) -``` +
+ polkadot-omni-node --chain ./chain_spec.json --dev + [Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc) + [Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ... + [Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2) + [Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ... + [Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32) + +
-The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. + The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. ## Related Resources @@ -10042,142 +9870,6 @@ JAM removes many of the opinions and constraints of the current relay chain whil This architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes. ---- - -Page Title: Pallet Testing - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md -- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/ -- Summary: Learn how to efficiently test pallets in the Polkadot SDK, ensuring the reliability and security of your pallets operations. - -# Pallet Testing - -## Introduction - -Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries. - -To begin unit testing, you must first set up a mock runtime that simulates blockchain behavior, incorporating the necessary pallets. For a deeper understanding, consult the [Mock Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\_blank} guide. - -## Writing Unit Tests - -Once the mock runtime is in place, the next step is to write unit tests that evaluate the functionality of your pallet. Unit tests allow you to test specific pallet features in isolation, ensuring that each function behaves correctly under various conditions. These tests typically reside in your pallet module's `test.rs` file. - -Unit tests in the Polkadot SDK use the Rust testing framework, and the mock runtime you've defined earlier will serve as the test environment. Below are the typical steps involved in writing unit tests for a pallet. - -The tests confirm that: - -- **Pallets initialize correctly**: At the start of each test, the system should initialize with block number 0, and the pallets should be in their default states. -- **Pallets modify each other's state**: The second test shows how one pallet can trigger changes in another pallet's internal state, confirming proper cross-pallet interactions. -- **State transitions between blocks are seamless**: By simulating block transitions, the tests validate that the runtime responds correctly to changes in the block number. - -Testing pallet interactions within the runtime is critical for ensuring the blockchain behaves as expected under real-world conditions. Writing integration tests allows validation of how pallets function together, preventing issues that might arise when the system is fully assembled. - -This approach provides a comprehensive view of the runtime's functionality, ensuring the blockchain is stable and reliable. - -### Test Initialization - -Each test starts by initializing the runtime environment, typically using the `new_test_ext()` function, which sets up the mock storage and environment. - -```rust -#[test] -fn test_pallet_functionality() { - new_test_ext().execute_with(|| { - // Test logic goes here - }); -} -``` - -### Function Call Testing - -Call the pallet's extrinsics or functions to simulate user interaction or internal logic. Use the `assert_ok!` macro to check for successful execution and `assert_err!` to verify that errors are correctly handled. - -```rust -#[test] -fn it_works_for_valid_input() { - new_test_ext().execute_with(|| { - // Call an extrinsic or function - assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param)); - }); -} - -#[test] -fn it_fails_for_invalid_input() { - new_test_ext().execute_with(|| { - // Call an extrinsic with invalid input and expect an error - assert_err!( - TemplateModule::some_function(Origin::signed(1), invalid_param), - Error::::InvalidInput - ); - }); -} -``` - -### Storage Testing - -After calling a function or extrinsic in your pallet, it's essential to verify that the state changes in the pallet's storage match the expected behavior to ensure data is updated correctly based on the actions taken. - -The following example shows how to test the storage behavior before and after the function call: - -```rust -#[test] -fn test_storage_update_on_extrinsic_call() { - new_test_ext().execute_with(|| { - // Check the initial storage state (before the call) - assert_eq!(Something::::get(), None); - - // Dispatch a signed extrinsic, which modifies storage - assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42)); - - // Validate that the storage has been updated as expected (after the call) - assert_eq!(Something::::get(), Some(42)); - }); -} - -``` - -### Event Testing - -It's also crucial to test the events that your pallet emits during execution. By default, events generated in a pallet using the [`#generate_deposit`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.generate_deposit.html){target=\_blank} macro are stored under the system's event storage key (system/events) as [`EventRecord`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.EventRecord.html){target=\_blank} entries. These can be accessed using [`System::events()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.events){target=\_blank} or verified with specific helper methods provided by the system pallet, such as [`assert_has_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_has_event){target=\_blank} and [`assert_last_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_last_event){target=\_blank}. - -Here's an example of testing events in a mock runtime: - -```rust -#[test] -fn it_emits_events_on_success() { - new_test_ext().execute_with(|| { - // Call an extrinsic or function - assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param)); - - // Verify that the expected event was emitted - assert!(System::events().iter().any(|record| { - record.event == Event::TemplateModule(TemplateEvent::SomeEvent) - })); - }); -} -``` - -Some key considerations are: - -- **Block number**: Events are not emitted on the genesis block, so you need to set the block number using [`System::set_block_number()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.set_block_number){target=\_blank} to ensure events are triggered. -- **Converting events**: Use `.into()` when instantiating your pallet's event to convert it into a generic event type, as required by the system's event storage. - -## Where to Go Next - -- Dive into the full implementation of the [`mock.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/mock.rs){target=\_blank} and [`test.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/tests.rs){target=\_blank} files in the [Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=_blank}. - -
- -- Guide __Benchmarking__ - - --- - - Explore methods to measure the performance and execution cost of your pallet. - - [:octicons-arrow-right-24: Reference](/develop/parachains/testing/benchmarking) - -
- - --- Page Title: Parachains Overview @@ -12776,6 +12468,142 @@ You now know the weight system, how it affects transaction fee computation, and - [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} +--- + +Page Title: Unit Test Pallets + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md +- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/ +- Summary: Learn how to efficiently test pallets in the Polkadot SDK, ensuring the reliability and security of your pallets operations. + +# Unit Test Pallets + +## Introduction + +Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries. + +To begin unit testing, you must first set up a mock runtime that simulates blockchain behavior, incorporating the necessary pallets. For a deeper understanding, consult the [Mock Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\_blank} guide. + +## Writing Unit Tests + +Once the mock runtime is in place, the next step is to write unit tests that evaluate the functionality of your pallet. Unit tests allow you to test specific pallet features in isolation, ensuring that each function behaves correctly under various conditions. These tests typically reside in your pallet module's `test.rs` file. + +Unit tests in the Polkadot SDK use the Rust testing framework, and the mock runtime you've defined earlier will serve as the test environment. Below are the typical steps involved in writing unit tests for a pallet. + +The tests confirm that: + +- **Pallets initialize correctly**: At the start of each test, the system should initialize with block number 0, and the pallets should be in their default states. +- **Pallets modify each other's state**: The second test shows how one pallet can trigger changes in another pallet's internal state, confirming proper cross-pallet interactions. +- **State transitions between blocks are seamless**: By simulating block transitions, the tests validate that the runtime responds correctly to changes in the block number. + +Testing pallet interactions within the runtime is critical for ensuring the blockchain behaves as expected under real-world conditions. Writing integration tests allows validation of how pallets function together, preventing issues that might arise when the system is fully assembled. + +This approach provides a comprehensive view of the runtime's functionality, ensuring the blockchain is stable and reliable. + +### Test Initialization + +Each test starts by initializing the runtime environment, typically using the `new_test_ext()` function, which sets up the mock storage and environment. + +```rust +#[test] +fn test_pallet_functionality() { + new_test_ext().execute_with(|| { + // Test logic goes here + }); +} +``` + +### Function Call Testing + +Call the pallet's extrinsics or functions to simulate user interaction or internal logic. Use the `assert_ok!` macro to check for successful execution and `assert_err!` to verify that errors are correctly handled. + +```rust +#[test] +fn it_works_for_valid_input() { + new_test_ext().execute_with(|| { + // Call an extrinsic or function + assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param)); + }); +} + +#[test] +fn it_fails_for_invalid_input() { + new_test_ext().execute_with(|| { + // Call an extrinsic with invalid input and expect an error + assert_err!( + TemplateModule::some_function(Origin::signed(1), invalid_param), + Error::::InvalidInput + ); + }); +} +``` + +### Storage Testing + +After calling a function or extrinsic in your pallet, it's essential to verify that the state changes in the pallet's storage match the expected behavior to ensure data is updated correctly based on the actions taken. + +The following example shows how to test the storage behavior before and after the function call: + +```rust +#[test] +fn test_storage_update_on_extrinsic_call() { + new_test_ext().execute_with(|| { + // Check the initial storage state (before the call) + assert_eq!(Something::::get(), None); + + // Dispatch a signed extrinsic, which modifies storage + assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42)); + + // Validate that the storage has been updated as expected (after the call) + assert_eq!(Something::::get(), Some(42)); + }); +} + +``` + +### Event Testing + +It's also crucial to test the events that your pallet emits during execution. By default, events generated in a pallet using the [`#generate_deposit`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.generate_deposit.html){target=\_blank} macro are stored under the system's event storage key (system/events) as [`EventRecord`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.EventRecord.html){target=\_blank} entries. These can be accessed using [`System::events()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.events){target=\_blank} or verified with specific helper methods provided by the system pallet, such as [`assert_has_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_has_event){target=\_blank} and [`assert_last_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_last_event){target=\_blank}. + +Here's an example of testing events in a mock runtime: + +```rust +#[test] +fn it_emits_events_on_success() { + new_test_ext().execute_with(|| { + // Call an extrinsic or function + assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param)); + + // Verify that the expected event was emitted + assert!(System::events().iter().any(|record| { + record.event == Event::TemplateModule(TemplateEvent::SomeEvent) + })); + }); +} +``` + +Some key considerations are: + +- **Block number**: Events are not emitted on the genesis block, so you need to set the block number using [`System::set_block_number()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.set_block_number){target=\_blank} to ensure events are triggered. +- **Converting events**: Use `.into()` when instantiating your pallet's event to convert it into a generic event type, as required by the system's event storage. + +## Where to Go Next + +- Dive into the full implementation of the [`mock.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/mock.rs){target=\_blank} and [`test.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/tests.rs){target=\_blank} files in the [Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=_blank}. + +
+ +- Guide __Benchmarking__ + + --- + + Explore methods to measure the performance and execution cost of your pallet. + + [:octicons-arrow-right-24: Reference](/develop/parachains/testing/benchmarking) + +
+ + --- Page Title: Unlock a Parachain diff --git a/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md b/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md index 263d742a9..d84e40e0f 100644 --- a/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md +++ b/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md @@ -9,42 +9,23 @@ url: https://docs.polkadot.com/parachains/customize-runtime/pallet-development/b Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks. -This guide continues the pallet development series, building on the [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet), [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime), and [Test Your Pallet](/parachains/customize-runtime/pallet-development/pallet-testing) tutorials. You'll learn how to benchmark the counter pallet extrinsics and integrate the generated weights into your runtime. +This guide continues building on what you've learned through the pallet development series. You'll learn how to benchmark the custom counter pallet extrinsics and integrate the generated weights into your runtime. ## Prerequisites Before you begin, ensure you have: -- Completed the previous pallet development tutorials -- Basic understanding of computational complexity -- Familiarity with Rust's testing framework +- Completed the previous pallet development tutorials: + - [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\_blank} + - [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\_blank} + - [Unit Test Pallets](/parachains/customize-runtime/pallet-development/pallet-testing/){target=\_blank} +- Basic understanding of [computational complexity](https://en.wikipedia.org/wiki/Computational_complexity){target=\_blank}. +- Familiarity with [Rust's testing framework](https://doc.rust-lang.org/book/ch11-00-testing.html){target=\_blank}. +- Familiarity setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}. Refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide for instructions if needed. -## Why Benchmark? +## Create the Benchmarking Module -In blockchain systems, every operation consumes resources. Weight is the mechanism Polkadot SDK uses to measure and limit resource consumption. Without accurate weights: - -- **Security Risk**: Malicious actors could submit transactions that consume excessive resources, blocking legitimate transactions or halting the chain -- **Inefficiency**: Over-estimated weights waste block space and reduce throughput -- **User Experience**: Inaccurate weights lead to incorrect fee calculations - -Benchmarking provides empirical measurements of your extrinsics under various conditions, ensuring weights reflect real-world resource consumption. - -## Understanding Weights - -The [weight system](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank} serves multiple purposes: - -- **DoS Protection**: Limits the computational work per block, preventing attackers from overwhelming the network -- **Fee Calculation**: Determines transaction fees based on actual resource usage -- **Block Production**: Helps block authors maximize throughput while staying within block limits - -Weights are expressed as [`Weight::from_parts(ref_time, proof_size)`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.from_parts){target=\_blank} where: - -- [`ref_time`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.ref_time){target=\_blank}: Computational time measured in picoseconds -- [`proof_size`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.proof_size){target=\_blank}: Storage proof size in bytes - -## Step 1: Create the Benchmarking Module - -Create a new file `benchmarking.rs` in your pallet's `src` directory. This module will contain all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} for your pallet: +Create a new file `benchmarking.rs` in your pallet's `src` directory and add the following code: ```rust title="pallets/pallet-custom/src/benchmarking.rs" #![cfg(feature = "runtime-benchmarks")] @@ -81,7 +62,7 @@ mod benchmarks { #[benchmark] fn decrement() { - // First set the counter to a non-zero value + // First, set the counter to a non-zero value CounterValue::::put(100); let caller: T::AccountId = whitelisted_caller(); @@ -98,20 +79,11 @@ mod benchmarks { } ``` -**Key components:** +This module contains all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\_blank} for your pallet. -- **`#![cfg(feature = "runtime-benchmarks")]`**: Ensures benchmarking code only compiles when the feature is enabled -- **[`#[benchmarks]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmarks.html){target=\_blank}**: Marks the module containing benchmark definitions -- **[`#[benchmark]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmark.html){target=\_blank}**: Defines individual benchmark functions -- **[`#[extrinsic_call]`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.extrinsic_call.html){target=\_blank}**: Marks the actual extrinsic invocation to measure -- **[`whitelisted_caller()`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/fn.whitelisted_caller.html){target=\_blank}**: Generates a funded account for benchmarking -- **[`impl_benchmark_test_suite!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.impl_benchmark_test_suite.html){target=\_blank}**: Generates test functions to verify benchmarks work correctly +## Define the Weight Trait -## Step 2: Define the Weight Trait - -The [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. This enables you to use placeholder weights during development and testing, then switch to auto-generated benchmarked weights in production without modifying the pallet code itself. - -Add a `weights` module to your pallet that defines the `WeightInfo` trait: +Add a `weights` module to your pallet that defines the `WeightInfo` trait using the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #[frame::pallet] @@ -145,13 +117,11 @@ pub mod pallet { } ``` -The `()` implementation provides placeholder weights for development. Later, this will be replaced with auto-generated weights from benchmarking. +The `()` implementation provides placeholder weights for development. -## Step 3: Add WeightInfo to Config +## Add WeightInfo to Config -By making `WeightInfo` an associated type in the `Config` trait, you allow each runtime that uses your pallet to specify which weight implementation to use. Different deployment environments (testnets, production chains, or different hardware configurations) may have different performance characteristics and can use different weight calculations. - -Update your pallet's `Config` trait to include `WeightInfo`: +Update your pallet's `Config` trait to include `WeightInfo` by adding the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #[pallet::config] @@ -165,11 +135,11 @@ pub trait Config: frame_system::Config { } ``` -## Step 4: Update Extrinsic Weight Annotations +The [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. By making `WeightInfo` an associated type in the `Config` trait, you will enable each runtime that uses your pallet to specify which weight implementation to use. -By calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. This allows you to easily switch between placeholder weights for testing and benchmarked weights for production without changing any pallet code. +## Update Extrinsic Weight Annotations -Replace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait: +Replace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait by adding the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #[pallet::call] @@ -194,11 +164,11 @@ impl Pallet { } ``` -## Step 5: Include the Benchmarking Module +By calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. You can switch between placeholder weights for testing and benchmarked weights for production easily, without changing any pallet code. -The `#[cfg(feature = "runtime-benchmarks")]` attribute ensures that benchmarking code is only compiled when explicitly needed. This keeps your production runtime lean by excluding benchmarking infrastructure from normal builds, as it's only needed when generating weights. +## Include the Benchmarking Module -At the top of your `lib.rs`, add the module declaration: +At the top of your `lib.rs`, add the module declaration by adding the following code: ```rust title="pallets/pallet-custom/src/lib.rs" #![cfg_attr(not(feature = "std"), no_std)] @@ -211,14 +181,14 @@ pub use pallet::*; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -// ... rest of the pallet +// Additional pallet code ``` -## Step 6: Configure Pallet Dependencies +The `#[cfg(feature = "runtime-benchmarks")]` attribute ensures that benchmarking code is only compiled when explicitly needed to keep your production runtime efficient. -The feature flag system in Cargo allows you to conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds. +## Configure Pallet Dependencies -Update your pallet's `Cargo.toml` to enable the benchmarking feature: +Update your pallet's `Cargo.toml` to enable the benchmarking feature by adding the following code: ```toml title="pallets/pallet-custom/Cargo.toml" [dependencies] @@ -238,11 +208,11 @@ std = [ ] ``` -## Step 7: Update Mock Runtime +The Cargo feature flag system lets you conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds. -In your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo` since unit tests focus on verifying functional correctness rather than performance characteristics. This keeps tests fast and focused on validating logic. +## Update Mock Runtime -Add the `WeightInfo` type to your test configuration in `mock.rs`: +Add the `WeightInfo` type to your test configuration in `mock.rs` by adding the following code: ```rust title="pallets/pallet-custom/src/mock.rs" impl pallet_custom::Config for Test { @@ -252,427 +222,285 @@ impl pallet_custom::Config for Test { } ``` -## Step 8: Configure Runtime Benchmarking - -To execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. This involves three configuration steps: +In your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo`, since unit tests focus on verifying functional correctness rather than performance. -### Update Runtime Cargo.toml +## Configure Runtime Benchmarking -When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. +To execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. Follow these steps to update the runtime configuration: -Add your pallet to the runtime's `runtime-benchmarks` feature in `runtime/Cargo.toml`: - -```toml title="runtime/Cargo.toml" -runtime-benchmarks = [ - "cumulus-pallet-parachain-system/runtime-benchmarks", - "hex-literal", - "pallet-parachain-template/runtime-benchmarks", - "polkadot-sdk/runtime-benchmarks", - "pallet-custom/runtime-benchmarks", -] -``` +1. **Update `runtime/Cargo.toml`**: Add your pallet to the runtime's `runtime-benchmarks` feature as follows: -### Update Runtime Configuration + ```toml title="runtime/Cargo.toml" + runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "hex-literal", + "pallet-parachain-template/runtime-benchmarks", + "polkadot-sdk/runtime-benchmarks", + "pallet-custom/runtime-benchmarks", + ] + ``` -Start with the placeholder implementation during development. After successfully running benchmarks and generating the weights file, you'll update this to use the benchmarked weights. + When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. -In `runtime/src/configs/mod.rs`, add the `WeightInfo` type: +2. **Update runtime configuration**: Run development benchmarks with the placeholder implementation and use the resulting weights file to update benchmark weights as follows: -```rust title="runtime/src/configs/mod.rs" -impl pallet_custom::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type CounterMaxValue = ConstU32<1000>; - type WeightInfo = (); -} -``` - -### Register Benchmarks - -The `define_benchmarks!` macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks. - -Add your pallet to the benchmark list in `runtime/src/benchmarks.rs`: + ```rust title="runtime/src/configs/mod.rs" + impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = (); + } + ``` -```rust title="runtime/src/benchmarks.rs" -polkadot_sdk::frame_benchmarking::define_benchmarks!( - [frame_system, SystemBench::] - [pallet_balances, Balances] - // ... other pallets - [pallet_custom, CustomPallet] -); -``` +3. **Register benchmarks**: Add your pallet to the benchmark list in `runtime/src/benchmarks.rs` as follows: -## Step 9: Run Benchmarks + ```rust title="runtime/src/benchmarks.rs" + polkadot_sdk::frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + // ... other pallets + [pallet_custom, CustomPallet] + ); + ``` -### Test Benchmark Compilation + The [`define_benchmarks!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.define_benchmarks.html){target=\_blank} macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks. -The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the full runtime. +## Test Benchmark Compilation -First, verify your benchmarks compile and run as tests: +Run the following command to verify your benchmarks compile and run as tests: ```bash cargo test -p pallet-custom --features runtime-benchmarks ``` -You should see your benchmark tests passing: +You will see terminal output similar to the following as your benchmark tests pass: -``` -test benchmarking::benchmarks::bench_set_counter_value ... ok -test benchmarking::benchmarks::bench_increment ... ok -test benchmarking::benchmarks::bench_decrement ... ok -``` +
+ cargo test -p pallet-custom --features runtime-benchmarks + test benchmarking::benchmarks::bench_set_counter_value ... ok + test benchmarking::benchmarks::bench_increment ... ok + test benchmarking::benchmarks::bench_decrement ... ok + +
-### Build the Runtime with Benchmarks +The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the entire runtime. -This build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. This is a special build used only for benchmarking - you'll create a different build later for actually running your chain. +## Build the Runtime with Benchmarks -Compile the runtime with benchmarking enabled to generate the WASM binary: +Compile the runtime with benchmarking enabled to generate the WASM binary using the following command: ```bash cargo build --release --features runtime-benchmarks ``` -This produces the runtime WASM file needed for benchmarking, typically located at: -``` -target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm -``` +This command produces the runtime WASM file needed for benchmarking, typically located at: `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm` -### Install the Benchmarking Tool +The build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. You'll create a different build later for operating your chain in production. -[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} is the official Polkadot SDK tool specifically designed for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system. +## Install the Benchmarking Tool -Install the `frame-omni-bencher` CLI tool: +Install the `frame-omni-bencher` CLI tool using the following command: ```bash cargo install frame-omni-bencher --locked ``` -### Download the Weight Template +[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} is the official Polkadot SDK tool designed explicitly for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system. -The weight template is a Handlebars file that transforms raw benchmark data into a properly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow Polkadot SDK conventions and include all necessary metadata like benchmark execution parameters, storage operation counts, and hardware information. +## Download the Weight Template -Download the official weight template file: +Download the official weight template file using the following commands: ```bash curl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \ --output ./pallets/pallet-custom/frame-weight-template.hbs ``` -### Hardware Requirements for Benchmarking - -!!! warning "Critical: Benchmark on Production-Like Hardware" - Benchmarks must be executed on hardware similar to what will run your chain in production. Weight measurements are hardware-dependent, and benchmarking on different hardware can lead to dangerous under-estimation or wasteful over-estimation of weights. - -Weights represent the actual computational time and resources consumed by extrinsics. These measurements vary significantly across different hardware configurations: - -- **CPU Performance**: Different processors execute instructions at different speeds. A faster development laptop will produce lower weight values than production server hardware -- **Storage Speed**: Database read/write performance varies between NVMe SSDs, SATA SSDs, and HDDs, affecting storage-related weights -- **Memory Bandwidth**: RAM speed impacts how quickly data can be accessed during execution -- **CPU Cache**: Cache size and architecture differences affect repeated operations - -Benchmarking on faster hardware than production leads to under-estimated weights - attackers could submit extrinsics that consume more resources than the weights suggest, potentially causing blocks to take longer than expected to produce or even halting the chain. Conversely, benchmarking on slower hardware creates over-estimated weights, resulting in unnecessarily high transaction fees and wasted block capacity. - -**Best practices:** - -1. **Match production specifications**: If your chain will run on specific validator hardware, benchmark on identical or very similar machines -2. **Use reference hardware**: The Polkadot ecosystem often uses standardized reference hardware specifications for consistency. Consider following these standards if your chain will connect to Polkadot or Kusama -3. **Dedicated benchmarking environment**: Run benchmarks on a machine without other heavy processes to ensure consistent measurements -4. **Document your hardware**: The generated weight files include hardware information in comments. Review this to ensure it matches your production environment -5. **Re-benchmark when hardware changes**: If your validator hardware specifications change, re-run benchmarks and update weights - -For development and testing purposes, you can run benchmarks on any available hardware to verify that your benchmark functions work correctly. However, before deploying to production, always re-run benchmarks on production-equivalent hardware. - -### Execute Benchmarks - -Benchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking the WASM ensures your weight measurements reflect real-world conditions. - -Run benchmarks for your pallet to generate weight files: - -```bash -frame-omni-bencher v1 benchmark pallet \ - --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ - --pallet pallet_custom \ - --extrinsic "" \ - --template ./pallets/pallet-custom/frame-weight-template.hbs \ - --output ./pallets/pallet-custom/src/weights.rs -``` - -**Command breakdown:** - -- `v1`: Specifies the benchmarking framework version (v2 API) -- `benchmark pallet`: Subcommand indicating you want to benchmark pallet extrinsics -- `--runtime`: Path to the compiled WASM runtime file that includes your pallet and benchmarks -- `--pallet pallet_custom`: Name of the pallet to benchmark (must match the name used in `define_benchmarks!`) -- `--extrinsic ""`: Empty string benchmarks all extrinsics in the pallet; you can specify a single extrinsic name to benchmark only that one -- `--template`: Path to the Handlebars template that formats the output -- `--output`: Destination file path for the generated weights module +The weight template is a Handlebars file that transforms raw benchmark data into a correctly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow the Polkadot SDK conventions and include all necessary metadata, such as benchmark execution parameters, storage operation counts, and hardware information. -### Advanced Options +## Execute Benchmarks -You can customize benchmark execution with additional parameters for more detailed measurements: +Run benchmarks for your pallet to generate weight files using the following commands: ```bash frame-omni-bencher v1 benchmark pallet \ --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ --pallet pallet_custom \ --extrinsic "" \ - --steps 50 \ - --repeat 20 \ --template ./pallets/pallet-custom/frame-weight-template.hbs \ --output ./pallets/pallet-custom/src/weights.rs ``` -**Additional parameters:** +Benchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking against the WASM ensures your weight measurements reflect real-world conditions. -- `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time -- `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise and providing more reliable weight estimates -- `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution -- `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions +??? note "Additional customization" -## Step 10: Use Generated Weights + You can customize benchmark execution with additional parameters for more detailed measurements, as shown in the sample code below: -After running benchmarks, a `weights.rs` file is generated containing measured weights. The generated weights are based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. Estimates or placeholder values cannot capture these nuances and will either waste block space (over-estimation) or create security risks (under-estimation). + ```bash + frame-omni-bencher v1 benchmark pallet \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \ + --pallet pallet_custom \ + --extrinsic "" \ + --steps 50 \ + --repeat 20 \ + --template ./pallets/pallet-custom/frame-weight-template.hbs \ + --output ./pallets/pallet-custom/src/weights.rs + ``` + + - `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time. + - `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise, and providing more reliable weight estimates. + - `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution. + - `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions. -The file includes: +## Use Generated Weights -- Detailed documentation about the benchmark execution environment (date, hardware, parameters) -- The `WeightInfo` trait definition matching your benchmark functions -- `SubstrateWeight` implementation with measured weights from your benchmarks -- Database read/write costs calculated based on observed storage operations -- Component complexity annotations for variable inputs (if you use linear components) -- A fallback `()` implementation for testing environments +After running benchmarks, a `weights.rs` file is generated containing measured weights based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. -### Integrate the Generated Weights +Follow these steps to use the generated weights with your pallet: -Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during normal operation to calculate transaction fees and enforce block limits. +1. Integrate the generated weights by adding the weights module to your pallet's `lib.rs` as follows: -Add the weights module to your pallet's `lib.rs`: - -```rust title="pallets/pallet-custom/src/lib.rs" -#![cfg_attr(not(feature = "std"), no_std)] + ```rust title="pallets/pallet-custom/src/lib.rs" + #![cfg_attr(not(feature = "std"), no_std)] -extern crate alloc; -use alloc::vec::Vec; + extern crate alloc; + use alloc::vec::Vec; -pub use pallet::*; + pub use pallet::*; -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; + #[cfg(feature = "runtime-benchmarks")] + mod benchmarking; -pub mod weights; + pub mod weights; -#[frame::pallet] -pub mod pallet { - use super::*; - use frame::prelude::*; - use crate::weights::WeightInfo; - // ... rest of pallet -} -``` - -### Update Runtime Configuration - -This change activates your benchmarked weights in the production runtime. Now when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits. - -Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation: - -```rust title="runtime/src/configs/mod.rs" -impl pallet_custom::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type CounterMaxValue = ConstU32<1000>; - type WeightInfo = pallet_custom::weights::SubstrateWeight; -} -``` - -### Example Generated Weight File - -The generated `weights.rs` file will look similar to this: - -```rust title="pallets/pallet-custom/src/weights.rs" -//! Autogenerated weights for `pallet_custom` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20` - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(missing_docs)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; - -pub trait WeightInfo { - fn set_counter_value() -> Weight; - fn increment() -> Weight; - fn decrement() -> Weight; -} - -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - fn set_counter_value() -> Weight { - Weight::from_parts(8_234_000, 0) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(1)) - } - - fn increment() -> Weight { - Weight::from_parts(12_456_000, 0) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } - - fn decrement() -> Weight { - Weight::from_parts(11_987_000, 0) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) + #[frame::pallet] + pub mod pallet { + use super::*; + use frame::prelude::*; + use crate::weights::WeightInfo; + // ... rest of pallet } -} -``` - -**Note**: The actual numbers will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} accounts for database read and write operations. + ``` -## Benchmarking Best Practices + Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during regular operation to calculate transaction fees and enforce block limits. -### 1. Test Worst-Case Scenarios +2. Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation by adding the following code: -Benchmarks should always measure maximum possible resource consumption. If you benchmark average or best-case scenarios, malicious users could craft transactions that hit worst-case paths in your code, consuming more resources than the weights indicate and potentially slowing down or halting block production. - -```rust -#[benchmark] -fn complex_operation() { - // Set up worst-case storage state - for i in 0..100 { - SomeStorage::::insert(i, vec![0u8; 1000]); + ```rust title="runtime/src/configs/mod.rs" + impl pallet_custom::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + type WeightInfo = pallet_custom::weights::SubstrateWeight; } + ``` - let caller = whitelisted_caller(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller)); -} -``` - -### 2. Use Linear Components for Variable Complexity + This change activates your benchmarked weights in the production runtime. Now, when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits. -Many extrinsics have variable costs depending on input parameters. [Linear components](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/trait.BenchmarkingSetup.html){target=\_blank} tell the benchmarking framework to test your extrinsic with different values of `n`, measure the execution time for each, and calculate a formula like `Weight = base_weight + (n * per_item_weight)`. This produces dynamic weights that accurately reflect the actual work being done. +??? code "Example generated weight file" + + The generated `weights.rs` file will look similar to this: -When extrinsic complexity depends on input size, use linear components: + ```rust title="pallets/pallet-custom/src/weights.rs" + //! Autogenerated weights for `pallet_custom` + //! + //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 + //! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20` -```rust title="pallets/pallet-custom/src/benchmarking.rs" -#[benchmark] -fn process_items(n: Linear<0, 100>) { - let caller = whitelisted_caller(); - let items: Vec = (0..n).collect(); + #![cfg_attr(rustfmt, rustfmt_skip)] + #![allow(unused_parens)] + #![allow(unused_imports)] + #![allow(missing_docs)] - #[extrinsic_call] - _(RawOrigin::Signed(caller), items); -} -``` + use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; + use core::marker::PhantomData; -### 3. Verify Results - -Assertions ensure that your benchmark is actually testing the code path you think it's testing. If your extrinsic fails silently or takes an early return, the benchmark would measure the wrong scenario and produce inaccurate weights. - -Always assert the expected state after extrinsic execution: - -```rust title="pallets/pallet-custom/src/benchmarking.rs" -#[benchmark] -fn my_extrinsic() { - let caller = whitelisted_caller(); - - #[extrinsic_call] - _(RawOrigin::Signed(caller.clone())); - - // Verify the extrinsic had the expected effect - assert_eq!(MyStorage::::get(&caller), expected_value); -} -``` - -### 4. Minimize Setup Code - -While the benchmarking framework tries to isolate the extrinsic execution, excessive setup code can add noise to measurements. More importantly, setup code that doesn't reflect real-world pre-conditions can lead to benchmarking unrealistic scenarios. + pub trait WeightInfo { + fn set_counter_value() -> Weight; + fn increment() -> Weight; + fn decrement() -> Weight; + } -Only include necessary setup in benchmarks: + pub struct SubstrateWeight(PhantomData); + impl WeightInfo for SubstrateWeight { + fn set_counter_value() -> Weight { + Weight::from_parts(8_234_000, 0) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } -```rust title="pallets/pallet-custom/src/benchmarking.rs" -#[benchmark] -fn efficient_benchmark() { - // Minimal setup - let caller = whitelisted_caller(); + fn increment() -> Weight { + Weight::from_parts(12_456_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } - #[extrinsic_call] - _(RawOrigin::Signed(caller)); + fn decrement() -> Weight { + Weight::from_parts(11_987_000, 0) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + } + ``` - // Minimal assertions -} -``` + The actual numbers in your `weights.rs` file will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} accounts for database read and write operations. ## Run Your Chain Locally -Now that you've added the pallet to your runtime, you can launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\_blank} guide. - -### Build the Production Runtime - -The `runtime-benchmarks` feature flag adds special host functions (like `ext_benchmarking_current_time` and `ext_benchmarking_get_read_and_written_keys`) that are only available in the benchmarking execution environment. These functions allow the benchmarking framework to precisely measure execution time and track storage operations. However, regular nodes don't provide these host functions, so a runtime compiled with benchmarking features will fail to start on a production node. - -Before running your chain, rebuild the runtime **without** the `runtime-benchmarks` feature: - -```bash -cargo build --release -``` - -!!! note "Build Types" - Understanding the difference between builds is critical: - - - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher` - - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your actual chain +Now that you've added the pallet to your runtime, you can follow these steps to launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\_blank}: -This produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. +1. Before running your chain, rebuild the production runtime without the `runtime-benchmarks` feature using the following command: -### Generate a Chain Specification + ```bash + cargo build --release + ``` -The chain specification defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. By generating a new chain spec with your updated runtime (now containing your benchmarked pallet), you ensure that nodes starting from this spec will use the correct version of your code with proper weight calculations. + The `runtime-benchmarks` feature flag adds special host functions that are only available in the benchmarking execution environment. A runtime compiled with benchmarking features will fail to start on a production node. -Create a new chain specification file with the updated runtime: + This build produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. -```bash -chain-spec-builder create -t development \ ---relay-chain paseo \ ---para-id 1000 \ ---runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ -named-preset development -``` + !!! note "Compare build types" + - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher`. + - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your chain in production. -This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime. +2. Generate a new chain specification file with the updated runtime using the following commands: -### Start the Parachain Node + ```bash + chain-spec-builder create -t development \ + --relay-chain paseo \ + --para-id 1000 \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ + named-preset development + ``` -Launch the parachain using the Polkadot Omni Node with the generated chain specification by running the following command: + This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime, which defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. Generating this new chain spec with your updated runtime ensures nodes starting from this spec will use the correct version of your code with proper weight calculations. -```bash -polkadot-omni-node --chain ./chain_spec.json --dev -``` +3. Start the parachain node using the Polkadot Omni Node with the generated chain specification by running the following command: -The node will start and display initialization information including: + ```bash + polkadot-omni-node --chain ./chain_spec.json --dev + ``` -- The chain specification name -- The node identity and peer ID -- Database location -- Network endpoints (JSON-RPC and Prometheus) + The node will start and display initialization information, including: -### Verify Block Production + - The chain specification name + - The node identity and peer ID + - Database location + - Network endpoints (JSON-RPC and Prometheus) -Once the node is running, you should see log messages indicating successful block production: +4. Once the node is running, you will see log messages confirming successful production of blocks similar to the following: -``` -[Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc) -[Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ... -[Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2) -[Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ... -[Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32) -``` +
+ polkadot-omni-node --chain ./chain_spec.json --dev + [Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc) + [Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ... + [Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2) + [Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ... + [Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32) + +
-The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. + The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. ## Related Resources diff --git a/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md b/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md index b26d07b1f..06a497f7c 100644 --- a/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md +++ b/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md @@ -1,11 +1,11 @@ --- -title: Pallet Testing +title: Unit Test Pallets description: Learn how to efficiently test pallets in the Polkadot SDK, ensuring the reliability and security of your pallets operations. categories: Parachains url: https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/ --- -# Pallet Testing +# Unit Test Pallets ## Introduction diff --git a/llms-full.jsonl b/llms-full.jsonl index 5f037cdff..9c1a59263 100644 --- a/llms-full.jsonl +++ b/llms-full.jsonl @@ -268,44 +268,24 @@ {"page_id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "page_title": "Add Pallets to the Runtime", "index": 3, "depth": 2, "title": "Recompile the Runtime", "anchor": "recompile-the-runtime", "start_char": 10415, "end_char": 10864, "estimated_token_count": 89, "token_estimator": "heuristic-v1", "text": "## Recompile the Runtime\n\nAfter adding and configuring your pallets in the runtime, the next step is to ensure everything is set up correctly. To do this, recompile the runtime with the following command (make sure you're in the project's root directory):\n\n```bash\ncargo build --release\n```\n\nThis command ensures the runtime compiles without errors, validates the pallet configurations, and prepares the build for subsequent testing or deployment."} {"page_id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "page_title": "Add Pallets to the Runtime", "index": 4, "depth": 2, "title": "Run Your Chain Locally", "anchor": "run-your-chain-locally", "start_char": 10864, "end_char": 12339, "estimated_token_count": 365, "token_estimator": "heuristic-v1", "text": "## Run Your Chain Locally\n\nLaunch your parachain locally and start producing blocks:\n\n!!!tip\n Generated chain TestNet specifications include development accounts \"Alice\" and \"Bob.\" These accounts are pre-funded with native parachain currency, allowing you to sign and send TestNet transactions. Take a look at the [Polkadot.js Accounts section](https://polkadot.js.org/apps/#/accounts){target=\\_blank} to view the development accounts for your chain.\n\n1. Create a new chain specification file with the updated runtime:\n\n ```bash\n chain-spec-builder create -t development \\\n --relay-chain paseo \\\n --para-id 1000 \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \\\n named-preset development\n ```\n\n2. Start the omni node with the generated chain specification:\n\n ```bash\n polkadot-omni-node --chain ./chain_spec.json --dev\n ```\n\n3. Verify you can interact with the new pallets using the [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/extrinsics){target=\\_blank} interface. Navigate to the **Extrinsics** tab and check that you can see both pallets:\n\n - Utility pallet\n\n ![](/images/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/add-pallets-to-runtime-01.webp)\n \n\n - Custom pallet\n\n ![](/images/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/add-pallets-to-runtime-02.webp)"} {"page_id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "page_title": "Add Pallets to the Runtime", "index": 5, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 12339, "end_char": 13091, "estimated_token_count": 183, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Tutorial __Deploy on Paseo TestNet__\n\n ---\n\n Deploy your Polkadot SDK blockchain on Paseo! Follow this step-by-step guide for a seamless journey to a successful TestNet deployment.\n\n [:octicons-arrow-right-24: Get Started](/tutorials/polkadot-sdk/parachains/zero-to-hero/deploy-to-testnet/)\n\n- Tutorial __Pallet Benchmarking (Optional)__\n\n ---\n\n Discover how to measure extrinsic costs and assign precise weights to optimize your pallet for accurate fees and runtime performance.\n\n [:octicons-arrow-right-24: Get Started](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-benchmarking/)\n\n
"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 0, "end_char": 868, "estimated_token_count": 183, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nBenchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.\n\nThis guide continues the pallet development series, building on the [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet), [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime), and [Test Your Pallet](/parachains/customize-runtime/pallet-development/pallet-testing) tutorials. You'll learn how to benchmark the counter pallet extrinsics and integrate the generated weights into your runtime."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 868, "end_char": 1071, "estimated_token_count": 32, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have:\n\n- Completed the previous pallet development tutorials\n- Basic understanding of computational complexity\n- Familiarity with Rust's testing framework"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 2, "depth": 2, "title": "Why Benchmark?", "anchor": "why-benchmark", "start_char": 1071, "end_char": 1723, "estimated_token_count": 109, "token_estimator": "heuristic-v1", "text": "## Why Benchmark?\n\nIn blockchain systems, every operation consumes resources. Weight is the mechanism Polkadot SDK uses to measure and limit resource consumption. Without accurate weights:\n\n- **Security Risk**: Malicious actors could submit transactions that consume excessive resources, blocking legitimate transactions or halting the chain\n- **Inefficiency**: Over-estimated weights waste block space and reduce throughput\n- **User Experience**: Inaccurate weights lead to incorrect fee calculations\n\nBenchmarking provides empirical measurements of your extrinsics under various conditions, ensuring weights reflect real-world resource consumption."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 3, "depth": 2, "title": "Understanding Weights", "anchor": "understanding-weights", "start_char": 1723, "end_char": 2778, "estimated_token_count": 255, "token_estimator": "heuristic-v1", "text": "## Understanding Weights\n\nThe [weight system](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\\_blank} serves multiple purposes:\n\n- **DoS Protection**: Limits the computational work per block, preventing attackers from overwhelming the network\n- **Fee Calculation**: Determines transaction fees based on actual resource usage\n- **Block Production**: Helps block authors maximize throughput while staying within block limits\n\nWeights are expressed as [`Weight::from_parts(ref_time, proof_size)`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.from_parts){target=\\_blank} where:\n\n- [`ref_time`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.ref_time){target=\\_blank}: Computational time measured in picoseconds\n- [`proof_size`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html#method.proof_size){target=\\_blank}: Storage proof size in bytes"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 4, "depth": 2, "title": "Step 1: Create the Benchmarking Module", "anchor": "step-1-create-the-benchmarking-module", "start_char": 2778, "end_char": 5474, "estimated_token_count": 728, "token_estimator": "heuristic-v1", "text": "## Step 1: Create the Benchmarking Module\n\nCreate a new file `benchmarking.rs` in your pallet's `src` directory. This module will contain all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\\_blank} for your pallet:\n\n```rust title=\"pallets/pallet-custom/src/benchmarking.rs\"\n#![cfg(feature = \"runtime-benchmarks\")]\n\nuse super::*;\nuse frame::deps::frame_benchmarking::v2::*;\nuse frame::benchmarking::prelude::RawOrigin;\n\n#[benchmarks]\nmod benchmarks {\n use super::*;\n\n #[benchmark]\n fn set_counter_value() {\n let new_value: u32 = 100;\n\n #[extrinsic_call]\n _(RawOrigin::Root, new_value);\n\n assert_eq!(CounterValue::::get(), new_value);\n }\n\n #[benchmark]\n fn increment() {\n let caller: T::AccountId = whitelisted_caller();\n let amount: u32 = 50;\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller.clone()), amount);\n\n assert_eq!(CounterValue::::get(), amount);\n assert_eq!(UserInteractions::::get(caller), 1);\n }\n\n #[benchmark]\n fn decrement() {\n // First set the counter to a non-zero value\n CounterValue::::put(100);\n\n let caller: T::AccountId = whitelisted_caller();\n let amount: u32 = 30;\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller.clone()), amount);\n\n assert_eq!(CounterValue::::get(), 70);\n assert_eq!(UserInteractions::::get(caller), 1);\n }\n\n impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);\n}\n```\n\n**Key components:**\n\n- **`#![cfg(feature = \"runtime-benchmarks\")]`**: Ensures benchmarking code only compiles when the feature is enabled\n- **[`#[benchmarks]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmarks.html){target=\\_blank}**: Marks the module containing benchmark definitions\n- **[`#[benchmark]` macro](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.benchmark.html){target=\\_blank}**: Defines individual benchmark functions\n- **[`#[extrinsic_call]`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/attr.extrinsic_call.html){target=\\_blank}**: Marks the actual extrinsic invocation to measure\n- **[`whitelisted_caller()`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/fn.whitelisted_caller.html){target=\\_blank}**: Generates a funded account for benchmarking\n- **[`impl_benchmark_test_suite!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.impl_benchmark_test_suite.html){target=\\_blank}**: Generates test functions to verify benchmarks work correctly"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 5, "depth": 2, "title": "Step 2: Define the Weight Trait", "anchor": "step-2-define-the-weight-trait", "start_char": 5474, "end_char": 6891, "estimated_token_count": 297, "token_estimator": "heuristic-v1", "text": "## Step 2: Define the Weight Trait\n\nThe [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. This enables you to use placeholder weights during development and testing, then switch to auto-generated benchmarked weights in production without modifying the pallet code itself.\n\nAdd a `weights` module to your pallet that defines the `WeightInfo` trait:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#[frame::pallet]\npub mod pallet {\n use frame::prelude::*;\n pub use weights::WeightInfo;\n\n pub mod weights {\n use frame::prelude::*;\n\n pub trait WeightInfo {\n fn set_counter_value() -> Weight;\n fn increment() -> Weight;\n fn decrement() -> Weight;\n }\n\n impl WeightInfo for () {\n fn set_counter_value() -> Weight {\n Weight::from_parts(10_000, 0)\n }\n fn increment() -> Weight {\n Weight::from_parts(15_000, 0)\n }\n fn decrement() -> Weight {\n Weight::from_parts(15_000, 0)\n }\n }\n }\n\n // ... rest of pallet\n}\n```\n\nThe `()` implementation provides placeholder weights for development. Later, this will be replaced with auto-generated weights from benchmarking."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 6, "depth": 2, "title": "Step 3: Add WeightInfo to Config", "anchor": "step-3-add-weightinfo-to-config", "start_char": 6891, "end_char": 7656, "estimated_token_count": 169, "token_estimator": "heuristic-v1", "text": "## Step 3: Add WeightInfo to Config\n\nBy making `WeightInfo` an associated type in the `Config` trait, you allow each runtime that uses your pallet to specify which weight implementation to use. Different deployment environments (testnets, production chains, or different hardware configurations) may have different performance characteristics and can use different weight calculations.\n\nUpdate your pallet's `Config` trait to include `WeightInfo`:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#[pallet::config]\npub trait Config: frame_system::Config {\n type RuntimeEvent: From> + IsType<::RuntimeEvent>;\n\n #[pallet::constant]\n type CounterMaxValue: Get;\n\n type WeightInfo: weights::WeightInfo;\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 7, "depth": 2, "title": "Step 4: Update Extrinsic Weight Annotations", "anchor": "step-4-update-extrinsic-weight-annotations", "start_char": 7656, "end_char": 8833, "estimated_token_count": 290, "token_estimator": "heuristic-v1", "text": "## Step 4: Update Extrinsic Weight Annotations\n\nBy calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. This allows you to easily switch between placeholder weights for testing and benchmarked weights for production without changing any pallet code.\n\nReplace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#[pallet::call]\nimpl Pallet {\n #[pallet::call_index(0)]\n #[pallet::weight(T::WeightInfo::set_counter_value())]\n pub fn set_counter_value(origin: OriginFor, new_value: u32) -> DispatchResult {\n // ... implementation\n }\n\n #[pallet::call_index(1)]\n #[pallet::weight(T::WeightInfo::increment())]\n pub fn increment(origin: OriginFor, amount: u32) -> DispatchResult {\n // ... implementation\n }\n\n #[pallet::call_index(2)]\n #[pallet::weight(T::WeightInfo::decrement())]\n pub fn decrement(origin: OriginFor, amount: u32) -> DispatchResult {\n // ... implementation\n }\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 8, "depth": 2, "title": "Step 5: Include the Benchmarking Module", "anchor": "step-5-include-the-benchmarking-module", "start_char": 8833, "end_char": 9453, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Step 5: Include the Benchmarking Module\n\nThe `#[cfg(feature = \"runtime-benchmarks\")]` attribute ensures that benchmarking code is only compiled when explicitly needed. This keeps your production runtime lean by excluding benchmarking infrastructure from normal builds, as it's only needed when generating weights.\n\nAt the top of your `lib.rs`, add the module declaration:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#![cfg_attr(not(feature = \"std\"), no_std)]\n\nextern crate alloc;\nuse alloc::vec::Vec;\n\npub use pallet::*;\n\n#[cfg(feature = \"runtime-benchmarks\")]\nmod benchmarking;\n\n// ... rest of the pallet\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 9, "depth": 2, "title": "Step 6: Configure Pallet Dependencies", "anchor": "step-6-configure-pallet-dependencies", "start_char": 9453, "end_char": 10350, "estimated_token_count": 212, "token_estimator": "heuristic-v1", "text": "## Step 6: Configure Pallet Dependencies\n\nThe feature flag system in Cargo allows you to conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds.\n\nUpdate your pallet's `Cargo.toml` to enable the benchmarking feature:\n\n```toml title=\"pallets/pallet-custom/Cargo.toml\"\n[dependencies]\ncodec = { features = [\"derive\"], workspace = true }\nscale-info = { features = [\"derive\"], workspace = true }\nframe = { features = [\"experimental\", \"runtime\"], workspace = true }\n\n[features]\ndefault = [\"std\"]\nruntime-benchmarks = [\n \"frame/runtime-benchmarks\",\n]\nstd = [\n \"codec/std\",\n \"scale-info/std\",\n \"frame/std\",\n]\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 10, "depth": 2, "title": "Step 7: Update Mock Runtime", "anchor": "step-7-update-mock-runtime", "start_char": 10350, "end_char": 10898, "estimated_token_count": 117, "token_estimator": "heuristic-v1", "text": "## Step 7: Update Mock Runtime\n\nIn your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo` since unit tests focus on verifying functional correctness rather than performance characteristics. This keeps tests fast and focused on validating logic.\n\nAdd the `WeightInfo` type to your test configuration in `mock.rs`:\n\n```rust title=\"pallets/pallet-custom/src/mock.rs\"\nimpl pallet_custom::Config for Test {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n type WeightInfo = ();\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 11, "depth": 2, "title": "Step 8: Configure Runtime Benchmarking", "anchor": "step-8-configure-runtime-benchmarking", "start_char": 10898, "end_char": 11085, "estimated_token_count": 31, "token_estimator": "heuristic-v1", "text": "## Step 8: Configure Runtime Benchmarking\n\nTo execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. This involves three configuration steps:"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 12, "depth": 3, "title": "Update Runtime Cargo.toml", "anchor": "update-runtime-cargotoml", "start_char": 11085, "end_char": 11652, "estimated_token_count": 137, "token_estimator": "heuristic-v1", "text": "### Update Runtime Cargo.toml\n\nWhen you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included.\n\nAdd your pallet to the runtime's `runtime-benchmarks` feature in `runtime/Cargo.toml`:\n\n```toml title=\"runtime/Cargo.toml\"\nruntime-benchmarks = [\n \"cumulus-pallet-parachain-system/runtime-benchmarks\",\n \"hex-literal\",\n \"pallet-parachain-template/runtime-benchmarks\",\n \"polkadot-sdk/runtime-benchmarks\",\n \"pallet-custom/runtime-benchmarks\",\n]\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 13, "depth": 3, "title": "Update Runtime Configuration", "anchor": "update-runtime-configuration", "start_char": 11652, "end_char": 12130, "estimated_token_count": 103, "token_estimator": "heuristic-v1", "text": "### Update Runtime Configuration\n\nStart with the placeholder implementation during development. After successfully running benchmarks and generating the weights file, you'll update this to use the benchmarked weights.\n\nIn `runtime/src/configs/mod.rs`, add the `WeightInfo` type:\n\n```rust title=\"runtime/src/configs/mod.rs\"\nimpl pallet_custom::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n type WeightInfo = ();\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 14, "depth": 3, "title": "Register Benchmarks", "anchor": "register-benchmarks", "start_char": 12130, "end_char": 12611, "estimated_token_count": 104, "token_estimator": "heuristic-v1", "text": "### Register Benchmarks\n\nThe `define_benchmarks!` macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks.\n\nAdd your pallet to the benchmark list in `runtime/src/benchmarks.rs`:\n\n```rust title=\"runtime/src/benchmarks.rs\"\npolkadot_sdk::frame_benchmarking::define_benchmarks!(\n [frame_system, SystemBench::]\n [pallet_balances, Balances]\n // ... other pallets\n [pallet_custom, CustomPallet]\n);\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 15, "depth": 2, "title": "Step 9: Run Benchmarks", "anchor": "step-9-run-benchmarks", "start_char": 12611, "end_char": 12638, "estimated_token_count": 7, "token_estimator": "heuristic-v1", "text": "## Step 9: Run Benchmarks"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 16, "depth": 3, "title": "Test Benchmark Compilation", "anchor": "test-benchmark-compilation", "start_char": 12638, "end_char": 13283, "estimated_token_count": 128, "token_estimator": "heuristic-v1", "text": "### Test Benchmark Compilation\n\nThe `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the full runtime.\n\nFirst, verify your benchmarks compile and run as tests:\n\n```bash\ncargo test -p pallet-custom --features runtime-benchmarks\n```\n\nYou should see your benchmark tests passing:\n\n```\ntest benchmarking::benchmarks::bench_set_counter_value ... ok\ntest benchmarking::benchmarks::bench_increment ... ok\ntest benchmarking::benchmarks::bench_decrement ... ok\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 17, "depth": 3, "title": "Build the Runtime with Benchmarks", "anchor": "build-the-runtime-with-benchmarks", "start_char": 13283, "end_char": 13996, "estimated_token_count": 132, "token_estimator": "heuristic-v1", "text": "### Build the Runtime with Benchmarks\n\nThis build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. This is a special build used only for benchmarking - you'll create a different build later for actually running your chain.\n\nCompile the runtime with benchmarking enabled to generate the WASM binary:\n\n```bash\ncargo build --release --features runtime-benchmarks\n```\n\nThis produces the runtime WASM file needed for benchmarking, typically located at:\n```\ntarget/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 18, "depth": 3, "title": "Install the Benchmarking Tool", "anchor": "install-the-benchmarking-tool", "start_char": 13996, "end_char": 14536, "estimated_token_count": 118, "token_estimator": "heuristic-v1", "text": "### Install the Benchmarking Tool\n\n[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\\_blank} is the official Polkadot SDK tool specifically designed for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system.\n\nInstall the `frame-omni-bencher` CLI tool:\n\n```bash\ncargo install frame-omni-bencher --locked\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 19, "depth": 3, "title": "Download the Weight Template", "anchor": "download-the-weight-template", "start_char": 14536, "end_char": 15301, "estimated_token_count": 155, "token_estimator": "heuristic-v1", "text": "### Download the Weight Template\n\nThe weight template is a Handlebars file that transforms raw benchmark data into a properly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow Polkadot SDK conventions and include all necessary metadata like benchmark execution parameters, storage operation counts, and hardware information.\n\nDownload the official weight template file:\n\n```bash\ncurl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \\\n--output ./pallets/pallet-custom/frame-weight-template.hbs\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 20, "depth": 3, "title": "Hardware Requirements for Benchmarking", "anchor": "hardware-requirements-for-benchmarking", "start_char": 15301, "end_char": 17789, "estimated_token_count": 432, "token_estimator": "heuristic-v1", "text": "### Hardware Requirements for Benchmarking\n\n!!! warning \"Critical: Benchmark on Production-Like Hardware\"\n Benchmarks must be executed on hardware similar to what will run your chain in production. Weight measurements are hardware-dependent, and benchmarking on different hardware can lead to dangerous under-estimation or wasteful over-estimation of weights.\n\nWeights represent the actual computational time and resources consumed by extrinsics. These measurements vary significantly across different hardware configurations:\n\n- **CPU Performance**: Different processors execute instructions at different speeds. A faster development laptop will produce lower weight values than production server hardware\n- **Storage Speed**: Database read/write performance varies between NVMe SSDs, SATA SSDs, and HDDs, affecting storage-related weights\n- **Memory Bandwidth**: RAM speed impacts how quickly data can be accessed during execution\n- **CPU Cache**: Cache size and architecture differences affect repeated operations\n\nBenchmarking on faster hardware than production leads to under-estimated weights - attackers could submit extrinsics that consume more resources than the weights suggest, potentially causing blocks to take longer than expected to produce or even halting the chain. Conversely, benchmarking on slower hardware creates over-estimated weights, resulting in unnecessarily high transaction fees and wasted block capacity.\n\n**Best practices:**\n\n1. **Match production specifications**: If your chain will run on specific validator hardware, benchmark on identical or very similar machines\n2. **Use reference hardware**: The Polkadot ecosystem often uses standardized reference hardware specifications for consistency. Consider following these standards if your chain will connect to Polkadot or Kusama\n3. **Dedicated benchmarking environment**: Run benchmarks on a machine without other heavy processes to ensure consistent measurements\n4. **Document your hardware**: The generated weight files include hardware information in comments. Review this to ensure it matches your production environment\n5. **Re-benchmark when hardware changes**: If your validator hardware specifications change, re-run benchmarks and update weights\n\nFor development and testing purposes, you can run benchmarks on any available hardware to verify that your benchmark functions work correctly. However, before deploying to production, always re-run benchmarks on production-equivalent hardware."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 21, "depth": 3, "title": "Execute Benchmarks", "anchor": "execute-benchmarks", "start_char": 17789, "end_char": 19210, "estimated_token_count": 294, "token_estimator": "heuristic-v1", "text": "### Execute Benchmarks\n\nBenchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking the WASM ensures your weight measurements reflect real-world conditions.\n\nRun benchmarks for your pallet to generate weight files:\n\n```bash\nframe-omni-bencher v1 benchmark pallet \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \\\n --pallet pallet_custom \\\n --extrinsic \"\" \\\n --template ./pallets/pallet-custom/frame-weight-template.hbs \\\n --output ./pallets/pallet-custom/src/weights.rs\n```\n\n**Command breakdown:**\n\n- `v1`: Specifies the benchmarking framework version (v2 API)\n- `benchmark pallet`: Subcommand indicating you want to benchmark pallet extrinsics\n- `--runtime`: Path to the compiled WASM runtime file that includes your pallet and benchmarks\n- `--pallet pallet_custom`: Name of the pallet to benchmark (must match the name used in `define_benchmarks!`)\n- `--extrinsic \"\"`: Empty string benchmarks all extrinsics in the pallet; you can specify a single extrinsic name to benchmark only that one\n- `--template`: Path to the Handlebars template that formats the output\n- `--output`: Destination file path for the generated weights module"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 22, "depth": 3, "title": "Advanced Options", "anchor": "advanced-options", "start_char": 19210, "end_char": 20357, "estimated_token_count": 242, "token_estimator": "heuristic-v1", "text": "### Advanced Options\n\nYou can customize benchmark execution with additional parameters for more detailed measurements:\n\n```bash\nframe-omni-bencher v1 benchmark pallet \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \\\n --pallet pallet_custom \\\n --extrinsic \"\" \\\n --steps 50 \\\n --repeat 20 \\\n --template ./pallets/pallet-custom/frame-weight-template.hbs \\\n --output ./pallets/pallet-custom/src/weights.rs\n```\n\n**Additional parameters:**\n\n- `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time\n- `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise and providing more reliable weight estimates\n- `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution\n- `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 23, "depth": 2, "title": "Step 10: Use Generated Weights", "anchor": "step-10-use-generated-weights", "start_char": 20357, "end_char": 21332, "estimated_token_count": 168, "token_estimator": "heuristic-v1", "text": "## Step 10: Use Generated Weights\n\nAfter running benchmarks, a `weights.rs` file is generated containing measured weights. The generated weights are based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements. Estimates or placeholder values cannot capture these nuances and will either waste block space (over-estimation) or create security risks (under-estimation).\n\nThe file includes:\n\n- Detailed documentation about the benchmark execution environment (date, hardware, parameters)\n- The `WeightInfo` trait definition matching your benchmark functions\n- `SubstrateWeight` implementation with measured weights from your benchmarks\n- Database read/write costs calculated based on observed storage operations\n- Component complexity annotations for variable inputs (if you use linear components)\n- A fallback `()` implementation for testing environments"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 24, "depth": 3, "title": "Integrate the Generated Weights", "anchor": "integrate-the-generated-weights", "start_char": 21332, "end_char": 22065, "estimated_token_count": 189, "token_estimator": "heuristic-v1", "text": "### Integrate the Generated Weights\n\nUnlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during normal operation to calculate transaction fees and enforce block limits.\n\nAdd the weights module to your pallet's `lib.rs`:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#![cfg_attr(not(feature = \"std\"), no_std)]\n\nextern crate alloc;\nuse alloc::vec::Vec;\n\npub use pallet::*;\n\n#[cfg(feature = \"runtime-benchmarks\")]\nmod benchmarking;\n\npub mod weights;\n\n#[frame::pallet]\npub mod pallet {\n use super::*;\n use frame::prelude::*;\n use crate::weights::WeightInfo;\n // ... rest of pallet\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 25, "depth": 3, "title": "Update Runtime Configuration", "anchor": "update-runtime-configuration-2", "start_char": 22065, "end_char": 22694, "estimated_token_count": 121, "token_estimator": "heuristic-v1", "text": "### Update Runtime Configuration\n\nThis change activates your benchmarked weights in the production runtime. Now when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits.\n\nUpdate your runtime configuration to use the generated weights instead of the placeholder `()` implementation:\n\n```rust title=\"runtime/src/configs/mod.rs\"\nimpl pallet_custom::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n type WeightInfo = pallet_custom::weights::SubstrateWeight;\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 26, "depth": 3, "title": "Example Generated Weight File", "anchor": "example-generated-weight-file", "start_char": 22694, "end_char": 24357, "estimated_token_count": 450, "token_estimator": "heuristic-v1", "text": "### Example Generated Weight File\n\nThe generated `weights.rs` file will look similar to this:\n\n```rust title=\"pallets/pallet-custom/src/weights.rs\"\n//! Autogenerated weights for `pallet_custom`\n//!\n//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0\n//! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`\n\n#![cfg_attr(rustfmt, rustfmt_skip)]\n#![allow(unused_parens)]\n#![allow(unused_imports)]\n#![allow(missing_docs)]\n\nuse frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};\nuse core::marker::PhantomData;\n\npub trait WeightInfo {\n fn set_counter_value() -> Weight;\n fn increment() -> Weight;\n fn decrement() -> Weight;\n}\n\npub struct SubstrateWeight(PhantomData);\nimpl WeightInfo for SubstrateWeight {\n fn set_counter_value() -> Weight {\n Weight::from_parts(8_234_000, 0)\n .saturating_add(T::DbWeight::get().reads(1))\n .saturating_add(T::DbWeight::get().writes(1))\n }\n\n fn increment() -> Weight {\n Weight::from_parts(12_456_000, 0)\n .saturating_add(T::DbWeight::get().reads(2))\n .saturating_add(T::DbWeight::get().writes(2))\n }\n\n fn decrement() -> Weight {\n Weight::from_parts(11_987_000, 0)\n .saturating_add(T::DbWeight::get().reads(2))\n .saturating_add(T::DbWeight::get().writes(2))\n }\n}\n```\n\n**Note**: The actual numbers will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\\_blank} accounts for database read and write operations."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 27, "depth": 2, "title": "Benchmarking Best Practices", "anchor": "benchmarking-best-practices", "start_char": 24357, "end_char": 24389, "estimated_token_count": 5, "token_estimator": "heuristic-v1", "text": "## Benchmarking Best Practices"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 28, "depth": 3, "title": "1. Test Worst-Case Scenarios", "anchor": "1-test-worst-case-scenarios", "start_char": 24389, "end_char": 25006, "estimated_token_count": 138, "token_estimator": "heuristic-v1", "text": "### 1. Test Worst-Case Scenarios\n\nBenchmarks should always measure maximum possible resource consumption. If you benchmark average or best-case scenarios, malicious users could craft transactions that hit worst-case paths in your code, consuming more resources than the weights indicate and potentially slowing down or halting block production.\n\n```rust\n#[benchmark]\nfn complex_operation() {\n // Set up worst-case storage state\n for i in 0..100 {\n SomeStorage::::insert(i, vec![0u8; 1000]);\n }\n\n let caller = whitelisted_caller();\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller));\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 29, "depth": 3, "title": "2. Use Linear Components for Variable Complexity", "anchor": "2-use-linear-components-for-variable-complexity", "start_char": 25006, "end_char": 25882, "estimated_token_count": 206, "token_estimator": "heuristic-v1", "text": "### 2. Use Linear Components for Variable Complexity\n\nMany extrinsics have variable costs depending on input parameters. [Linear components](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/trait.BenchmarkingSetup.html){target=\\_blank} tell the benchmarking framework to test your extrinsic with different values of `n`, measure the execution time for each, and calculate a formula like `Weight = base_weight + (n * per_item_weight)`. This produces dynamic weights that accurately reflect the actual work being done.\n\nWhen extrinsic complexity depends on input size, use linear components:\n\n```rust title=\"pallets/pallet-custom/src/benchmarking.rs\"\n#[benchmark]\nfn process_items(n: Linear<0, 100>) {\n let caller = whitelisted_caller();\n let items: Vec = (0..n).collect();\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller), items);\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 30, "depth": 3, "title": "3. Verify Results", "anchor": "3-verify-results", "start_char": 25882, "end_char": 26518, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "### 3. Verify Results\n\nAssertions ensure that your benchmark is actually testing the code path you think it's testing. If your extrinsic fails silently or takes an early return, the benchmark would measure the wrong scenario and produce inaccurate weights.\n\nAlways assert the expected state after extrinsic execution:\n\n```rust title=\"pallets/pallet-custom/src/benchmarking.rs\"\n#[benchmark]\nfn my_extrinsic() {\n let caller = whitelisted_caller();\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller.clone()));\n\n // Verify the extrinsic had the expected effect\n assert_eq!(MyStorage::::get(&caller), expected_value);\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 31, "depth": 3, "title": "4. Minimize Setup Code", "anchor": "4-minimize-setup-code", "start_char": 26518, "end_char": 27092, "estimated_token_count": 120, "token_estimator": "heuristic-v1", "text": "### 4. Minimize Setup Code\n\nWhile the benchmarking framework tries to isolate the extrinsic execution, excessive setup code can add noise to measurements. More importantly, setup code that doesn't reflect real-world pre-conditions can lead to benchmarking unrealistic scenarios.\n\nOnly include necessary setup in benchmarks:\n\n```rust title=\"pallets/pallet-custom/src/benchmarking.rs\"\n#[benchmark]\nfn efficient_benchmark() {\n // Minimal setup\n let caller = whitelisted_caller();\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller));\n\n // Minimal assertions\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 32, "depth": 2, "title": "Run Your Chain Locally", "anchor": "run-your-chain-locally", "start_char": 27092, "end_char": 27618, "estimated_token_count": 141, "token_estimator": "heuristic-v1", "text": "## Run Your Chain Locally\n\nNow that you've added the pallet to your runtime, you can launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\\_blank}. For instructions on setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\\_blank}, refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\\_blank} guide."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 33, "depth": 3, "title": "Build the Production Runtime", "anchor": "build-the-production-runtime", "start_char": 27618, "end_char": 28821, "estimated_token_count": 223, "token_estimator": "heuristic-v1", "text": "### Build the Production Runtime\n\nThe `runtime-benchmarks` feature flag adds special host functions (like `ext_benchmarking_current_time` and `ext_benchmarking_get_read_and_written_keys`) that are only available in the benchmarking execution environment. These functions allow the benchmarking framework to precisely measure execution time and track storage operations. However, regular nodes don't provide these host functions, so a runtime compiled with benchmarking features will fail to start on a production node.\n\nBefore running your chain, rebuild the runtime **without** the `runtime-benchmarks` feature:\n\n```bash\ncargo build --release\n```\n\n!!! note \"Build Types\"\n Understanding the difference between builds is critical:\n\n - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher`\n - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your actual chain\n\nThis produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 34, "depth": 3, "title": "Generate a Chain Specification", "anchor": "generate-a-chain-specification", "start_char": 28821, "end_char": 29655, "estimated_token_count": 165, "token_estimator": "heuristic-v1", "text": "### Generate a Chain Specification\n\nThe chain specification defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. By generating a new chain spec with your updated runtime (now containing your benchmarked pallet), you ensure that nodes starting from this spec will use the correct version of your code with proper weight calculations.\n\nCreate a new chain specification file with the updated runtime:\n\n```bash\nchain-spec-builder create -t development \\\n--relay-chain paseo \\\n--para-id 1000 \\\n--runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \\\nnamed-preset development\n```\n\nThis command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 35, "depth": 3, "title": "Start the Parachain Node", "anchor": "start-the-parachain-node", "start_char": 29655, "end_char": 30074, "estimated_token_count": 84, "token_estimator": "heuristic-v1", "text": "### Start the Parachain Node\n\nLaunch the parachain using the Polkadot Omni Node with the generated chain specification by running the following command:\n\n```bash\npolkadot-omni-node --chain ./chain_spec.json --dev\n```\n\nThe node will start and display initialization information including:\n\n- The chain specification name\n- The node identity and peer ID\n- Database location\n- Network endpoints (JSON-RPC and Prometheus)"} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 36, "depth": 3, "title": "Verify Block Production", "anchor": "verify-block-production", "start_char": 30074, "end_char": 30777, "estimated_token_count": 190, "token_estimator": "heuristic-v1", "text": "### Verify Block Production\n\nOnce the node is running, you should see log messages indicating successful block production:\n\n```\n[Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc)\n[Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ...\n[Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2)\n[Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ...\n[Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32)\n```\n\nThe parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\\_blank}."} -{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 37, "depth": 2, "title": "Related Resources", "anchor": "related-resources", "start_char": 30777, "end_char": 31318, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Related Resources\n\n- [FRAME Benchmarking Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/index.html){target=\\_blank}\n- [Weight Struct Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html){target=\\_blank}\n- [Benchmarking v2 API](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\\_blank}\n- [frame-omni-bencher Tool](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\\_blank}"} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 0, "end_char": 631, "estimated_token_count": 119, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nBenchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.\n\nThis guide continues building on what you've learned through the pallet development series. You'll learn how to benchmark the custom counter pallet extrinsics and integrate the generated weights into your runtime."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 631, "end_char": 1611, "estimated_token_count": 262, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have:\n\n- Completed the previous pallet development tutorials:\n - [Create a Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\\_blank}\n - [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\\_blank}\n - [Unit Test Pallets](/parachains/customize-runtime/pallet-development/pallet-testing/){target=\\_blank}\n- Basic understanding of [computational complexity](https://en.wikipedia.org/wiki/Computational_complexity){target=\\_blank}.\n- Familiarity with [Rust's testing framework](https://doc.rust-lang.org/book/ch11-00-testing.html){target=\\_blank}.\n- Familiarity setting up the Polkadot Omni Node and [Polkadot Chain Spec Builder](https://crates.io/crates/staging-chain-spec-builder){target=\\_blank}. Refer to the [Set Up a Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\\_blank} guide for instructions if needed."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 2, "depth": 2, "title": "Create the Benchmarking Module", "anchor": "create-the-benchmarking-module", "start_char": 1611, "end_char": 3218, "estimated_token_count": 430, "token_estimator": "heuristic-v1", "text": "## Create the Benchmarking Module\n\nCreate a new file `benchmarking.rs` in your pallet's `src` directory and add the following code:\n\n```rust title=\"pallets/pallet-custom/src/benchmarking.rs\"\n#![cfg(feature = \"runtime-benchmarks\")]\n\nuse super::*;\nuse frame::deps::frame_benchmarking::v2::*;\nuse frame::benchmarking::prelude::RawOrigin;\n\n#[benchmarks]\nmod benchmarks {\n use super::*;\n\n #[benchmark]\n fn set_counter_value() {\n let new_value: u32 = 100;\n\n #[extrinsic_call]\n _(RawOrigin::Root, new_value);\n\n assert_eq!(CounterValue::::get(), new_value);\n }\n\n #[benchmark]\n fn increment() {\n let caller: T::AccountId = whitelisted_caller();\n let amount: u32 = 50;\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller.clone()), amount);\n\n assert_eq!(CounterValue::::get(), amount);\n assert_eq!(UserInteractions::::get(caller), 1);\n }\n\n #[benchmark]\n fn decrement() {\n // First, set the counter to a non-zero value\n CounterValue::::put(100);\n\n let caller: T::AccountId = whitelisted_caller();\n let amount: u32 = 30;\n\n #[extrinsic_call]\n _(RawOrigin::Signed(caller.clone()), amount);\n\n assert_eq!(CounterValue::::get(), 70);\n assert_eq!(UserInteractions::::get(caller), 1);\n }\n\n impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);\n}\n```\n\nThis module contains all the [benchmarking definitions](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\\_blank} for your pallet."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 3, "depth": 2, "title": "Define the Weight Trait", "anchor": "define-the-weight-trait", "start_char": 3218, "end_char": 4168, "estimated_token_count": 201, "token_estimator": "heuristic-v1", "text": "## Define the Weight Trait\n\nAdd a `weights` module to your pallet that defines the `WeightInfo` trait using the following code:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#[frame::pallet]\npub mod pallet {\n use frame::prelude::*;\n pub use weights::WeightInfo;\n\n pub mod weights {\n use frame::prelude::*;\n\n pub trait WeightInfo {\n fn set_counter_value() -> Weight;\n fn increment() -> Weight;\n fn decrement() -> Weight;\n }\n\n impl WeightInfo for () {\n fn set_counter_value() -> Weight {\n Weight::from_parts(10_000, 0)\n }\n fn increment() -> Weight {\n Weight::from_parts(15_000, 0)\n }\n fn decrement() -> Weight {\n Weight::from_parts(15_000, 0)\n }\n }\n }\n\n // ... rest of pallet\n}\n```\n\nThe `()` implementation provides placeholder weights for development."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 4, "depth": 2, "title": "Add WeightInfo to Config", "anchor": "add-weightinfo-to-config", "start_char": 4168, "end_char": 4994, "estimated_token_count": 200, "token_estimator": "heuristic-v1", "text": "## Add WeightInfo to Config \n\nUpdate your pallet's `Config` trait to include `WeightInfo` by adding the following code:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#[pallet::config]\npub trait Config: frame_system::Config {\n type RuntimeEvent: From> + IsType<::RuntimeEvent>;\n\n #[pallet::constant]\n type CounterMaxValue: Get;\n\n type WeightInfo: weights::WeightInfo;\n}\n```\n\nThe [`WeightInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/trait.WeightInfo.html){target=\\_blank} trait provides an abstraction layer that allows weights to be swapped at runtime configuration. By making `WeightInfo` an associated type in the `Config` trait, you will enable each runtime that uses your pallet to specify which weight implementation to use."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 5, "depth": 2, "title": "Update Extrinsic Weight Annotations", "anchor": "update-extrinsic-weight-annotations", "start_char": 4994, "end_char": 6182, "estimated_token_count": 291, "token_estimator": "heuristic-v1", "text": "## Update Extrinsic Weight Annotations\n\nReplace the placeholder weights in your extrinsics with calls to the `WeightInfo` trait by adding the following code:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#[pallet::call]\nimpl Pallet {\n #[pallet::call_index(0)]\n #[pallet::weight(T::WeightInfo::set_counter_value())]\n pub fn set_counter_value(origin: OriginFor, new_value: u32) -> DispatchResult {\n // ... implementation\n }\n\n #[pallet::call_index(1)]\n #[pallet::weight(T::WeightInfo::increment())]\n pub fn increment(origin: OriginFor, amount: u32) -> DispatchResult {\n // ... implementation\n }\n\n #[pallet::call_index(2)]\n #[pallet::weight(T::WeightInfo::decrement())]\n pub fn decrement(origin: OriginFor, amount: u32) -> DispatchResult {\n // ... implementation\n }\n}\n```\n\nBy calling `T::WeightInfo::function_name()` instead of using hardcoded `Weight::from_parts()` values, your extrinsics automatically use whichever weight implementation is configured in the runtime. You can switch between placeholder weights for testing and benchmarked weights for production easily, without changing any pallet code."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 6, "depth": 2, "title": "Include the Benchmarking Module", "anchor": "include-the-benchmarking-module", "start_char": 6182, "end_char": 6719, "estimated_token_count": 141, "token_estimator": "heuristic-v1", "text": "## Include the Benchmarking Module\n\nAt the top of your `lib.rs`, add the module declaration by adding the following code:\n\n```rust title=\"pallets/pallet-custom/src/lib.rs\"\n#![cfg_attr(not(feature = \"std\"), no_std)]\n\nextern crate alloc;\nuse alloc::vec::Vec;\n\npub use pallet::*;\n\n#[cfg(feature = \"runtime-benchmarks\")]\nmod benchmarking;\n\n// Additional pallet code\n```\n\nThe `#[cfg(feature = \"runtime-benchmarks\")]` attribute ensures that benchmarking code is only compiled when explicitly needed to keep your production runtime efficient."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 7, "depth": 2, "title": "Configure Pallet Dependencies", "anchor": "configure-pallet-dependencies", "start_char": 6719, "end_char": 7629, "estimated_token_count": 212, "token_estimator": "heuristic-v1", "text": "## Configure Pallet Dependencies\n\nUpdate your pallet's `Cargo.toml` to enable the benchmarking feature by adding the following code:\n\n```toml title=\"pallets/pallet-custom/Cargo.toml\"\n[dependencies]\ncodec = { features = [\"derive\"], workspace = true }\nscale-info = { features = [\"derive\"], workspace = true }\nframe = { features = [\"experimental\", \"runtime\"], workspace = true }\n\n[features]\ndefault = [\"std\"]\nruntime-benchmarks = [\n \"frame/runtime-benchmarks\",\n]\nstd = [\n \"codec/std\",\n \"scale-info/std\",\n \"frame/std\",\n]\n```\n\nThe Cargo feature flag system lets you conditionally compile code based on which features are enabled. By defining a `runtime-benchmarks` feature that cascades to FRAME's benchmarking features, you create a clean way to build your pallet with or without benchmarking support, ensuring all necessary dependencies are available when needed but excluded from production builds."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 8, "depth": 2, "title": "Update Mock Runtime", "anchor": "update-mock-runtime", "start_char": 7629, "end_char": 8128, "estimated_token_count": 109, "token_estimator": "heuristic-v1", "text": "## Update Mock Runtime\n\nAdd the `WeightInfo` type to your test configuration in `mock.rs` by adding the following code:\n\n```rust title=\"pallets/pallet-custom/src/mock.rs\"\nimpl pallet_custom::Config for Test {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n type WeightInfo = ();\n}\n```\n\nIn your mock runtime for testing, use the placeholder `()` implementation of `WeightInfo`, since unit tests focus on verifying functional correctness rather than performance."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 9, "depth": 2, "title": "Configure Runtime Benchmarking", "anchor": "configure-runtime-benchmarking", "start_char": 8128, "end_char": 9970, "estimated_token_count": 390, "token_estimator": "heuristic-v1", "text": "## Configure Runtime Benchmarking\n\nTo execute benchmarks, your pallet must be integrated into the runtime's benchmarking infrastructure. Follow these steps to update the runtime configuration:\n\n1. **Update `runtime/Cargo.toml`**: Add your pallet to the runtime's `runtime-benchmarks` feature as follows:\n\n ```toml title=\"runtime/Cargo.toml\"\n runtime-benchmarks = [\n \"cumulus-pallet-parachain-system/runtime-benchmarks\",\n \"hex-literal\",\n \"pallet-parachain-template/runtime-benchmarks\",\n \"polkadot-sdk/runtime-benchmarks\",\n \"pallet-custom/runtime-benchmarks\",\n ]\n ```\n\n When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included.\n\n2. **Update runtime configuration**: Run development benchmarks with the placeholder implementation and use the resulting weights file to update benchmark weights as follows:\n\n ```rust title=\"runtime/src/configs/mod.rs\"\n impl pallet_custom::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n type WeightInfo = ();\n }\n ```\n\n3. **Register benchmarks**: Add your pallet to the benchmark list in `runtime/src/benchmarks.rs` as follows:\n\n ```rust title=\"runtime/src/benchmarks.rs\"\n polkadot_sdk::frame_benchmarking::define_benchmarks!(\n [frame_system, SystemBench::]\n [pallet_balances, Balances]\n // ... other pallets\n [pallet_custom, CustomPallet]\n );\n ```\n\n The [`define_benchmarks!`](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/macro.define_benchmarks.html){target=\\_blank} macro creates the infrastructure that allows the benchmarking CLI tool to discover and execute your pallet's benchmarks."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 10, "depth": 2, "title": "Test Benchmark Compilation", "anchor": "test-benchmark-compilation", "start_char": 9970, "end_char": 10962, "estimated_token_count": 245, "token_estimator": "heuristic-v1", "text": "## Test Benchmark Compilation\n\nRun the following command to verify your benchmarks compile and run as tests:\n\n```bash\ncargo test -p pallet-custom --features runtime-benchmarks\n```\n\nYou will see terminal output similar to the following as your benchmark tests pass:\n\n
\n cargo test -p pallet-custom --features runtime-benchmarks\n test benchmarking::benchmarks::bench_set_counter_value ... ok\n test benchmarking::benchmarks::bench_increment ... ok\n test benchmarking::benchmarks::bench_decrement ... ok\n \n
\n\nThe `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. Running these tests verifies that your benchmarks compile correctly, execute without panicking, and pass their assertions, catching issues early before building the entire runtime."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 11, "depth": 2, "title": "Build the Runtime with Benchmarks", "anchor": "build-the-runtime-with-benchmarks", "start_char": 10962, "end_char": 11657, "estimated_token_count": 123, "token_estimator": "heuristic-v1", "text": "## Build the Runtime with Benchmarks\n\nCompile the runtime with benchmarking enabled to generate the WASM binary using the following command:\n\n```bash\ncargo build --release --features runtime-benchmarks\n```\n\nThis command produces the runtime WASM file needed for benchmarking, typically located at: `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm`\n\nThe build includes all the benchmarking infrastructure and special host functions needed for measurement. The resulting WASM runtime contains your benchmark code and can communicate with the benchmarking tool's execution environment. You'll create a different build later for operating your chain in production."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 12, "depth": 2, "title": "Install the Benchmarking Tool", "anchor": "install-the-benchmarking-tool", "start_char": 11657, "end_char": 12222, "estimated_token_count": 121, "token_estimator": "heuristic-v1", "text": "## Install the Benchmarking Tool\n\nInstall the `frame-omni-bencher` CLI tool using the following command:\n\n```bash\ncargo install frame-omni-bencher --locked\n```\n\n[`frame-omni-bencher`](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\\_blank} is the official Polkadot SDK tool designed explicitly for FRAME pallet benchmarking. It provides a standardized way to execute benchmarks, measure execution times and storage operations, and generate properly formatted weight files with full integration into the FRAME weight system."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 13, "depth": 2, "title": "Download the Weight Template", "anchor": "download-the-weight-template", "start_char": 12222, "end_char": 13024, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Download the Weight Template\n\nDownload the official weight template file using the following commands:\n\n```bash\ncurl -L https://raw.githubusercontent.com/paritytech/polkadot-sdk/refs/tags/polkadot-stable2412/substrate/.maintain/frame-weight-template.hbs \\\n--output ./pallets/pallet-custom/frame-weight-template.hbs\n```\n\nThe weight template is a Handlebars file that transforms raw benchmark data into a correctly formatted Rust source file. It defines the structure of the generated `weights.rs` file, including imports, trait definitions, documentation comments, and formatting. Using the official template ensures your weight files follow the Polkadot SDK conventions and include all necessary metadata, such as benchmark execution parameters, storage operation counts, and hardware information."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 14, "depth": 2, "title": "Execute Benchmarks", "anchor": "execute-benchmarks", "start_char": 13024, "end_char": 15060, "estimated_token_count": 407, "token_estimator": "heuristic-v1", "text": "## Execute Benchmarks\n\nRun benchmarks for your pallet to generate weight files using the following commands:\n\n```bash\nframe-omni-bencher v1 benchmark pallet \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \\\n --pallet pallet_custom \\\n --extrinsic \"\" \\\n --template ./pallets/pallet-custom/frame-weight-template.hbs \\\n --output ./pallets/pallet-custom/src/weights.rs\n```\n\nBenchmarks execute against the compiled WASM runtime rather than native code because WASM is what actually runs in production on the blockchain. WASM execution can have different performance characteristics than native code due to compilation and sandboxing overhead, so benchmarking against the WASM ensures your weight measurements reflect real-world conditions.\n\n??? note \"Additional customization\"\n\n You can customize benchmark execution with additional parameters for more detailed measurements, as shown in the sample code below:\n\n ```bash\n frame-omni-bencher v1 benchmark pallet \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.wasm \\\n --pallet pallet_custom \\\n --extrinsic \"\" \\\n --steps 50 \\\n --repeat 20 \\\n --template ./pallets/pallet-custom/frame-weight-template.hbs \\\n --output ./pallets/pallet-custom/src/weights.rs\n ```\n \n - `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time.\n - `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise, and providing more reliable weight estimates.\n - `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution.\n - `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 15, "depth": 2, "title": "Use Generated Weights", "anchor": "use-generated-weights", "start_char": 15060, "end_char": 18735, "estimated_token_count": 831, "token_estimator": "heuristic-v1", "text": "## Use Generated Weights\n\nAfter running benchmarks, a `weights.rs` file is generated containing measured weights based on actual measurements of your code running on real hardware, accounting for the specific complexity of your logic, storage access patterns, and computational requirements.\n\nFollow these steps to use the generated weights with your pallet:\n\n1. Integrate the generated weights by adding the weights module to your pallet's `lib.rs` as follows:\n\n ```rust title=\"pallets/pallet-custom/src/lib.rs\"\n #![cfg_attr(not(feature = \"std\"), no_std)]\n\n extern crate alloc;\n use alloc::vec::Vec;\n\n pub use pallet::*;\n\n #[cfg(feature = \"runtime-benchmarks\")]\n mod benchmarking;\n\n pub mod weights;\n\n #[frame::pallet]\n pub mod pallet {\n use super::*;\n use frame::prelude::*;\n use crate::weights::WeightInfo;\n // ... rest of pallet\n }\n ```\n\n Unlike the benchmarking module (which is only needed when running benchmarks), the weights module must be available in all builds because the runtime needs to call the weight functions during regular operation to calculate transaction fees and enforce block limits.\n\n2. Update your runtime configuration to use the generated weights instead of the placeholder `()` implementation by adding the following code:\n\n ```rust title=\"runtime/src/configs/mod.rs\"\n impl pallet_custom::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n type WeightInfo = pallet_custom::weights::SubstrateWeight;\n }\n ```\n\n This change activates your benchmarked weights in the production runtime. Now, when users submit transactions that call your pallet's extrinsics, the runtime will use the actual measured weights to calculate fees and enforce block limits.\n\n??? code \"Example generated weight file\"\n \n The generated `weights.rs` file will look similar to this:\n\n ```rust title=\"pallets/pallet-custom/src/weights.rs\"\n //! Autogenerated weights for `pallet_custom`\n //!\n //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0\n //! DATE: 2025-01-15, STEPS: `50`, REPEAT: `20`\n\n #![cfg_attr(rustfmt, rustfmt_skip)]\n #![allow(unused_parens)]\n #![allow(unused_imports)]\n #![allow(missing_docs)]\n\n use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};\n use core::marker::PhantomData;\n\n pub trait WeightInfo {\n fn set_counter_value() -> Weight;\n fn increment() -> Weight;\n fn decrement() -> Weight;\n }\n\n pub struct SubstrateWeight(PhantomData);\n impl WeightInfo for SubstrateWeight {\n fn set_counter_value() -> Weight {\n Weight::from_parts(8_234_000, 0)\n .saturating_add(T::DbWeight::get().reads(1))\n .saturating_add(T::DbWeight::get().writes(1))\n }\n\n fn increment() -> Weight {\n Weight::from_parts(12_456_000, 0)\n .saturating_add(T::DbWeight::get().reads(2))\n .saturating_add(T::DbWeight::get().writes(2))\n }\n\n fn decrement() -> Weight {\n Weight::from_parts(11_987_000, 0)\n .saturating_add(T::DbWeight::get().reads(2))\n .saturating_add(T::DbWeight::get().writes(2))\n }\n }\n ```\n\n The actual numbers in your `weights.rs` file will vary based on your hardware and implementation complexity. The [`DbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\\_blank} accounts for database read and write operations."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 16, "depth": 2, "title": "Run Your Chain Locally", "anchor": "run-your-chain-locally", "start_char": 18735, "end_char": 22211, "estimated_token_count": 795, "token_estimator": "heuristic-v1", "text": "## Run Your Chain Locally\n\nNow that you've added the pallet to your runtime, you can follow these steps to launch your parachain locally to test the new functionality using the [Polkadot Omni Node](https://crates.io/crates/polkadot-omni-node){target=\\_blank}: \n\n1. Before running your chain, rebuild the production runtime without the `runtime-benchmarks` feature using the following command:\n\n ```bash\n cargo build --release\n ```\n\n The `runtime-benchmarks` feature flag adds special host functions that are only available in the benchmarking execution environment. A runtime compiled with benchmarking features will fail to start on a production node.\n\n This build produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`.\n\n !!! note \"Compare build types\"\n - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher`.\n - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your chain in production.\n\n2. Generate a new chain specification file with the updated runtime using the following commands:\n\n ```bash\n chain-spec-builder create -t development \\\n --relay-chain paseo \\\n --para-id 1000 \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \\\n named-preset development\n ```\n\n This command generates a chain specification file, `chain_spec.json`, for your parachain with the updated runtime, which defines the initial state and configuration of your blockchain, including the runtime WASM code, genesis storage, and network parameters. Generating this new chain spec with your updated runtime ensures nodes starting from this spec will use the correct version of your code with proper weight calculations.\n\n3. Start the parachain node using the Polkadot Omni Node with the generated chain specification by running the following command:\n\n ```bash\n polkadot-omni-node --chain ./chain_spec.json --dev\n ```\n\n The node will start and display initialization information, including:\n\n - The chain specification name\n - The node identity and peer ID\n - Database location\n - Network endpoints (JSON-RPC and Prometheus)\n\n4. Once the node is running, you will see log messages confirming successful production of blocks similar to the following:\n\n
\n polkadot-omni-node --chain ./chain_spec.json --dev\n [Parachain] 🔨 Initializing Genesis block/state (state: 0x47ce…ec8d, header-hash: 0xeb12…fecc)\n [Parachain] 🎁 Prepared block for proposing at 1 (3 ms) ...\n [Parachain] 🏆 Imported #1 (0xeb12…fecc → 0xee51…98d2)\n [Parachain] 🎁 Prepared block for proposing at 2 (3 ms) ...\n [Parachain] 🏆 Imported #2 (0xee51…98d2 → 0x35e0…cc32)\n \n
\n\n The parachain will produce new blocks every few seconds. You can now interact with your pallet's extrinsics through the JSON-RPC endpoint at `http://127.0.0.1:9944` using tools like [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\\_blank}."} +{"page_id": "parachains-customize-runtime-pallet-development-benchmark-pallet", "page_title": "Benchmark Your Pallet", "index": 17, "depth": 2, "title": "Related Resources", "anchor": "related-resources", "start_char": 22211, "end_char": 22752, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Related Resources\n\n- [FRAME Benchmarking Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/index.html){target=\\_blank}\n- [Weight Struct Documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.Weight.html){target=\\_blank}\n- [Benchmarking v2 API](https://paritytech.github.io/polkadot-sdk/master/frame_benchmarking/v2/index.html){target=\\_blank}\n- [frame-omni-bencher Tool](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\\_blank}"} {"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 26, "end_char": 847, "estimated_token_count": 167, "token_estimator": "heuristic-v1", "text": "## Introduction\n\n[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functionality with precision and flexibility. While FRAME includes a library of pre-built pallets, its true strength lies in creating custom pallets tailored to your specific needs.\n\nIn this guide, you'll learn how to build a custom counter pallet from scratch that demonstrates core pallet development concepts."} {"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 847, "end_char": 1217, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have:\n\n- [Polkadot SDK dependencies installed](/parachains/install-polkadot-sdk/){target=\\_blank}.\n- A [Polkadot SDK Parchain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/){target=\\_blank} set up locally.\n- Basic familiarity with [FRAME concepts](/parachains/customize-runtime/){target=\\_blank}."} {"page_id": "parachains-customize-runtime-pallet-development-create-a-pallet", "page_title": "Create a Custom Pallet", "index": 2, "depth": 2, "title": "Core Pallet Components", "anchor": "core-pallet-components", "start_char": 1217, "end_char": 2092, "estimated_token_count": 193, "token_estimator": "heuristic-v1", "text": "## Core Pallet Components\n\nAs you build your custom pallet, you'll work with these key sections:\n\n- **Imports and dependencies**: Bring in necessary FRAME libraries and external modules.\n- **Runtime configuration trait**: Specify types and constants for pallet-runtime interaction.\n- **Runtime events**: Define signals that communicate state changes.\n- **Runtime errors**: Define error types returned from dispatchable calls.\n- **Runtime storage**: Declare on-chain storage items for your pallet's state.\n- **Genesis configuration**: Set initial blockchain state.\n- **Dispatchable functions (extrinsics)**: Create callable functions for user interactions.\n\nFor additional macros beyond those covered here, refer to the [pallet_macros](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\\_blank} section of the Polkadot SDK Docs."} @@ -345,13 +325,13 @@ {"page_id": "parachains-customize-runtime-pallet-development-mock-runtime", "page_title": "Mock Your Runtime", "index": 10, "depth": 2, "title": "Verify Mock Compilation", "anchor": "verify-mock-compilation", "start_char": 7931, "end_char": 10853, "estimated_token_count": 564, "token_estimator": "heuristic-v1", "text": "## Verify Mock Compilation\n\nBefore proceeding to write tests, ensure your mock runtime compiles correctly:\n\n```bash\ncargo test --package pallet-custom --lib\n```\n\nThis command compiles the test code (including the mock and genesis configuration) without running tests yet. Address any compilation errors before continuing.\n\n??? code \"Complete mock runtime script\"\n\n Here's the complete `mock.rs` file for reference:\n\n ```rust title=\"src/mock.rs\"\n use crate as pallet_custom;\n use frame::{\n deps::{\n frame_support::{ derive_impl, traits::ConstU32 },\n sp_io,\n sp_runtime::{ traits::IdentityLookup, BuildStorage },\n },\n prelude::*,\n };\n\n type Block = frame_system::mocking::MockBlock;\n\n // Configure a mock runtime to test the pallet.\n frame::deps::frame_support::construct_runtime!(\n pub enum Test\n {\n System: frame_system,\n CustomPallet: pallet_custom,\n }\n );\n\n #[derive_impl(frame_system::config_preludes::TestDefaultConfig)]\n impl frame_system::Config for Test {\n type Block = Block;\n type AccountId = u64;\n type Lookup = IdentityLookup;\n }\n\n impl pallet_custom::Config for Test {\n type RuntimeEvent = RuntimeEvent;\n type CounterMaxValue = ConstU32<1000>;\n }\n\n // Build genesis storage according to the mock runtime.\n pub fn new_test_ext() -> sp_io::TestExternalities {\n let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap();\n\n (pallet_custom::GenesisConfig:: {\n initial_counter_value: 0,\n initial_user_interactions: vec![],\n })\n .assimilate_storage(&mut t)\n .unwrap();\n\n t.into()\n }\n\n // Helper function to create a test externalities with a specific initial counter value\n pub fn new_test_ext_with_counter(initial_value: u32) -> sp_io::TestExternalities {\n let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap();\n\n (pallet_custom::GenesisConfig:: {\n initial_counter_value: initial_value,\n initial_user_interactions: vec![],\n })\n .assimilate_storage(&mut t)\n .unwrap();\n\n t.into()\n }\n\n // Helper function to create a test externalities with initial user interactions\n pub fn new_test_ext_with_interactions(\n initial_value: u32,\n interactions: Vec<(u64, u32)>\n ) -> sp_io::TestExternalities {\n let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap();\n\n (pallet_custom::GenesisConfig:: {\n initial_counter_value: initial_value,\n initial_user_interactions: interactions,\n })\n .assimilate_storage(&mut t)\n .unwrap();\n\n t.into()\n }\n ```"} {"page_id": "parachains-customize-runtime-pallet-development-mock-runtime", "page_title": "Mock Your Runtime", "index": 11, "depth": 2, "title": "Key Takeaways", "anchor": "key-takeaways", "start_char": 10853, "end_char": 11416, "estimated_token_count": 98, "token_estimator": "heuristic-v1", "text": "## Key Takeaways\n\nYou've successfully created a mock runtime with a genesis configuration for your custom pallet. You can now:\n\n- Test your pallet without a full runtime.\n- Set initial blockchain state for different test scenarios.\n- Create different genesis setups for various testing needs.\n- Use this minimal setup to test all pallet functionality.\n\nThe mock runtime with a genesis configuration is essential for test-driven development, enabling you to verify logic under different initial conditions before integrating it into the actual parachain runtime."} {"page_id": "parachains-customize-runtime-pallet-development-mock-runtime", "page_title": "Mock Your Runtime", "index": 12, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 11416, "end_char": 11766, "estimated_token_count": 87, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Guide __Pallet Unit Testing__\n\n ---\n\n Learn to write comprehensive unit tests for your pallet using the mock runtime you just created.\n\n [:octicons-arrow-right-24: Continue](/parachains/customize-runtime/pallet-development/pallet-testing/)\n\n
"} -{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Pallet Testing", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 18, "end_char": 672, "estimated_token_count": 123, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nUnit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.\n\nTo begin unit testing, you must first set up a mock runtime that simulates blockchain behavior, incorporating the necessary pallets. For a deeper understanding, consult the [Mock Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\\_blank} guide."} -{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Pallet Testing", "index": 1, "depth": 2, "title": "Writing Unit Tests", "anchor": "writing-unit-tests", "start_char": 672, "end_char": 2195, "estimated_token_count": 285, "token_estimator": "heuristic-v1", "text": "## Writing Unit Tests\n\nOnce the mock runtime is in place, the next step is to write unit tests that evaluate the functionality of your pallet. Unit tests allow you to test specific pallet features in isolation, ensuring that each function behaves correctly under various conditions. These tests typically reside in your pallet module's `test.rs` file.\n\nUnit tests in the Polkadot SDK use the Rust testing framework, and the mock runtime you've defined earlier will serve as the test environment. Below are the typical steps involved in writing unit tests for a pallet.\n\nThe tests confirm that:\n\n- **Pallets initialize correctly**: At the start of each test, the system should initialize with block number 0, and the pallets should be in their default states.\n- **Pallets modify each other's state**: The second test shows how one pallet can trigger changes in another pallet's internal state, confirming proper cross-pallet interactions.\n- **State transitions between blocks are seamless**: By simulating block transitions, the tests validate that the runtime responds correctly to changes in the block number.\n\nTesting pallet interactions within the runtime is critical for ensuring the blockchain behaves as expected under real-world conditions. Writing integration tests allows validation of how pallets function together, preventing issues that might arise when the system is fully assembled.\n\nThis approach provides a comprehensive view of the runtime's functionality, ensuring the blockchain is stable and reliable."} -{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Pallet Testing", "index": 2, "depth": 3, "title": "Test Initialization", "anchor": "test-initialization", "start_char": 2195, "end_char": 2507, "estimated_token_count": 68, "token_estimator": "heuristic-v1", "text": "### Test Initialization\n\nEach test starts by initializing the runtime environment, typically using the `new_test_ext()` function, which sets up the mock storage and environment.\n\n```rust\n#[test]\nfn test_pallet_functionality() {\n new_test_ext().execute_with(|| {\n // Test logic goes here\n });\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Pallet Testing", "index": 3, "depth": 3, "title": "Function Call Testing", "anchor": "function-call-testing", "start_char": 2507, "end_char": 3280, "estimated_token_count": 167, "token_estimator": "heuristic-v1", "text": "### Function Call Testing\n\nCall the pallet's extrinsics or functions to simulate user interaction or internal logic. Use the `assert_ok!` macro to check for successful execution and `assert_err!` to verify that errors are correctly handled.\n\n```rust\n#[test]\nfn it_works_for_valid_input() {\n new_test_ext().execute_with(|| {\n // Call an extrinsic or function\n assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param));\n });\n}\n\n#[test]\nfn it_fails_for_invalid_input() {\n new_test_ext().execute_with(|| {\n // Call an extrinsic with invalid input and expect an error\n assert_err!(\n TemplateModule::some_function(Origin::signed(1), invalid_param),\n Error::::InvalidInput\n );\n });\n}\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Pallet Testing", "index": 4, "depth": 3, "title": "Storage Testing", "anchor": "storage-testing", "start_char": 3280, "end_char": 4129, "estimated_token_count": 190, "token_estimator": "heuristic-v1", "text": "### Storage Testing\n\nAfter calling a function or extrinsic in your pallet, it's essential to verify that the state changes in the pallet's storage match the expected behavior to ensure data is updated correctly based on the actions taken.\n\nThe following example shows how to test the storage behavior before and after the function call:\n\n```rust\n#[test]\nfn test_storage_update_on_extrinsic_call() {\n new_test_ext().execute_with(|| {\n // Check the initial storage state (before the call)\n assert_eq!(Something::::get(), None);\n\n // Dispatch a signed extrinsic, which modifies storage\n assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42));\n\n // Validate that the storage has been updated as expected (after the call)\n assert_eq!(Something::::get(), Some(42));\n });\n}\n\n```"} -{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Pallet Testing", "index": 5, "depth": 3, "title": "Event Testing", "anchor": "event-testing", "start_char": 4129, "end_char": 6150, "estimated_token_count": 519, "token_estimator": "heuristic-v1", "text": "### Event Testing\n\nIt's also crucial to test the events that your pallet emits during execution. By default, events generated in a pallet using the [`#generate_deposit`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.generate_deposit.html){target=\\_blank} macro are stored under the system's event storage key (system/events) as [`EventRecord`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.EventRecord.html){target=\\_blank} entries. These can be accessed using [`System::events()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.events){target=\\_blank} or verified with specific helper methods provided by the system pallet, such as [`assert_has_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_has_event){target=\\_blank} and [`assert_last_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_last_event){target=\\_blank}.\n\nHere's an example of testing events in a mock runtime:\n\n```rust\n#[test]\nfn it_emits_events_on_success() {\n new_test_ext().execute_with(|| {\n // Call an extrinsic or function\n assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param));\n\n // Verify that the expected event was emitted\n assert!(System::events().iter().any(|record| {\n record.event == Event::TemplateModule(TemplateEvent::SomeEvent)\n }));\n });\n}\n```\n\nSome key considerations are:\n\n- **Block number**: Events are not emitted on the genesis block, so you need to set the block number using [`System::set_block_number()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.set_block_number){target=\\_blank} to ensure events are triggered.\n- **Converting events**: Use `.into()` when instantiating your pallet's event to convert it into a generic event type, as required by the system's event storage."} -{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Pallet Testing", "index": 6, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 6150, "end_char": 6892, "estimated_token_count": 211, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n- Dive into the full implementation of the [`mock.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/mock.rs){target=\\_blank} and [`test.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/tests.rs){target=\\_blank} files in the [Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=_blank}.\n\n
\n\n- Guide __Benchmarking__\n\n ---\n\n Explore methods to measure the performance and execution cost of your pallet.\n\n [:octicons-arrow-right-24: Reference](/develop/parachains/testing/benchmarking)\n\n
"} +{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Unit Test Pallets", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 21, "end_char": 675, "estimated_token_count": 123, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nUnit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.\n\nTo begin unit testing, you must first set up a mock runtime that simulates blockchain behavior, incorporating the necessary pallets. For a deeper understanding, consult the [Mock Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\\_blank} guide."} +{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Unit Test Pallets", "index": 1, "depth": 2, "title": "Writing Unit Tests", "anchor": "writing-unit-tests", "start_char": 675, "end_char": 2198, "estimated_token_count": 285, "token_estimator": "heuristic-v1", "text": "## Writing Unit Tests\n\nOnce the mock runtime is in place, the next step is to write unit tests that evaluate the functionality of your pallet. Unit tests allow you to test specific pallet features in isolation, ensuring that each function behaves correctly under various conditions. These tests typically reside in your pallet module's `test.rs` file.\n\nUnit tests in the Polkadot SDK use the Rust testing framework, and the mock runtime you've defined earlier will serve as the test environment. Below are the typical steps involved in writing unit tests for a pallet.\n\nThe tests confirm that:\n\n- **Pallets initialize correctly**: At the start of each test, the system should initialize with block number 0, and the pallets should be in their default states.\n- **Pallets modify each other's state**: The second test shows how one pallet can trigger changes in another pallet's internal state, confirming proper cross-pallet interactions.\n- **State transitions between blocks are seamless**: By simulating block transitions, the tests validate that the runtime responds correctly to changes in the block number.\n\nTesting pallet interactions within the runtime is critical for ensuring the blockchain behaves as expected under real-world conditions. Writing integration tests allows validation of how pallets function together, preventing issues that might arise when the system is fully assembled.\n\nThis approach provides a comprehensive view of the runtime's functionality, ensuring the blockchain is stable and reliable."} +{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Unit Test Pallets", "index": 2, "depth": 3, "title": "Test Initialization", "anchor": "test-initialization", "start_char": 2198, "end_char": 2510, "estimated_token_count": 68, "token_estimator": "heuristic-v1", "text": "### Test Initialization\n\nEach test starts by initializing the runtime environment, typically using the `new_test_ext()` function, which sets up the mock storage and environment.\n\n```rust\n#[test]\nfn test_pallet_functionality() {\n new_test_ext().execute_with(|| {\n // Test logic goes here\n });\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Unit Test Pallets", "index": 3, "depth": 3, "title": "Function Call Testing", "anchor": "function-call-testing", "start_char": 2510, "end_char": 3283, "estimated_token_count": 167, "token_estimator": "heuristic-v1", "text": "### Function Call Testing\n\nCall the pallet's extrinsics or functions to simulate user interaction or internal logic. Use the `assert_ok!` macro to check for successful execution and `assert_err!` to verify that errors are correctly handled.\n\n```rust\n#[test]\nfn it_works_for_valid_input() {\n new_test_ext().execute_with(|| {\n // Call an extrinsic or function\n assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param));\n });\n}\n\n#[test]\nfn it_fails_for_invalid_input() {\n new_test_ext().execute_with(|| {\n // Call an extrinsic with invalid input and expect an error\n assert_err!(\n TemplateModule::some_function(Origin::signed(1), invalid_param),\n Error::::InvalidInput\n );\n });\n}\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Unit Test Pallets", "index": 4, "depth": 3, "title": "Storage Testing", "anchor": "storage-testing", "start_char": 3283, "end_char": 4132, "estimated_token_count": 190, "token_estimator": "heuristic-v1", "text": "### Storage Testing\n\nAfter calling a function or extrinsic in your pallet, it's essential to verify that the state changes in the pallet's storage match the expected behavior to ensure data is updated correctly based on the actions taken.\n\nThe following example shows how to test the storage behavior before and after the function call:\n\n```rust\n#[test]\nfn test_storage_update_on_extrinsic_call() {\n new_test_ext().execute_with(|| {\n // Check the initial storage state (before the call)\n assert_eq!(Something::::get(), None);\n\n // Dispatch a signed extrinsic, which modifies storage\n assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42));\n\n // Validate that the storage has been updated as expected (after the call)\n assert_eq!(Something::::get(), Some(42));\n });\n}\n\n```"} +{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Unit Test Pallets", "index": 5, "depth": 3, "title": "Event Testing", "anchor": "event-testing", "start_char": 4132, "end_char": 6153, "estimated_token_count": 519, "token_estimator": "heuristic-v1", "text": "### Event Testing\n\nIt's also crucial to test the events that your pallet emits during execution. By default, events generated in a pallet using the [`#generate_deposit`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.generate_deposit.html){target=\\_blank} macro are stored under the system's event storage key (system/events) as [`EventRecord`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.EventRecord.html){target=\\_blank} entries. These can be accessed using [`System::events()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.events){target=\\_blank} or verified with specific helper methods provided by the system pallet, such as [`assert_has_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_has_event){target=\\_blank} and [`assert_last_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_last_event){target=\\_blank}.\n\nHere's an example of testing events in a mock runtime:\n\n```rust\n#[test]\nfn it_emits_events_on_success() {\n new_test_ext().execute_with(|| {\n // Call an extrinsic or function\n assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param));\n\n // Verify that the expected event was emitted\n assert!(System::events().iter().any(|record| {\n record.event == Event::TemplateModule(TemplateEvent::SomeEvent)\n }));\n });\n}\n```\n\nSome key considerations are:\n\n- **Block number**: Events are not emitted on the genesis block, so you need to set the block number using [`System::set_block_number()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.set_block_number){target=\\_blank} to ensure events are triggered.\n- **Converting events**: Use `.into()` when instantiating your pallet's event to convert it into a generic event type, as required by the system's event storage."} +{"page_id": "parachains-customize-runtime-pallet-development-pallet-testing", "page_title": "Unit Test Pallets", "index": 6, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 6153, "end_char": 6895, "estimated_token_count": 211, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n- Dive into the full implementation of the [`mock.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/mock.rs){target=\\_blank} and [`test.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/tests.rs){target=\\_blank} files in the [Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=_blank}.\n\n
\n\n- Guide __Benchmarking__\n\n ---\n\n Explore methods to measure the performance and execution cost of your pallet.\n\n [:octicons-arrow-right-24: Reference](/develop/parachains/testing/benchmarking)\n\n
"} {"page_id": "parachains-customize-runtime", "page_title": "Overview of FRAME", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 26, "end_char": 754, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nA blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose.\n\nThis overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime."} {"page_id": "parachains-customize-runtime", "page_title": "Overview of FRAME", "index": 1, "depth": 2, "title": "Understanding Your Runtime", "anchor": "understanding-your-runtime", "start_char": 754, "end_char": 1533, "estimated_token_count": 158, "token_estimator": "heuristic-v1", "text": "## Understanding Your Runtime\n\nThe runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\\_blank} pallet receives it and routes it to the appropriate pallet for execution.\n\nThink of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case."} {"page_id": "parachains-customize-runtime", "page_title": "Overview of FRAME", "index": 2, "depth": 2, "title": "Runtime Architecture", "anchor": "runtime-architecture", "start_char": 1533, "end_char": 2085, "estimated_token_count": 121, "token_estimator": "heuristic-v1", "text": "## Runtime Architecture\n\nThe following diagram shows how FRAME components work together to form your runtime:\n\n![](/images/parachains/customize-runtime/index/frame-overview-01.webp)\n\nThe main components are:\n\n- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution.\n- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic.\n- **`frame_system`**: Provides core runtime primitives and storage.\n- **`frame_support`**: Utilities and macros that simplify pallet development."} diff --git a/llms.txt b/llms.txt index 3a102f2bf..98d224c83 100644 --- a/llms.txt +++ b/llms.txt @@ -87,7 +87,7 @@ Docs: Parachains - [Benchmark Your Pallet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md): Learn how to benchmark your custom pallet extrinsics to generate accurate weight calculations for production use. - [Create a Custom Pallet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md): Learn how to create custom pallets using FRAME, allowing for flexible, modular, and scalable blockchain development. Follow the step-by-step guide. - [Mock Your Runtime](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md): Learn how to create a mock runtime environment for testing your custom pallets in isolation, enabling comprehensive unit testing before runtime integration. -- [Pallet Testing](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md): Learn how to efficiently test pallets in the Polkadot SDK, ensuring the reliability and security of your pallets operations. +- [Unit Test Pallets](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md): Learn how to efficiently test pallets in the Polkadot SDK, ensuring the reliability and security of your pallets operations. - [Overview of FRAME](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md): Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. - [Get Started with Parachain Development](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md): Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. - [Opening HRMP Channels Between Parachains](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md): Learn how to open HRMP channels between parachains on Polkadot. Discover the step-by-step process for establishing uni- and bidirectional communication. From 3a952dc4e13f248c40e444637d2a481ca8bfb94b Mon Sep 17 00:00:00 2001 From: DAWN KELLY Date: Tue, 18 Nov 2025 14:01:52 -0500 Subject: [PATCH 04/12] apply copilot feedback --- .../customize-runtime/pallet-development/benchmark-pallet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parachains/customize-runtime/pallet-development/benchmark-pallet.md b/parachains/customize-runtime/pallet-development/benchmark-pallet.md index 092b8d6e1..7c9407b07 100644 --- a/parachains/customize-runtime/pallet-development/benchmark-pallet.md +++ b/parachains/customize-runtime/pallet-development/benchmark-pallet.md @@ -241,7 +241,7 @@ To execute benchmarks, your pallet must be integrated into the runtime's benchma When you build the runtime with `--features runtime-benchmarks`, this configuration ensures all necessary benchmarking code across all pallets (including yours) is included. -2. **Update runtime configuration**: Run development benchmarks with the placeholder implementation and use the resulting weights file to update benchmark weights as follows: +2. **Update runtime configuration**: Using the the placeholder implementation, run development benchmarks as follows: ```rust title="runtime/src/configs/mod.rs" impl pallet_custom::Config for Runtime { From b027f5acda8b6b9aa18c50c0d4cdbaf0c2f30c44 Mon Sep 17 00:00:00 2001 From: DAWN KELLY Date: Thu, 20 Nov 2025 13:51:00 -0500 Subject: [PATCH 05/12] update snippet title --- .../customize-runtime/pallet-development/benchmark-pallet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parachains/customize-runtime/pallet-development/benchmark-pallet.md b/parachains/customize-runtime/pallet-development/benchmark-pallet.md index 7c9407b07..cc4521409 100644 --- a/parachains/customize-runtime/pallet-development/benchmark-pallet.md +++ b/parachains/customize-runtime/pallet-development/benchmark-pallet.md @@ -84,7 +84,7 @@ This module contains all the [benchmarking definitions](https://paritytech.githu Add a `weights` module to your pallet that defines the `WeightInfo` trait using the following code: -```rust title="pallets/pallet-custom/src/lib.rs" +```rust title="pallets/pallet-custom/src/weights.rs" #[frame::pallet] pub mod pallet { use frame::prelude::*; From f4577d1f48ec16c27aa541cd3f644f080a168dda Mon Sep 17 00:00:00 2001 From: Dawn Kelly <83190195+dawnkelly09@users.noreply.github.com> Date: Thu, 20 Nov 2025 13:53:25 -0500 Subject: [PATCH 06/12] Apply suggestions from code review Co-authored-by: Erin Shaben --- .../pallet-development/benchmark-pallet.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/parachains/customize-runtime/pallet-development/benchmark-pallet.md b/parachains/customize-runtime/pallet-development/benchmark-pallet.md index cc4521409..0b3a5bc72 100644 --- a/parachains/customize-runtime/pallet-development/benchmark-pallet.md +++ b/parachains/customize-runtime/pallet-development/benchmark-pallet.md @@ -1,6 +1,6 @@ --- title: Benchmark Your Pallet -description: Learn how to benchmark your custom pallet extrinsics to generate accurate weight calculations for production use. +description: Learn how to benchmark extrinsics in your custom pallet to generate precise weight calculations suitable for production use. categories: Parachains --- @@ -286,7 +286,7 @@ The `impl_benchmark_test_suite!` macro generates unit tests for each benchmark. ## Build the Runtime with Benchmarks -Compile the runtime with benchmarking enabled to generate the WASM binary using the following command: +Compile the runtime with benchmarking enabled to generate the Wasm binary using the following command: ```bash cargo build --release --features runtime-benchmarks @@ -347,10 +347,10 @@ Benchmarks execute against the compiled WASM runtime rather than native code bec --output ./pallets/pallet-custom/src/weights.rs ``` - - `--steps 50`: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time. - - `--repeat 20`: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise, and providing more reliable weight estimates. - - `--heap-pages 4096`: WASM heap pages allocation. Affects available memory during execution. - - `--wasm-execution compiled`: WASM execution method. Use `compiled` for performance closest to production conditions. + - **`--steps 50`**: Number of different input values to test when using linear components (default: 50). More steps provide finer granularity for detecting complexity trends but increase benchmarking time. + - **`--repeat 20`**: Number of repetitions for each measurement (default: 20). More repetitions improve statistical accuracy by averaging out variance, reducing the impact of system noise, and providing more reliable weight estimates. + - **`--heap-pages 4096`**: WASM heap pages allocation. Affects available memory during execution. + - **`--wasm-execution compiled`**: WASM execution method. Use `compiled` for performance closest to production conditions. ## Use Generated Weights @@ -459,8 +459,8 @@ Now that you've added the pallet to your runtime, you can follow these steps to This build produces a production-ready WASM runtime at `target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`. !!! note "Compare build types" - - `cargo build --release --features runtime-benchmarks` - Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher`. - - `cargo build --release` - Compiles production runtime without benchmarking features. Use this for running your chain in production. + - **`cargo build --release --features runtime-benchmarks`**: Compiles with benchmarking host functions for measurement. Use this ONLY when running benchmarks with `frame-omni-bencher`. + - **`cargo build --release`**: Compiles production runtime without benchmarking features. Use this for running your chain in production. 2. Generate a new chain specification file with the updated runtime using the following commands: From 1177ee75d3882760786eec70ad44f0c232452ca9 Mon Sep 17 00:00:00 2001 From: DAWN KELLY Date: Thu, 20 Nov 2025 13:53:40 -0500 Subject: [PATCH 07/12] apply feedback from review --- .../customize-runtime/pallet-development/benchmark-pallet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parachains/customize-runtime/pallet-development/benchmark-pallet.md b/parachains/customize-runtime/pallet-development/benchmark-pallet.md index 0b3a5bc72..389cfd1eb 100644 --- a/parachains/customize-runtime/pallet-development/benchmark-pallet.md +++ b/parachains/customize-runtime/pallet-development/benchmark-pallet.md @@ -116,7 +116,7 @@ pub mod pallet { } ``` -The `()` implementation provides placeholder weights for development. +The `WeightInfo for ()` implementation provides placeholder weights for development. ## Add WeightInfo to Config From 57a8f6e6bda219ec95a183a6f1dd3adb4f0241cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hussein?= <80422357+nhussein11@users.noreply.github.com> Date: Tue, 18 Nov 2025 14:11:53 -0300 Subject: [PATCH 08/12] Add Hardhat Get Started (new IA) (#1196) * add harthdat get started * fix: llms * fix and formating * fix --------- Co-authored-by: 0xlukem --- .ai/categories/smart-contracts.md | 960 +- .ai/categories/tooling.md | 464 +- ...ts-dev-environments-hardhat-get-started.md | 464 +- .../smart-contracts-for-eth-devs-migration.md | 4 +- .ai/site-index.json | 15229 +++++++++++----- llms-full.jsonl | 139 +- llms.txt | 14 +- .../dev-environments/hardhat/get-started.md | 345 +- 8 files changed, 11485 insertions(+), 6134 deletions(-) diff --git a/.ai/categories/smart-contracts.md b/.ai/categories/smart-contracts.md index 1e901e36e..dfd3931b5 100644 --- a/.ai/categories/smart-contracts.md +++ b/.ai/categories/smart-contracts.md @@ -4439,6 +4439,280 @@ By defining weights, you can trade-off the number of transactions per second and Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. +--- + +Page Title: hardhat + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-hardhat/ +- Summary: Learn how to deploy a basic smart contract to Polkadot Hub using Hardhat, Perfect for professional workflows requiring comprehensive testing and debugging. + +[Hardhat](https://hardhat.org/){target=\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects. + +**Prerequisites:** + +- Basic understanding of Solidity programming. +- [Node.js](https://nodejs.org/en/download){target=\_blank} v22.13.1 or later. +- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). +- A wallet with a private key for signing transactions. + +### Setup + +Initialize your Hardhat project: + +```bash +mkdir hardhat-deployment +cd hardhat-deployment +npx hardhat --init +``` + +### Configure Hardhat + +Edit `hardhat.config.js`: + +```javascript title="hardhat.config.js" hl_lines="39-43" +import type { HardhatUserConfig } from "hardhat/config"; + +import hardhatToolboxViemPlugin from "@nomicfoundation/hardhat-toolbox-viem"; +import { configVariable } from "hardhat/config"; + +const config: HardhatUserConfig = { + plugins: [hardhatToolboxViemPlugin], + solidity: { + profiles: { + default: { + version: "0.8.28", + }, + production: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + }, + }, + networks: { + hardhatMainnet: { + type: "edr-simulated", + chainType: "l1", + }, + hardhatOp: { + type: "edr-simulated", + chainType: "op", + }, + sepolia: { + type: "http", + chainType: "l1", + url: configVariable("SEPOLIA_RPC_URL"), + accounts: [configVariable("SEPOLIA_PRIVATE_KEY")], + }, + polkadotHubTestnet: { + url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; + +export default config; + +``` + +### Create Your Contract + +Replace the default contract in `contracts/Storage.sol`: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +contract Storage { + uint256 private storedNumber; + + function store(uint256 num) public { + storedNumber = num; + } + + function retrieve() public view returns (uint256) { + return storedNumber; + } +} +``` + +### Compile + +```bash +npx hardhat build +``` + +### Set Up Deployment + +Create a deployment module in `ignition/modules/Storage.ts`: + +```typescript title="ignition/modules/Storage.ts" +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; + +export default buildModule('StorageModule', (m) => { + const storage = m.contract('Storage'); + return { storage }; +}); +``` + +### Deploy + +Deploy to Polkadot Hub TestNet: + +```bash +npx hardhat ignition deploy ignition/modules/Storage.ts --network polkadotHubTestnet +``` + +### Next Steps + +- Deploy an ERC-20 token on Polkadot Hub, either using the [Deploy an ERC-20](/smart-contracts/cookbook/smart-contracts/deploy-erc20) guide or the [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20) guide. +- Deploy an NFT on Polkadot Hub, either using the [Deploy an NFT](/smart-contracts/cookbook/smart-contracts/deploy-nft) guide or the [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft) guide. +- Check out in details each [development environment](/smart-contracts/dev-environments/). + + +--- + +Page Title: hardhat + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-hardhat/ +- Summary: Learn how to deploy a basic smart contract to Polkadot Hub using Hardhat, Perfect for professional workflows requiring comprehensive testing and debugging. + +[Hardhat](https://hardhat.org/){target=\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects. + +**Prerequisites:** + +- Basic understanding of Solidity programming. +- [Node.js](https://nodejs.org/en/download){target=\_blank} v22.13.1 or later. +- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). +- A wallet with a private key for signing transactions. + +### Setup + +Initialize your Hardhat project: + +```bash +mkdir hardhat-deployment +cd hardhat-deployment +npx hardhat --init +``` + +### Configure Hardhat + +Edit `hardhat.config.js`: + +```javascript title="hardhat.config.js" hl_lines="39-43" +import type { HardhatUserConfig } from "hardhat/config"; + +import hardhatToolboxViemPlugin from "@nomicfoundation/hardhat-toolbox-viem"; +import { configVariable } from "hardhat/config"; + +const config: HardhatUserConfig = { + plugins: [hardhatToolboxViemPlugin], + solidity: { + profiles: { + default: { + version: "0.8.28", + }, + production: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + }, + }, + networks: { + hardhatMainnet: { + type: "edr-simulated", + chainType: "l1", + }, + hardhatOp: { + type: "edr-simulated", + chainType: "op", + }, + sepolia: { + type: "http", + chainType: "l1", + url: configVariable("SEPOLIA_RPC_URL"), + accounts: [configVariable("SEPOLIA_PRIVATE_KEY")], + }, + polkadotHubTestnet: { + url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + accounts: [configVariable("PRIVATE_KEY")], + }, + }, +}; + +export default config; + +``` + +### Create Your Contract + +Replace the default contract in `contracts/Storage.sol`: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; + +contract Storage { + uint256 private storedNumber; + + function store(uint256 num) public { + storedNumber = num; + } + + function retrieve() public view returns (uint256) { + return storedNumber; + } +} +``` + +### Compile + +```bash +npx hardhat build +``` + +### Set Up Deployment + +Create a deployment module in `ignition/modules/Storage.ts`: + +```typescript title="ignition/modules/Storage.ts" +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; + +export default buildModule('StorageModule', (m) => { + const storage = m.contract('Storage'); + return { storage }; +}); +``` + +### Deploy + +Deploy to Polkadot Hub TestNet: + +```bash +npx hardhat ignition deploy ignition/modules/Storage.ts --network polkadotHubTestnet +``` + +### Next Steps + +- Deploy an ERC-20 token on Polkadot Hub, either using the [Deploy an ERC-20](/smart-contracts/cookbook/smart-contracts/deploy-erc20) guide or the [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20) guide. +- Deploy an NFT on Polkadot Hub, either using the [Deploy an NFT](/smart-contracts/cookbook/smart-contracts/deploy-nft) guide or the [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft) guide. +- Check out in details each [development environment](/smart-contracts/dev-environments/). + + --- Page Title: Install Polkadot SDK @@ -4860,6 +5134,16 @@ To stop the node, press `Control-C` in the terminal. +- __Get Started with Parachain Development__ + + --- + + Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. + + [:octicons-arrow-right-24: Get Started](/parachains/get-started/) + + + --- @@ -6218,48 +6502,202 @@ The node will begin producing blocks immediately and display initialization logs 2025-05-29 10:42:42 🏆 Imported #1 (0x1ae1…b8b4 → 0xa88d…e36a) -For debugging purposes or to monitor low-level operations, you can enable detailed logging by setting environment variables before running the command: +For debugging purposes or to monitor low-level operations, you can enable detailed logging by setting environment variables before running the command: + +```bash +RUST_LOG="error,evm=debug,sc_rpc_server=info,runtime::revive=debug" ./target/release/revive-dev-node --dev +``` + +Once the node is running, open a new terminal window and start the ETH-RPC adapter. This component translates Ethereum JSON-RPC calls into Substrate-compatible requests, allowing you to use familiar Ethereum tools like MetaMask, Hardhat, or Ethers.js: + +```bash +./target/release/eth-rpc --dev +``` + +You should see logs indicating that the adapter is ready to accept connections: + +
+ ./target/release/eth-rpc --dev +
+ 2025-05-29 10:48:48 Running in --dev mode, RPC CORS has been disabled. + 2025-05-29 10:48:48 Running in --dev mode, RPC CORS has been disabled. + 2025-05-29 10:48:48 🌐 Connecting to node at: ws://127.0.0.1:9944 ... + 2025-05-29 10:48:48 🌟 Connected to node at: ws://127.0.0.1:9944 + 2025-05-29 10:48:48 💾 Using in-memory database, keeping only 256 blocks in memory + 2025-05-29 10:48:48 〽️ Prometheus exporter started at 127.0.0.1:9616 + 2025-05-29 10:48:48 Running JSON-RPC server: addr=127.0.0.1:8545,[::1]:8545 + 2025-05-29 10:48:48 🔌 Subscribing to new blocks (BestBlocks) + 2025-05-29 10:48:48 🔌 Subscribing to new blocks (FinalizedBlocks) +
+ +Similar to the Revive Dev node, you can enable detailed logging for the ETH-RPC adapter to troubleshoot issues: + +```bash +RUST_LOG="info,eth-rpc=debug" ./target/release/eth-rpc --dev +``` + +Your local development environment is now active and accessible at `http://localhost:8545`. This endpoint accepts standard Ethereum JSON-RPC requests, enabling seamless integration with existing Ethereum development tools and workflows. + +You can connect wallets, deploy contracts using Remix or Hardhat, and interact with your smart contracts as you would on any Ethereum-compatible network. + + +--- + +Page Title: Migration FAQs and Considerations + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/ +- Summary: Learn how to migrate your existing Ethereum contracts to the Polkadot Hub using REVM and PolkaVM by following these considerations. + +# Migration FAQs and Considerations + +## Introduction + +This guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns. + +## Migration Considerations + +Take into account the following considerations before migrating your contracts: + +- Standard ERC-20, ERC-721, ERC-1155 tokens work without changes. +- DeFi protocols, DEXs, and AMMs migrate seamlessly. +- DAOs and governance contracts are fully compatible. +- Most Solidity contracts deploy identically to Ethereum. + +## Migration Checklist + +Before migrating your contracts, review this checklist: + +- Factory contracts using PVM bytecode need pre-uploaded dependencies. +- Contracts using `EXTCODECOPY` for runtime manipulation require review (for projects that will use PVM bytecode, not EVM bytecode). +- Replace `transfer()` and `send()` with proper reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode). + +## Migration FAQs + +### Which backend should I choose? + +- Choose REVM if you want: + + - Zero-modification deployment of existing Ethereum contracts. + - Exact EVM behavior for audited code. + - Compatibility with tools that inspect EVM bytecode. + - Rapid deployment without optimization. + +- Choose PolkaVM if you want: + + - Better performance for computation-heavy applications. + - Lower execution costs for intensive operations. + - Access to next-generation smart contract features. + +If you are unsure which to choose, start with REVM for immediate compatibility, then consider PolkaVM for performance optimization once deployed. + +### Do I need to rewrite my Solidity code? + +No, for most contracts. Standard Solidity patterns work on both backends. + +### What about factory contracts? + +- **REVM**: Factory contracts work identically to Ethereum with no changes needed. + + The original factory pattern is: + + ```solidity + contract TokenFactory { + function createToken(string memory name) public returns (address) { + // Creates new contract at runtime + Token newToken = new Token(name); + return address(newToken); + } + } + ``` + +- **PolkaVM**: Factory contracts require pre-uploading dependent contracts. + + Here's how to adapt the original factory pattern: + + ```solidity + contract TokenFactory { + // Reference pre-uploaded Token contract by hash + bytes32 public tokenCodeHash; + + constructor(bytes32 _tokenCodeHash) { + tokenCodeHash = _tokenCodeHash; + } + + function createToken(string memory name) public returns (address) { + // Instantiate from pre-uploaded code + Token newToken = new Token{salt: keccak256(abi.encode(name))}(name); + return address(newToken); + } + } + ``` + +The deployment steps for PolkaVM factories are: + +1. Upload the contract code to the chain. +2. Note the returned code hash. +3. Deploy the Factory contract with the contract code hash. +4. Factory can now instantiate contracts using the pre-uploaded code. + +### How do gas costs compare? -```bash -RUST_LOG="error,evm=debug,sc_rpc_server=info,runtime::revive=debug" ./target/release/revive-dev-node --dev -``` +For more information on gas costs, see the [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} page. -Once the node is running, open a new terminal window and start the ETH-RPC adapter. This component translates Ethereum JSON-RPC calls into Substrate-compatible requests, allowing you to use familiar Ethereum tools like MetaMask, Hardhat, or Ethers.js: +### Which Solidity features are not supported? -```bash -./target/release/eth-rpc --dev -``` +For REVM, any Solidity feature will function smoothly without requiring changes or adaptations. For PVM, there are considerations, as was mentioned above. -You should see logs indicating that the adapter is ready to accept connections: +For PolkaVM, there are some considerations: -
- ./target/release/eth-rpc --dev -
- 2025-05-29 10:48:48 Running in --dev mode, RPC CORS has been disabled. - 2025-05-29 10:48:48 Running in --dev mode, RPC CORS has been disabled. - 2025-05-29 10:48:48 🌐 Connecting to node at: ws://127.0.0.1:9944 ... - 2025-05-29 10:48:48 🌟 Connected to node at: ws://127.0.0.1:9944 - 2025-05-29 10:48:48 💾 Using in-memory database, keeping only 256 blocks in memory - 2025-05-29 10:48:48 〽️ Prometheus exporter started at 127.0.0.1:9616 - 2025-05-29 10:48:48 Running JSON-RPC server: addr=127.0.0.1:8545,[::1]:8545 - 2025-05-29 10:48:48 🔌 Subscribing to new blocks (BestBlocks) - 2025-05-29 10:48:48 🔌 Subscribing to new blocks (FinalizedBlocks) -
+- `EXTCODECOPY`: Only works in constructor code. +- Runtime code modification: Use on-chain constructors instead. +- **Gas stipends**: `address.send()` and `address.transfer()` don't provide reentrancy protection. +- **Unsupported operations**: `pc`, `extcodecopy`, `selfdestruct`, `blobhash`, and `blobbasefee` (blob-related operations). -Similar to the Revive Dev node, you can enable detailed logging for the ETH-RPC adapter to troubleshoot issues: +### How do I handle the existential deposit? -```bash -RUST_LOG="info,eth-rpc=debug" ./target/release/eth-rpc --dev -``` +Polkadot requires accounts to maintain a minimum balance (existential deposit or ED) to remain active. -Your local development environment is now active and accessible at `http://localhost:8545`. This endpoint accepts standard Ethereum JSON-RPC requests, enabling seamless integration with existing Ethereum development tools and workflows. +This is handled automatically for you: -You can connect wallets, deploy contracts using Remix or Hardhat, and interact with your smart contracts as you would on any Ethereum-compatible network. +- Balance queries via Ethereum RPC automatically deduct the ED. +- New account transfers include ED in transaction fees. +- Contract-to-contract transfers draw ED from the transaction signer. + +You typically don't need to do anything special, but be aware: + +- Accounts below ED threshold are automatically deleted. +- ED is around 0.01 DOT (varies by network). +- Your contracts don't need to manage this explicitly. + +### Can I use my existing development tools? + +Yes. Both backends support: + +- **Wallets**: [MetaMask](https://metamask.io/){target=\_blank}, [Talisman](https://talisman.xyz/){target=\_blank}, [SubWallet](https://www.subwallet.app/){target=\_blank} +- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\_blank}, [Foundry](/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/){target=\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} (just consider that for PVM bytecode, you will use the Polkadot version of the tooling) +- **Libraries**: [ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank}, [web3.js](/smart-contracts/libraries/web3-js/){target=\_blank}, [viem](/smart-contracts/libraries/viem/){target=\_blank} +- **Testing tools**: Your existing test suites work + +Connect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow. + +## Conclusion + +Most Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance. + +There are a few key points to keep in mind during migration: + +- Replace `transfer()` and `send()` with `.call{value}("")` and use reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode). +- PolkaVM factory contracts using PVM bytecode need pre-uploaded dependencies. +- Don't hardcode gas values. +- Test thoroughly on [TestNet](/smart-contracts/connect/#__tabbed_1_1){target=\_blank} before mainnet deployment. + +Your existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns. --- -Page Title: Migration FAQs and Considerations +Page Title: Networks - Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md - Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/ @@ -8976,464 +9414,150 @@ Page Title: Use Hardhat with Polkadot Hub - Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md - Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/get-started/ -- Summary: Learn how to create, compile, test, and deploy smart contracts on Polkadot Hub using Hardhat, a powerful development environment for blockchain developers. +- Summary: Overview of Hardhat, a powerful development environment for creating, compiling, testing, and deploying smart contracts on Polkadot Hub. # Hardhat -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -
-- :octicons-code-16:{ .lg .middle } __Test and Deploy with Hardhat__ - - --- - - Master Solidity smart contract development with Hardhat. Learn testing, deployment, and network interaction in one comprehensive tutorial. - -
- [:octicons-arrow-right-24: Get Started](/tutorials/smart-contracts/launch-your-first-project/test-and-deploy-with-hardhat){target=\_blank} - -
- -!!! note "Contracts Code Blob Size Disclaimer" - The maximum contract code blob size on Polkadot Hub networks is _100 kilobytes_, significantly larger than Ethereum’s EVM limit of 24 kilobytes. - - For detailed comparisons and migration guidelines, see the [EVM vs. PolkaVM](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#current-memory-limits){target=\_blank} documentation page. - ## Overview -Hardhat is a robust development environment for Ethereum-compatible chains that makes smart contract development more efficient. This guide walks you through the essentials of using Hardhat to create, compile, test, and deploy smart contracts on Polkadot Hub. - -## Prerequisites - -Before getting started, ensure you have: - -- [Node.js](https://nodejs.org/){target=\_blank} (v16.0.0 or later) and npm installed. - - Note: Use Node.js 22.5+ and npm version 10.9.0+ to avoid issues with the Polkadot plugin. -- Basic understanding of Solidity programming. -- Some PAS test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}). To learn how to get test tokens, check out the [Test Tokens](/smart-contracts/connect/#test-tokens){target=\_blank} section. - -## Set Up Hardhat - -1. Create a new directory for your project and navigate into it: - - ```bash - mkdir hardhat-example - cd hardhat-example - ``` - -2. Initialize a new npm project: - - ```bash - npm init -y - ``` - -3. To interact with Polkadot, Hardhat requires the following plugin to compile contracts to PolkaVM bytecode and to spawn a local node compatible with PolkaVM: - - ```bash - npm install --save-dev @parity/hardhat-polkadot@0.1.9 - ``` - -4. Create a Hardhat project: - - ```bash - npx hardhat-polkadot init - ``` - - Select **Create a JavaScript project** when prompted and follow the instructions. After that, your project will be created with three main folders: - - - **`contracts`**: Where your Solidity smart contracts live. - - **`test`**: Contains your test files that validate contract functionality. - - **`ignition`**: Deployment modules for safely deploying your contracts to various networks. - -5. Add the following folder to the `.gitignore` file if it is not already there: - - ```bash - echo '/ignition/deployments/' >> .gitignore - ``` - -6. Finish the setup by installing all the dependencies: - - ```bash - npm install - ``` - - !!! note - This last step is needed to set up the `hardhat-polkadot` plugin. It will install the `@parity/hardhat-polkadot` package and all its dependencies. In the future, the plugin will handle this automatically. - -## Compile Your Contract - -The plugin will compile your Solidity contracts for Solidity versions `0.8.0` and higher to be PolkaVM compatible. When compiling your contract, there are two ways to configure your compilation process: +Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer. -- **npm compiler**: Uses library [@parity/resolc](https://www.npmjs.com/package/@parity/resolc){target=\_blank} for simplicity and ease of use. -- **Binary compiler**: Uses your local `resolc` binary directly for more control and configuration options. +Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit including compilation, local testing nodes, debugging tools, and deployment automation. -To compile your project, follow these instructions: +## Hardhat Workflow -1. Modify your Hardhat configuration file to specify which compilation process you will be using and activate the `polkavm` flag in the Hardhat network: +From the first sketch of a contract to ongoing operations, Hardhat encourages a repeatable cycle: define the functionality you need, scaffold the workspace, write and refine Solidity code, compile it into deployable artifacts, validate behavior with automated tests, deploy confidently to the target network, and keep iterating with scripts that monitor and interact with what you shipped. - === "npm Configuration" - - ```javascript title="hardhat.config.js" hl_lines="9-11 14" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); - - require('@parity/hardhat-polkadot'); - - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - solidity: '0.8.28', - resolc: { - compilerSource: 'npm', - }, - networks: { - hardhat: { - polkavm: true, - }, - }, - }; - ``` - - === "Binary Configuration" - - ```javascript title="hardhat.config.js" hl_lines="9-14 17" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); - - require('@parity/hardhat-polkadot'); - - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - solidity: '0.8.28', - resolc: { - compilerSource: 'binary', - settings: { - compilerPath: 'INSERT_PATH_TO_RESOLC_COMPILER', - }, - }, - networks: { - hardhat: { - polkavm: true, - }, - }, - }; - ``` - - For the binary configuration, replace `INSERT_PATH_TO_RESOLC_COMPILER` with the proper path to the binary. To obtain the binary, check the [releases](https://github.com/paritytech/revive/releases){target=\_blank} section of the `resolc` compiler, and download the latest version. - - The default settings used can be found in the [`constants.ts`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/constants.ts#L8-L23){target=\_blank} file of the `hardhat-polkadot` source code. You can change them according to your project needs. Generally, the recommended settings for optimized outputs are the following: - - ```javascript title="hardhat.config.js" hl_lines="4-10" - resolc: { - ... - settings: { - optimizer: { - enabled: true, - parameters: 'z', - fallbackOz: true, - runs: 200, - }, - standardJson: true, - }, - ... - } - ``` - - You can check the [`ResolcConfig`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/types.ts#L26){target=\_blank} for more information about compilation settings. - -2. Compile the contract with Hardhat: - - ```bash - npx hardhat compile - ``` - -3. After successful compilation, you'll see the artifacts generated in the `artifacts-pvm` directory: - - ```bash - ls artifacts-pvm/contracts/*.sol/ - ``` - - You should see JSON files containing the contract ABI and bytecode of the contracts you compiled. - -## Set Up a Testing Environment - -Hardhat allows you to spin up a local testing environment to test and validate your smart contract functionalities before deploying to live networks. The `hardhat-polkadot` plugin provides the possibility to spin up a local node with an ETH-RPC adapter for running local tests. - -For complete isolation and control over the testing environment, you can configure Hardhat to work with a fresh local Substrate node. This approach is ideal when you want to test in a clean environment without any existing state or when you need specific node configurations. - -Configure a local node setup by adding the node binary path along with the ETH-RPC adapter path: - -```javascript title="hardhat.config.js" hl_lines="12-20" -// hardhat.config.js -require('@nomicfoundation/hardhat-toolbox'); +```mermaid +flowchart LR + plan[Plan Contract] + scaffold[Scaffold Project] + develop[Write & Update Contracts] + compile[Compile Sources] + test[Run Automated Tests] + deploy[Deploy to Target Network] + operate[Interact & Monitor] -require('@parity/hardhat-polkadot'); -/** @type import('hardhat/config').HardhatUserConfig */ -module.exports = { - ... - networks: { - hardhat: { - polkavm: true, - nodeConfig: { - nodeBinaryPath: 'INSERT_PATH_TO_SUBSTRATE_NODE', - rpcPort: 8000, - dev: true, - }, - adapterConfig: { - adapterBinaryPath: 'INSERT_PATH_TO_ETH_RPC_ADAPTER', - dev: true, - }, - }, - }, -}; + plan --> scaffold --> develop --> compile --> test --> deploy --> operate ``` -Replace `INSERT_PATH_TO_SUBSTRATE_NODE` and `INSERT_PATH_TO_ETH_RPC_ADAPTER` with the actual paths to your compiled binaries. The `dev: true` flag configures both the node and adapter for development mode. To obtain these binaries, check the [Installation](/smart-contracts/dev-environments/local-dev-node/#install-the-substrate-node-and-eth-rpc-adapter){target=\_blank} section on the Local Development Node page. +## Project Anatomy -!!! warning - If you're using the default `hardhat.config.js` created by the `hardhat-polkadot` plugin, it includes a `forking` section pointing to the Polkadot Hub TestNet. When you run `npx hardhat node`, Hardhat will start a fork of that network. To use your local node instead, comment out the `forking` section; otherwise, `npx hardhat node` will continue to use the forked network even if a local node is defined in the configuration. - -Once configured, start your chosen testing environment with: +A freshly initialized Hardhat project keeps code, configuration, and automation neatly separated: -```bash -npx hardhat node +``` +. +├── contracts/ +│ └── MyContract.sol +├── ignition/ +│ └── modules/ +├── scripts/ +│ └── interact.js +├── test/ +│ └── MyContract.test.js +└── hardhat.config.js ``` -This command will launch either the forked network or local node (depending on your configuration) along with the ETH-RPC adapter, providing you with a complete testing environment ready for contract deployment and interaction. By default, the Substrate node will be running on `localhost:8000` and the ETH-RPC adapter on `localhost:8545`. - -The output will be something like this: - -
- npx hardhat node -
- Starting server at 127.0.0.1:8000 - ../bin/substrate-node --rpc-port=8000 --dev - Starting the Eth RPC Adapter at 127.0.0.1:8545 - ../bin/eth-rpc --node-rpc-url=ws://localhost:8000 --dev - 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. - 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. - 2025-05-29 13:00:32 🌐 Connecting to node at: ws://localhost:8000 ... - 2025-05-29 13:00:32 Substrate Node - 2025-05-29 13:00:32 ✌️ version 3.0.0-dev-f73c228b7a1 - 2025-05-29 13:00:32 ❤️ by Parity Technologies <admin@parity.io>, 2017-2025 - 2025-05-29 13:00:32 📋 Chain specification: Development - 2025-05-29 13:00:32 🏷 Node name: electric-activity-4221 - 2025-05-29 13:00:32 👤 Role: AUTHORITY - 2025-05-29 13:00:32 💾 Database: RocksDb at /var/folders/f4/7rdt2m9d7j361dm453cpggbm0000gn/T/substrateOaoecu/chains/dev/db/full - 2025-05-29 13:00:36 [0] 💸 generated 1 npos voters, 1 from validators and 0 nominators - ... -
- -## Test Your Contract - -When testing your contract, be aware that [`@nomicfoundation/hardhat-toolbox/network-helpers`](https://hardhat.org/hardhat-network-helpers/docs/overview){target=\_blank} is not fully compatible with Polkadot Hub's available RPCs. Specifically, Hardhat-only helpers like `time` and `loadFixture` may not work due to missing RPC calls in the node. For more details, refer to the [Compatibility](https://github.com/paritytech/hardhat-polkadot/tree/main/packages/hardhat-polkadot-node#compatibility){target=\_blank} section in the `hardhat-revive` docs. You should avoid using helpers like `time` and `loadFixture` when writing tests. - -To run your test: - -1. Update the `hardhat.config.js` file accordingly to the [Set Up a Testing Environment](#set-up-a-testing-environment) section. - -2. Execute the following command to run your tests: - - ```bash - npx hardhat test - ``` - -## Deploy to a Local Node - -Before deploying to a live network, you can deploy your contract to a local node using [Ignition](https://hardhat.org/ignition/docs/getting-started#overview){target=\_blank} modules: - -1. Update the Hardhat configuration file to add the local network as a target for local deployment: - - ```javascript title="hardhat.config.js" hl_lines="13-16" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); - - require('@parity/hardhat-polkadot'); - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - ... - networks: { - hardhat: { - ... - }, - localNode: { - polkavm: true, - url: `http://127.0.0.1:8545`, - }, - }, - }, - }; - ``` - -2. Start a local node: - - ```bash - npx hardhat node - ``` - - This command will spawn a local Substrate node along with the ETH-RPC adapter. - -3. In a new terminal window, deploy the contract using Ignition: - - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network localNode - ``` - -## Deploying to a Live Network - -After testing your contract locally, you can deploy it to a live network. This guide will use the Polkadot Hub TestNet as the target network. Here's how to configure and deploy: - -1. Fund your deployment account with enough tokens to cover gas fees. In this case, the needed tokens are PAS (on Polkadot Hub TestNet). You can use the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank} to obtain testing tokens. +- `contracts/`: Solidity sources that define your smart contracts. +- `test/`: Automated tests written in JavaScript or TypeScript. +- `ignition/`: Deployment modules that orchestrate repeatable rollouts. +- `scripts/`: Utility scripts for deploying, validating, or interacting with contracts. +- `hardhat.config.js`: Central configuration for networks, compilers, and tooling. -2. Export your private key and save it in your Hardhat environment: +## Core Functionalities - ```bash - npx hardhat vars set PRIVATE_KEY "INSERT_PRIVATE_KEY" - ``` +### Project Setup - Replace `INSERT_PRIVATE_KEY` with your actual private key. For further details on private key exportation, refer to the article [How to export an account's private key](https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/){target=\_blank}. +Hardhat provides a structured project initialization with organized folders for contracts, tests, deployment scripts, and automation. Scaffold a workspace quickly and keep configuration in a single `hardhat.config.js` file. - !!! warning - Never reveal your private key, otherwise anyone with access to it can control your wallet and steal your funds. Store it securely and never share it publicly or commit it to version control systems. +- Learn more in the [Install and Configure](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} guide. -3. Check that your private key has been set up successfully by running: +### Contract Compilation - ```bash - npx hardhat vars get PRIVATE_KEY - ``` +Compile your Solidity smart contracts with configurable compiler versions and optimization settings. Hardhat captures build artifacts—ABI, bytecode, metadata—so you can deploy or interact with contracts from scripts and frontends. -4. Update your Hardhat configuration file with network settings for the Polkadot network you want to target: +- Deep dive into compilation in [Compile Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. - ```javascript title="hardhat.config.js" hl_lines="18-22" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); +### Testing Environment - require('@parity/hardhat-polkadot'); - const { vars } = require('hardhat/config'); +Run automated tests against a local Hardhat node, simulate transactions, and debug contract behavior before deploying to public networks. The built-in testing stack uses familiar JavaScript tooling such as Mocha and Chai. - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - ... - networks: { - hardhat: { - ... - }, - localNode: { - ... - }, - polkadotHubTestnet: { - polkavm: true, - url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - accounts: [vars.get('PRIVATE_KEY')], - }, - }, - }, - }; - ``` +- Master testing capabilities in [Test Your Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. -6. Deploy your contract using Ignition: +### Deployment - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network polkadotHubTestnet - ``` +Ship your contracts with reusable deployment scripts or Hardhat Ignition modules. Manage credentials securely, target multiple networks, and repeat deployments with confidence. -## Interacting with Your Contract +- Follow deployment steps in [Deploy Smart Contracts](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank}. -Once deployed, you can create a script to interact with your contract. To do so, create a file called `scripts/interact.js` and add some logic to interact with the contract. +### Contract Interaction -For example, for the default `MyToken.sol` contract, you can use the following file that connects to the contract at its address and retrieves the `unlockTime`, which represents when funds can be withdrawn. The script converts this timestamp into a readable date and logs it. It then checks the contract's balance and displays it. Finally, it attempts to call the withdrawal function on the contract, but it catches and logs the error message if the withdrawal is not yet allowed (e.g., before `unlockTime`). +Create scripts to interact with deployed contracts, read state, execute transactions, and automate maintenance tasks using your generated ABI. -```javascript title="interact.js" -const hre = require('hardhat'); +- See practical tips in [Interact with Smart Contracts](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank}. -async function main() { - // Get the contract factory - const MyToken = await hre.ethers.getContractFactory('MyToken'); - // Replace with your deployed contract address - const contractAddress = 'INSERT_CONTRACT_ADDRESS'; +## Where to Go Next - // Attach to existing contract - const token = await MyToken.attach(contractAddress); +Ready to explore the specifics? Dive into these guides to continue your Hardhat journey: - // Get signers - const [deployer] = await hre.ethers.getSigners(); +
- // Read contract state - const name = await token.name(); - const symbol = await token.symbol(); - const totalSupply = await token.totalSupply(); - const balance = await token.balanceOf(deployer.address); +- Guide __Install and Configure Hardhat__ - console.log(`Token: ${name} (${symbol})`); - console.log( - `Total Supply: ${hre.ethers.formatUnits(totalSupply, 18)} tokens`, - ); - console.log( - `Deployer Balance: ${hre.ethers.formatUnits(balance, 18)} tokens`, - ); -} + --- -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); + Initialize your workspace and adjust project settings for this toolchain. -``` + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} -Run your interaction script: +- Guide __Compile Smart Contracts__ -```bash -npx hardhat run scripts/interact.js --network polkadotHubTestnet -``` + --- -## Upgrading the Plugin + Configure compiler options and generate deployable artifacts. -If you already have a Hardhat Polkadot project and want to upgrade to a newer version of the plugin, to avoid errors (for example, `Cannot find module 'run-container'`), you can clean your dependencies by running the following commands: + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} -```bash -rm -rf node_modules package-lock.json -``` +- Guide __Test Your Smart Contracts__ -After that, you can upgrade the plugin to the latest version by running the following commands: + --- -```bash -npm install --save-dev @parity/hardhat-polkadot@latest -npm install -``` + Build automated tests and run them against a local node. -Consider using [Node.js](https://nodejs.org/){target=\_blank} 22.18+ and [npm](https://www.npmjs.com/){target=\_blank} version 10.9.0+ to avoid issues with the plugin. + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} -## Where to Go Next +- Guide __Deploy Smart Contracts__ -Hardhat provides a powerful environment for developing, testing, and deploying smart contracts on Polkadot Hub. Its plugin architecture allows seamless integration with PolkaVM through the `hardhat-resolc` and `hardhat-revive-node` plugins. + --- -Explore more about smart contracts through these resources: + Roll out contracts to local, test, or production networks with repeatable scripts. -
+ [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} -- Guide __Get Started with Smart Contracts__ +- Guide __Interact with Smart Contracts__ --- - Learn how to get started with smart contracts + Script on-chain interactions and automate maintenance tasks. - [:octicons-arrow-right-24: Get Started](/smart-contracts/get-started/) + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank} - External __Hardhat Documentation__ --- - Learn more about Hardhat's advanced features and best practices. + Explore Hardhat's official documentation for advanced features and best practices. - [:octicons-arrow-right-24: Get Started](https://hardhat.org/docs){target=\_blank} + [:octicons-arrow-right-24: Learn More](https://hardhat.org/docs){target=\_blank} - External __OpenZeppelin Contracts__ --- - Test your skills by deploying contracts with prebuilt templates. + Use prebuilt, audited contract templates to bootstrap your projects. - [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank} + [:octicons-arrow-right-24: Explore](https://www.openzeppelin.com/solidity-contracts){target=\_blank}
diff --git a/.ai/categories/tooling.md b/.ai/categories/tooling.md index d5f748831..8364c8937 100644 --- a/.ai/categories/tooling.md +++ b/.ai/categories/tooling.md @@ -10983,464 +10983,150 @@ Page Title: Use Hardhat with Polkadot Hub - Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md - Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/get-started/ -- Summary: Learn how to create, compile, test, and deploy smart contracts on Polkadot Hub using Hardhat, a powerful development environment for blockchain developers. +- Summary: Overview of Hardhat, a powerful development environment for creating, compiling, testing, and deploying smart contracts on Polkadot Hub. # Hardhat -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -
-- :octicons-code-16:{ .lg .middle } __Test and Deploy with Hardhat__ - - --- - - Master Solidity smart contract development with Hardhat. Learn testing, deployment, and network interaction in one comprehensive tutorial. - -
- [:octicons-arrow-right-24: Get Started](/tutorials/smart-contracts/launch-your-first-project/test-and-deploy-with-hardhat){target=\_blank} - -
- -!!! note "Contracts Code Blob Size Disclaimer" - The maximum contract code blob size on Polkadot Hub networks is _100 kilobytes_, significantly larger than Ethereum’s EVM limit of 24 kilobytes. - - For detailed comparisons and migration guidelines, see the [EVM vs. PolkaVM](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#current-memory-limits){target=\_blank} documentation page. - ## Overview -Hardhat is a robust development environment for Ethereum-compatible chains that makes smart contract development more efficient. This guide walks you through the essentials of using Hardhat to create, compile, test, and deploy smart contracts on Polkadot Hub. - -## Prerequisites - -Before getting started, ensure you have: - -- [Node.js](https://nodejs.org/){target=\_blank} (v16.0.0 or later) and npm installed. - - Note: Use Node.js 22.5+ and npm version 10.9.0+ to avoid issues with the Polkadot plugin. -- Basic understanding of Solidity programming. -- Some PAS test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}). To learn how to get test tokens, check out the [Test Tokens](/smart-contracts/connect/#test-tokens){target=\_blank} section. - -## Set Up Hardhat - -1. Create a new directory for your project and navigate into it: - - ```bash - mkdir hardhat-example - cd hardhat-example - ``` - -2. Initialize a new npm project: - - ```bash - npm init -y - ``` - -3. To interact with Polkadot, Hardhat requires the following plugin to compile contracts to PolkaVM bytecode and to spawn a local node compatible with PolkaVM: - - ```bash - npm install --save-dev @parity/hardhat-polkadot@0.1.9 - ``` - -4. Create a Hardhat project: - - ```bash - npx hardhat-polkadot init - ``` - - Select **Create a JavaScript project** when prompted and follow the instructions. After that, your project will be created with three main folders: - - - **`contracts`**: Where your Solidity smart contracts live. - - **`test`**: Contains your test files that validate contract functionality. - - **`ignition`**: Deployment modules for safely deploying your contracts to various networks. - -5. Add the following folder to the `.gitignore` file if it is not already there: - - ```bash - echo '/ignition/deployments/' >> .gitignore - ``` - -6. Finish the setup by installing all the dependencies: - - ```bash - npm install - ``` - - !!! note - This last step is needed to set up the `hardhat-polkadot` plugin. It will install the `@parity/hardhat-polkadot` package and all its dependencies. In the future, the plugin will handle this automatically. - -## Compile Your Contract - -The plugin will compile your Solidity contracts for Solidity versions `0.8.0` and higher to be PolkaVM compatible. When compiling your contract, there are two ways to configure your compilation process: - -- **npm compiler**: Uses library [@parity/resolc](https://www.npmjs.com/package/@parity/resolc){target=\_blank} for simplicity and ease of use. -- **Binary compiler**: Uses your local `resolc` binary directly for more control and configuration options. - -To compile your project, follow these instructions: - -1. Modify your Hardhat configuration file to specify which compilation process you will be using and activate the `polkavm` flag in the Hardhat network: - - === "npm Configuration" - - ```javascript title="hardhat.config.js" hl_lines="9-11 14" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); - - require('@parity/hardhat-polkadot'); - - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - solidity: '0.8.28', - resolc: { - compilerSource: 'npm', - }, - networks: { - hardhat: { - polkavm: true, - }, - }, - }; - ``` - - === "Binary Configuration" - - ```javascript title="hardhat.config.js" hl_lines="9-14 17" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); - - require('@parity/hardhat-polkadot'); - - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - solidity: '0.8.28', - resolc: { - compilerSource: 'binary', - settings: { - compilerPath: 'INSERT_PATH_TO_RESOLC_COMPILER', - }, - }, - networks: { - hardhat: { - polkavm: true, - }, - }, - }; - ``` - - For the binary configuration, replace `INSERT_PATH_TO_RESOLC_COMPILER` with the proper path to the binary. To obtain the binary, check the [releases](https://github.com/paritytech/revive/releases){target=\_blank} section of the `resolc` compiler, and download the latest version. - - The default settings used can be found in the [`constants.ts`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/constants.ts#L8-L23){target=\_blank} file of the `hardhat-polkadot` source code. You can change them according to your project needs. Generally, the recommended settings for optimized outputs are the following: - - ```javascript title="hardhat.config.js" hl_lines="4-10" - resolc: { - ... - settings: { - optimizer: { - enabled: true, - parameters: 'z', - fallbackOz: true, - runs: 200, - }, - standardJson: true, - }, - ... - } - ``` - - You can check the [`ResolcConfig`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/types.ts#L26){target=\_blank} for more information about compilation settings. - -2. Compile the contract with Hardhat: - - ```bash - npx hardhat compile - ``` - -3. After successful compilation, you'll see the artifacts generated in the `artifacts-pvm` directory: - - ```bash - ls artifacts-pvm/contracts/*.sol/ - ``` - - You should see JSON files containing the contract ABI and bytecode of the contracts you compiled. - -## Set Up a Testing Environment +Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer. -Hardhat allows you to spin up a local testing environment to test and validate your smart contract functionalities before deploying to live networks. The `hardhat-polkadot` plugin provides the possibility to spin up a local node with an ETH-RPC adapter for running local tests. +Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit including compilation, local testing nodes, debugging tools, and deployment automation. -For complete isolation and control over the testing environment, you can configure Hardhat to work with a fresh local Substrate node. This approach is ideal when you want to test in a clean environment without any existing state or when you need specific node configurations. +## Hardhat Workflow -Configure a local node setup by adding the node binary path along with the ETH-RPC adapter path: +From the first sketch of a contract to ongoing operations, Hardhat encourages a repeatable cycle: define the functionality you need, scaffold the workspace, write and refine Solidity code, compile it into deployable artifacts, validate behavior with automated tests, deploy confidently to the target network, and keep iterating with scripts that monitor and interact with what you shipped. -```javascript title="hardhat.config.js" hl_lines="12-20" -// hardhat.config.js -require('@nomicfoundation/hardhat-toolbox'); +```mermaid +flowchart LR + plan[Plan Contract] + scaffold[Scaffold Project] + develop[Write & Update Contracts] + compile[Compile Sources] + test[Run Automated Tests] + deploy[Deploy to Target Network] + operate[Interact & Monitor] -require('@parity/hardhat-polkadot'); -/** @type import('hardhat/config').HardhatUserConfig */ -module.exports = { - ... - networks: { - hardhat: { - polkavm: true, - nodeConfig: { - nodeBinaryPath: 'INSERT_PATH_TO_SUBSTRATE_NODE', - rpcPort: 8000, - dev: true, - }, - adapterConfig: { - adapterBinaryPath: 'INSERT_PATH_TO_ETH_RPC_ADAPTER', - dev: true, - }, - }, - }, -}; + plan --> scaffold --> develop --> compile --> test --> deploy --> operate ``` -Replace `INSERT_PATH_TO_SUBSTRATE_NODE` and `INSERT_PATH_TO_ETH_RPC_ADAPTER` with the actual paths to your compiled binaries. The `dev: true` flag configures both the node and adapter for development mode. To obtain these binaries, check the [Installation](/smart-contracts/dev-environments/local-dev-node/#install-the-substrate-node-and-eth-rpc-adapter){target=\_blank} section on the Local Development Node page. - -!!! warning - If you're using the default `hardhat.config.js` created by the `hardhat-polkadot` plugin, it includes a `forking` section pointing to the Polkadot Hub TestNet. When you run `npx hardhat node`, Hardhat will start a fork of that network. To use your local node instead, comment out the `forking` section; otherwise, `npx hardhat node` will continue to use the forked network even if a local node is defined in the configuration. +## Project Anatomy -Once configured, start your chosen testing environment with: +A freshly initialized Hardhat project keeps code, configuration, and automation neatly separated: -```bash -npx hardhat node +``` +. +├── contracts/ +│ └── MyContract.sol +├── ignition/ +│ └── modules/ +├── scripts/ +│ └── interact.js +├── test/ +│ └── MyContract.test.js +└── hardhat.config.js ``` -This command will launch either the forked network or local node (depending on your configuration) along with the ETH-RPC adapter, providing you with a complete testing environment ready for contract deployment and interaction. By default, the Substrate node will be running on `localhost:8000` and the ETH-RPC adapter on `localhost:8545`. - -The output will be something like this: - -
- npx hardhat node -
- Starting server at 127.0.0.1:8000 - ../bin/substrate-node --rpc-port=8000 --dev - Starting the Eth RPC Adapter at 127.0.0.1:8545 - ../bin/eth-rpc --node-rpc-url=ws://localhost:8000 --dev - 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. - 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. - 2025-05-29 13:00:32 🌐 Connecting to node at: ws://localhost:8000 ... - 2025-05-29 13:00:32 Substrate Node - 2025-05-29 13:00:32 ✌️ version 3.0.0-dev-f73c228b7a1 - 2025-05-29 13:00:32 ❤️ by Parity Technologies <admin@parity.io>, 2017-2025 - 2025-05-29 13:00:32 📋 Chain specification: Development - 2025-05-29 13:00:32 🏷 Node name: electric-activity-4221 - 2025-05-29 13:00:32 👤 Role: AUTHORITY - 2025-05-29 13:00:32 💾 Database: RocksDb at /var/folders/f4/7rdt2m9d7j361dm453cpggbm0000gn/T/substrateOaoecu/chains/dev/db/full - 2025-05-29 13:00:36 [0] 💸 generated 1 npos voters, 1 from validators and 0 nominators - ... -
- -## Test Your Contract - -When testing your contract, be aware that [`@nomicfoundation/hardhat-toolbox/network-helpers`](https://hardhat.org/hardhat-network-helpers/docs/overview){target=\_blank} is not fully compatible with Polkadot Hub's available RPCs. Specifically, Hardhat-only helpers like `time` and `loadFixture` may not work due to missing RPC calls in the node. For more details, refer to the [Compatibility](https://github.com/paritytech/hardhat-polkadot/tree/main/packages/hardhat-polkadot-node#compatibility){target=\_blank} section in the `hardhat-revive` docs. You should avoid using helpers like `time` and `loadFixture` when writing tests. - -To run your test: - -1. Update the `hardhat.config.js` file accordingly to the [Set Up a Testing Environment](#set-up-a-testing-environment) section. - -2. Execute the following command to run your tests: - - ```bash - npx hardhat test - ``` - -## Deploy to a Local Node - -Before deploying to a live network, you can deploy your contract to a local node using [Ignition](https://hardhat.org/ignition/docs/getting-started#overview){target=\_blank} modules: - -1. Update the Hardhat configuration file to add the local network as a target for local deployment: - - ```javascript title="hardhat.config.js" hl_lines="13-16" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); - - require('@parity/hardhat-polkadot'); - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - ... - networks: { - hardhat: { - ... - }, - localNode: { - polkavm: true, - url: `http://127.0.0.1:8545`, - }, - }, - }, - }; - ``` - -2. Start a local node: - - ```bash - npx hardhat node - ``` - - This command will spawn a local Substrate node along with the ETH-RPC adapter. - -3. In a new terminal window, deploy the contract using Ignition: - - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network localNode - ``` - -## Deploying to a Live Network - -After testing your contract locally, you can deploy it to a live network. This guide will use the Polkadot Hub TestNet as the target network. Here's how to configure and deploy: +- `contracts/`: Solidity sources that define your smart contracts. +- `test/`: Automated tests written in JavaScript or TypeScript. +- `ignition/`: Deployment modules that orchestrate repeatable rollouts. +- `scripts/`: Utility scripts for deploying, validating, or interacting with contracts. +- `hardhat.config.js`: Central configuration for networks, compilers, and tooling. -1. Fund your deployment account with enough tokens to cover gas fees. In this case, the needed tokens are PAS (on Polkadot Hub TestNet). You can use the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank} to obtain testing tokens. +## Core Functionalities -2. Export your private key and save it in your Hardhat environment: +### Project Setup - ```bash - npx hardhat vars set PRIVATE_KEY "INSERT_PRIVATE_KEY" - ``` +Hardhat provides a structured project initialization with organized folders for contracts, tests, deployment scripts, and automation. Scaffold a workspace quickly and keep configuration in a single `hardhat.config.js` file. - Replace `INSERT_PRIVATE_KEY` with your actual private key. For further details on private key exportation, refer to the article [How to export an account's private key](https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/){target=\_blank}. +- Learn more in the [Install and Configure](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} guide. - !!! warning - Never reveal your private key, otherwise anyone with access to it can control your wallet and steal your funds. Store it securely and never share it publicly or commit it to version control systems. +### Contract Compilation -3. Check that your private key has been set up successfully by running: +Compile your Solidity smart contracts with configurable compiler versions and optimization settings. Hardhat captures build artifacts—ABI, bytecode, metadata—so you can deploy or interact with contracts from scripts and frontends. - ```bash - npx hardhat vars get PRIVATE_KEY - ``` +- Deep dive into compilation in [Compile Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. -4. Update your Hardhat configuration file with network settings for the Polkadot network you want to target: +### Testing Environment - ```javascript title="hardhat.config.js" hl_lines="18-22" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); +Run automated tests against a local Hardhat node, simulate transactions, and debug contract behavior before deploying to public networks. The built-in testing stack uses familiar JavaScript tooling such as Mocha and Chai. - require('@parity/hardhat-polkadot'); - const { vars } = require('hardhat/config'); - - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - ... - networks: { - hardhat: { - ... - }, - localNode: { - ... - }, - polkadotHubTestnet: { - polkavm: true, - url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - accounts: [vars.get('PRIVATE_KEY')], - }, - }, - }, - }; - ``` +- Master testing capabilities in [Test Your Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. -6. Deploy your contract using Ignition: +### Deployment - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network polkadotHubTestnet - ``` +Ship your contracts with reusable deployment scripts or Hardhat Ignition modules. Manage credentials securely, target multiple networks, and repeat deployments with confidence. -## Interacting with Your Contract +- Follow deployment steps in [Deploy Smart Contracts](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank}. -Once deployed, you can create a script to interact with your contract. To do so, create a file called `scripts/interact.js` and add some logic to interact with the contract. +### Contract Interaction -For example, for the default `MyToken.sol` contract, you can use the following file that connects to the contract at its address and retrieves the `unlockTime`, which represents when funds can be withdrawn. The script converts this timestamp into a readable date and logs it. It then checks the contract's balance and displays it. Finally, it attempts to call the withdrawal function on the contract, but it catches and logs the error message if the withdrawal is not yet allowed (e.g., before `unlockTime`). +Create scripts to interact with deployed contracts, read state, execute transactions, and automate maintenance tasks using your generated ABI. -```javascript title="interact.js" -const hre = require('hardhat'); +- See practical tips in [Interact with Smart Contracts](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank}. -async function main() { - // Get the contract factory - const MyToken = await hre.ethers.getContractFactory('MyToken'); - // Replace with your deployed contract address - const contractAddress = 'INSERT_CONTRACT_ADDRESS'; +## Where to Go Next - // Attach to existing contract - const token = await MyToken.attach(contractAddress); +Ready to explore the specifics? Dive into these guides to continue your Hardhat journey: - // Get signers - const [deployer] = await hre.ethers.getSigners(); +
- // Read contract state - const name = await token.name(); - const symbol = await token.symbol(); - const totalSupply = await token.totalSupply(); - const balance = await token.balanceOf(deployer.address); +- Guide __Install and Configure Hardhat__ - console.log(`Token: ${name} (${symbol})`); - console.log( - `Total Supply: ${hre.ethers.formatUnits(totalSupply, 18)} tokens`, - ); - console.log( - `Deployer Balance: ${hre.ethers.formatUnits(balance, 18)} tokens`, - ); -} + --- -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); + Initialize your workspace and adjust project settings for this toolchain. -``` + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} -Run your interaction script: +- Guide __Compile Smart Contracts__ -```bash -npx hardhat run scripts/interact.js --network polkadotHubTestnet -``` + --- -## Upgrading the Plugin + Configure compiler options and generate deployable artifacts. -If you already have a Hardhat Polkadot project and want to upgrade to a newer version of the plugin, to avoid errors (for example, `Cannot find module 'run-container'`), you can clean your dependencies by running the following commands: + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} -```bash -rm -rf node_modules package-lock.json -``` +- Guide __Test Your Smart Contracts__ -After that, you can upgrade the plugin to the latest version by running the following commands: + --- -```bash -npm install --save-dev @parity/hardhat-polkadot@latest -npm install -``` + Build automated tests and run them against a local node. -Consider using [Node.js](https://nodejs.org/){target=\_blank} 22.18+ and [npm](https://www.npmjs.com/){target=\_blank} version 10.9.0+ to avoid issues with the plugin. + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} -## Where to Go Next +- Guide __Deploy Smart Contracts__ -Hardhat provides a powerful environment for developing, testing, and deploying smart contracts on Polkadot Hub. Its plugin architecture allows seamless integration with PolkaVM through the `hardhat-resolc` and `hardhat-revive-node` plugins. + --- -Explore more about smart contracts through these resources: + Roll out contracts to local, test, or production networks with repeatable scripts. -
+ [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} -- Guide __Get Started with Smart Contracts__ +- Guide __Interact with Smart Contracts__ --- - Learn how to get started with smart contracts + Script on-chain interactions and automate maintenance tasks. - [:octicons-arrow-right-24: Get Started](/smart-contracts/get-started/) + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank} - External __Hardhat Documentation__ --- - Learn more about Hardhat's advanced features and best practices. + Explore Hardhat's official documentation for advanced features and best practices. - [:octicons-arrow-right-24: Get Started](https://hardhat.org/docs){target=\_blank} + [:octicons-arrow-right-24: Learn More](https://hardhat.org/docs){target=\_blank} - External __OpenZeppelin Contracts__ --- - Test your skills by deploying contracts with prebuilt templates. + Use prebuilt, audited contract templates to bootstrap your projects. - [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank} + [:octicons-arrow-right-24: Explore](https://www.openzeppelin.com/solidity-contracts){target=\_blank}
diff --git a/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md b/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md index 2cfb71e8c..08e237fa1 100644 --- a/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md +++ b/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md @@ -1,465 +1,151 @@ --- title: Use Hardhat with Polkadot Hub -description: Learn how to create, compile, test, and deploy smart contracts on Polkadot Hub using Hardhat, a powerful development environment for blockchain developers. +description: Overview of Hardhat, a powerful development environment for creating, compiling, testing, and deploying smart contracts on Polkadot Hub. categories: Smart Contracts, Tooling url: https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/get-started/ --- # Hardhat -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -
-- :octicons-code-16:{ .lg .middle } __Test and Deploy with Hardhat__ - - --- - - Master Solidity smart contract development with Hardhat. Learn testing, deployment, and network interaction in one comprehensive tutorial. - -
- [:octicons-arrow-right-24: Get Started](/tutorials/smart-contracts/launch-your-first-project/test-and-deploy-with-hardhat){target=\_blank} - -
- -!!! note "Contracts Code Blob Size Disclaimer" - The maximum contract code blob size on Polkadot Hub networks is _100 kilobytes_, significantly larger than Ethereum’s EVM limit of 24 kilobytes. - - For detailed comparisons and migration guidelines, see the [EVM vs. PolkaVM](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#current-memory-limits){target=\_blank} documentation page. - ## Overview -Hardhat is a robust development environment for Ethereum-compatible chains that makes smart contract development more efficient. This guide walks you through the essentials of using Hardhat to create, compile, test, and deploy smart contracts on Polkadot Hub. - -## Prerequisites - -Before getting started, ensure you have: - -- [Node.js](https://nodejs.org/){target=\_blank} (v16.0.0 or later) and npm installed. - - Note: Use Node.js 22.5+ and npm version 10.9.0+ to avoid issues with the Polkadot plugin. -- Basic understanding of Solidity programming. -- Some PAS test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}). To learn how to get test tokens, check out the [Test Tokens](/smart-contracts/connect/#test-tokens){target=\_blank} section. - -## Set Up Hardhat - -1. Create a new directory for your project and navigate into it: - - ```bash - mkdir hardhat-example - cd hardhat-example - ``` - -2. Initialize a new npm project: - - ```bash - npm init -y - ``` - -3. To interact with Polkadot, Hardhat requires the following plugin to compile contracts to PolkaVM bytecode and to spawn a local node compatible with PolkaVM: - - ```bash - npm install --save-dev @parity/hardhat-polkadot@0.1.9 - ``` - -4. Create a Hardhat project: - - ```bash - npx hardhat-polkadot init - ``` - - Select **Create a JavaScript project** when prompted and follow the instructions. After that, your project will be created with three main folders: - - - **`contracts`**: Where your Solidity smart contracts live. - - **`test`**: Contains your test files that validate contract functionality. - - **`ignition`**: Deployment modules for safely deploying your contracts to various networks. - -5. Add the following folder to the `.gitignore` file if it is not already there: - - ```bash - echo '/ignition/deployments/' >> .gitignore - ``` - -6. Finish the setup by installing all the dependencies: - - ```bash - npm install - ``` - - !!! note - This last step is needed to set up the `hardhat-polkadot` plugin. It will install the `@parity/hardhat-polkadot` package and all its dependencies. In the future, the plugin will handle this automatically. - -## Compile Your Contract - -The plugin will compile your Solidity contracts for Solidity versions `0.8.0` and higher to be PolkaVM compatible. When compiling your contract, there are two ways to configure your compilation process: - -- **npm compiler**: Uses library [@parity/resolc](https://www.npmjs.com/package/@parity/resolc){target=\_blank} for simplicity and ease of use. -- **Binary compiler**: Uses your local `resolc` binary directly for more control and configuration options. - -To compile your project, follow these instructions: - -1. Modify your Hardhat configuration file to specify which compilation process you will be using and activate the `polkavm` flag in the Hardhat network: - - === "npm Configuration" - - ```javascript title="hardhat.config.js" hl_lines="9-11 14" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); +Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer. - require('@parity/hardhat-polkadot'); +Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit including compilation, local testing nodes, debugging tools, and deployment automation. - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - solidity: '0.8.28', - resolc: { - compilerSource: 'npm', - }, - networks: { - hardhat: { - polkavm: true, - }, - }, - }; - ``` +## Hardhat Workflow - === "Binary Configuration" +From the first sketch of a contract to ongoing operations, Hardhat encourages a repeatable cycle: define the functionality you need, scaffold the workspace, write and refine Solidity code, compile it into deployable artifacts, validate behavior with automated tests, deploy confidently to the target network, and keep iterating with scripts that monitor and interact with what you shipped. - ```javascript title="hardhat.config.js" hl_lines="9-14 17" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); +```mermaid +flowchart LR + plan[Plan Contract] + scaffold[Scaffold Project] + develop[Write & Update Contracts] + compile[Compile Sources] + test[Run Automated Tests] + deploy[Deploy to Target Network] + operate[Interact & Monitor] - require('@parity/hardhat-polkadot'); - - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - solidity: '0.8.28', - resolc: { - compilerSource: 'binary', - settings: { - compilerPath: 'INSERT_PATH_TO_RESOLC_COMPILER', - }, - }, - networks: { - hardhat: { - polkavm: true, - }, - }, - }; - ``` - - For the binary configuration, replace `INSERT_PATH_TO_RESOLC_COMPILER` with the proper path to the binary. To obtain the binary, check the [releases](https://github.com/paritytech/revive/releases){target=\_blank} section of the `resolc` compiler, and download the latest version. - - The default settings used can be found in the [`constants.ts`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/constants.ts#L8-L23){target=\_blank} file of the `hardhat-polkadot` source code. You can change them according to your project needs. Generally, the recommended settings for optimized outputs are the following: - - ```javascript title="hardhat.config.js" hl_lines="4-10" - resolc: { - ... - settings: { - optimizer: { - enabled: true, - parameters: 'z', - fallbackOz: true, - runs: 200, - }, - standardJson: true, - }, - ... - } - ``` - - You can check the [`ResolcConfig`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/types.ts#L26){target=\_blank} for more information about compilation settings. - -2. Compile the contract with Hardhat: - - ```bash - npx hardhat compile - ``` - -3. After successful compilation, you'll see the artifacts generated in the `artifacts-pvm` directory: - - ```bash - ls artifacts-pvm/contracts/*.sol/ - ``` - - You should see JSON files containing the contract ABI and bytecode of the contracts you compiled. - -## Set Up a Testing Environment - -Hardhat allows you to spin up a local testing environment to test and validate your smart contract functionalities before deploying to live networks. The `hardhat-polkadot` plugin provides the possibility to spin up a local node with an ETH-RPC adapter for running local tests. - -For complete isolation and control over the testing environment, you can configure Hardhat to work with a fresh local Substrate node. This approach is ideal when you want to test in a clean environment without any existing state or when you need specific node configurations. - -Configure a local node setup by adding the node binary path along with the ETH-RPC adapter path: - -```javascript title="hardhat.config.js" hl_lines="12-20" -// hardhat.config.js -require('@nomicfoundation/hardhat-toolbox'); - -require('@parity/hardhat-polkadot'); -/** @type import('hardhat/config').HardhatUserConfig */ -module.exports = { - ... - networks: { - hardhat: { - polkavm: true, - nodeConfig: { - nodeBinaryPath: 'INSERT_PATH_TO_SUBSTRATE_NODE', - rpcPort: 8000, - dev: true, - }, - adapterConfig: { - adapterBinaryPath: 'INSERT_PATH_TO_ETH_RPC_ADAPTER', - dev: true, - }, - }, - }, -}; + plan --> scaffold --> develop --> compile --> test --> deploy --> operate ``` -Replace `INSERT_PATH_TO_SUBSTRATE_NODE` and `INSERT_PATH_TO_ETH_RPC_ADAPTER` with the actual paths to your compiled binaries. The `dev: true` flag configures both the node and adapter for development mode. To obtain these binaries, check the [Installation](/smart-contracts/dev-environments/local-dev-node/#install-the-substrate-node-and-eth-rpc-adapter){target=\_blank} section on the Local Development Node page. - -!!! warning - If you're using the default `hardhat.config.js` created by the `hardhat-polkadot` plugin, it includes a `forking` section pointing to the Polkadot Hub TestNet. When you run `npx hardhat node`, Hardhat will start a fork of that network. To use your local node instead, comment out the `forking` section; otherwise, `npx hardhat node` will continue to use the forked network even if a local node is defined in the configuration. +## Project Anatomy -Once configured, start your chosen testing environment with: +A freshly initialized Hardhat project keeps code, configuration, and automation neatly separated: -```bash -npx hardhat node +``` +. +├── contracts/ +│ └── MyContract.sol +├── ignition/ +│ └── modules/ +├── scripts/ +│ └── interact.js +├── test/ +│ └── MyContract.test.js +└── hardhat.config.js ``` -This command will launch either the forked network or local node (depending on your configuration) along with the ETH-RPC adapter, providing you with a complete testing environment ready for contract deployment and interaction. By default, the Substrate node will be running on `localhost:8000` and the ETH-RPC adapter on `localhost:8545`. - -The output will be something like this: - -
- npx hardhat node -
- Starting server at 127.0.0.1:8000 - ../bin/substrate-node --rpc-port=8000 --dev - Starting the Eth RPC Adapter at 127.0.0.1:8545 - ../bin/eth-rpc --node-rpc-url=ws://localhost:8000 --dev - 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. - 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled. - 2025-05-29 13:00:32 🌐 Connecting to node at: ws://localhost:8000 ... - 2025-05-29 13:00:32 Substrate Node - 2025-05-29 13:00:32 ✌️ version 3.0.0-dev-f73c228b7a1 - 2025-05-29 13:00:32 ❤️ by Parity Technologies <admin@parity.io>, 2017-2025 - 2025-05-29 13:00:32 📋 Chain specification: Development - 2025-05-29 13:00:32 🏷 Node name: electric-activity-4221 - 2025-05-29 13:00:32 👤 Role: AUTHORITY - 2025-05-29 13:00:32 💾 Database: RocksDb at /var/folders/f4/7rdt2m9d7j361dm453cpggbm0000gn/T/substrateOaoecu/chains/dev/db/full - 2025-05-29 13:00:36 [0] 💸 generated 1 npos voters, 1 from validators and 0 nominators - ... -
- -## Test Your Contract - -When testing your contract, be aware that [`@nomicfoundation/hardhat-toolbox/network-helpers`](https://hardhat.org/hardhat-network-helpers/docs/overview){target=\_blank} is not fully compatible with Polkadot Hub's available RPCs. Specifically, Hardhat-only helpers like `time` and `loadFixture` may not work due to missing RPC calls in the node. For more details, refer to the [Compatibility](https://github.com/paritytech/hardhat-polkadot/tree/main/packages/hardhat-polkadot-node#compatibility){target=\_blank} section in the `hardhat-revive` docs. You should avoid using helpers like `time` and `loadFixture` when writing tests. - -To run your test: - -1. Update the `hardhat.config.js` file accordingly to the [Set Up a Testing Environment](#set-up-a-testing-environment) section. - -2. Execute the following command to run your tests: - - ```bash - npx hardhat test - ``` - -## Deploy to a Local Node - -Before deploying to a live network, you can deploy your contract to a local node using [Ignition](https://hardhat.org/ignition/docs/getting-started#overview){target=\_blank} modules: - -1. Update the Hardhat configuration file to add the local network as a target for local deployment: - - ```javascript title="hardhat.config.js" hl_lines="13-16" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); - - require('@parity/hardhat-polkadot'); - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - ... - networks: { - hardhat: { - ... - }, - localNode: { - polkavm: true, - url: `http://127.0.0.1:8545`, - }, - }, - }, - }; - ``` - -2. Start a local node: - - ```bash - npx hardhat node - ``` - - This command will spawn a local Substrate node along with the ETH-RPC adapter. - -3. In a new terminal window, deploy the contract using Ignition: - - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network localNode - ``` - -## Deploying to a Live Network - -After testing your contract locally, you can deploy it to a live network. This guide will use the Polkadot Hub TestNet as the target network. Here's how to configure and deploy: - -1. Fund your deployment account with enough tokens to cover gas fees. In this case, the needed tokens are PAS (on Polkadot Hub TestNet). You can use the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank} to obtain testing tokens. +- `contracts/`: Solidity sources that define your smart contracts. +- `test/`: Automated tests written in JavaScript or TypeScript. +- `ignition/`: Deployment modules that orchestrate repeatable rollouts. +- `scripts/`: Utility scripts for deploying, validating, or interacting with contracts. +- `hardhat.config.js`: Central configuration for networks, compilers, and tooling. -2. Export your private key and save it in your Hardhat environment: +## Core Functionalities - ```bash - npx hardhat vars set PRIVATE_KEY "INSERT_PRIVATE_KEY" - ``` +### Project Setup - Replace `INSERT_PRIVATE_KEY` with your actual private key. For further details on private key exportation, refer to the article [How to export an account's private key](https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/){target=\_blank}. +Hardhat provides a structured project initialization with organized folders for contracts, tests, deployment scripts, and automation. Scaffold a workspace quickly and keep configuration in a single `hardhat.config.js` file. - !!! warning - Never reveal your private key, otherwise anyone with access to it can control your wallet and steal your funds. Store it securely and never share it publicly or commit it to version control systems. +- Learn more in the [Install and Configure](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} guide. -3. Check that your private key has been set up successfully by running: +### Contract Compilation - ```bash - npx hardhat vars get PRIVATE_KEY - ``` +Compile your Solidity smart contracts with configurable compiler versions and optimization settings. Hardhat captures build artifacts—ABI, bytecode, metadata—so you can deploy or interact with contracts from scripts and frontends. -4. Update your Hardhat configuration file with network settings for the Polkadot network you want to target: +- Deep dive into compilation in [Compile Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. - ```javascript title="hardhat.config.js" hl_lines="18-22" - // hardhat.config.js - require('@nomicfoundation/hardhat-toolbox'); +### Testing Environment - require('@parity/hardhat-polkadot'); - const { vars } = require('hardhat/config'); +Run automated tests against a local Hardhat node, simulate transactions, and debug contract behavior before deploying to public networks. The built-in testing stack uses familiar JavaScript tooling such as Mocha and Chai. - /** @type import('hardhat/config').HardhatUserConfig */ - module.exports = { - ... - networks: { - hardhat: { - ... - }, - localNode: { - ... - }, - polkadotHubTestnet: { - polkavm: true, - url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - accounts: [vars.get('PRIVATE_KEY')], - }, - }, - }, - }; - ``` +- Master testing capabilities in [Test Your Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. -6. Deploy your contract using Ignition: +### Deployment - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network polkadotHubTestnet - ``` +Ship your contracts with reusable deployment scripts or Hardhat Ignition modules. Manage credentials securely, target multiple networks, and repeat deployments with confidence. -## Interacting with Your Contract +- Follow deployment steps in [Deploy Smart Contracts](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank}. -Once deployed, you can create a script to interact with your contract. To do so, create a file called `scripts/interact.js` and add some logic to interact with the contract. +### Contract Interaction -For example, for the default `MyToken.sol` contract, you can use the following file that connects to the contract at its address and retrieves the `unlockTime`, which represents when funds can be withdrawn. The script converts this timestamp into a readable date and logs it. It then checks the contract's balance and displays it. Finally, it attempts to call the withdrawal function on the contract, but it catches and logs the error message if the withdrawal is not yet allowed (e.g., before `unlockTime`). +Create scripts to interact with deployed contracts, read state, execute transactions, and automate maintenance tasks using your generated ABI. -```javascript title="interact.js" -const hre = require('hardhat'); +- See practical tips in [Interact with Smart Contracts](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank}. -async function main() { - // Get the contract factory - const MyToken = await hre.ethers.getContractFactory('MyToken'); - // Replace with your deployed contract address - const contractAddress = 'INSERT_CONTRACT_ADDRESS'; +## Where to Go Next - // Attach to existing contract - const token = await MyToken.attach(contractAddress); +Ready to explore the specifics? Dive into these guides to continue your Hardhat journey: - // Get signers - const [deployer] = await hre.ethers.getSigners(); +
- // Read contract state - const name = await token.name(); - const symbol = await token.symbol(); - const totalSupply = await token.totalSupply(); - const balance = await token.balanceOf(deployer.address); +- Guide __Install and Configure Hardhat__ - console.log(`Token: ${name} (${symbol})`); - console.log( - `Total Supply: ${hre.ethers.formatUnits(totalSupply, 18)} tokens`, - ); - console.log( - `Deployer Balance: ${hre.ethers.formatUnits(balance, 18)} tokens`, - ); -} + --- -main().catch((error) => { - console.error(error); - process.exitCode = 1; -}); + Initialize your workspace and adjust project settings for this toolchain. -``` + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} -Run your interaction script: +- Guide __Compile Smart Contracts__ -```bash -npx hardhat run scripts/interact.js --network polkadotHubTestnet -``` + --- -## Upgrading the Plugin + Configure compiler options and generate deployable artifacts. -If you already have a Hardhat Polkadot project and want to upgrade to a newer version of the plugin, to avoid errors (for example, `Cannot find module 'run-container'`), you can clean your dependencies by running the following commands: + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} -```bash -rm -rf node_modules package-lock.json -``` +- Guide __Test Your Smart Contracts__ -After that, you can upgrade the plugin to the latest version by running the following commands: + --- -```bash -npm install --save-dev @parity/hardhat-polkadot@latest -npm install -``` + Build automated tests and run them against a local node. -Consider using [Node.js](https://nodejs.org/){target=\_blank} 22.18+ and [npm](https://www.npmjs.com/){target=\_blank} version 10.9.0+ to avoid issues with the plugin. + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} -## Where to Go Next +- Guide __Deploy Smart Contracts__ -Hardhat provides a powerful environment for developing, testing, and deploying smart contracts on Polkadot Hub. Its plugin architecture allows seamless integration with PolkaVM through the `hardhat-resolc` and `hardhat-revive-node` plugins. + --- -Explore more about smart contracts through these resources: + Roll out contracts to local, test, or production networks with repeatable scripts. -
+ [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} -- Guide __Get Started with Smart Contracts__ +- Guide __Interact with Smart Contracts__ --- - Learn how to get started with smart contracts + Script on-chain interactions and automate maintenance tasks. - [:octicons-arrow-right-24: Get Started](/smart-contracts/get-started/) + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank} - External __Hardhat Documentation__ --- - Learn more about Hardhat's advanced features and best practices. + Explore Hardhat's official documentation for advanced features and best practices. - [:octicons-arrow-right-24: Get Started](https://hardhat.org/docs){target=\_blank} + [:octicons-arrow-right-24: Learn More](https://hardhat.org/docs){target=\_blank} - External __OpenZeppelin Contracts__ --- - Test your skills by deploying contracts with prebuilt templates. + Use prebuilt, audited contract templates to bootstrap your projects. - [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank} + [:octicons-arrow-right-24: Explore](https://www.openzeppelin.com/solidity-contracts){target=\_blank}
diff --git a/.ai/pages/smart-contracts-for-eth-devs-migration.md b/.ai/pages/smart-contracts-for-eth-devs-migration.md index 1586dde8f..58c91eb15 100644 --- a/.ai/pages/smart-contracts-for-eth-devs-migration.md +++ b/.ai/pages/smart-contracts-for-eth-devs-migration.md @@ -131,8 +131,8 @@ You typically don't need to do anything special, but be aware: Yes. Both backends support: - **Wallets**: [MetaMask](https://metamask.io/){target=\_blank}, [Talisman](https://talisman.xyz/){target=\_blank}, [SubWallet](https://www.subwallet.app/){target=\_blank} -- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} -- **Libraries**: [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank}, [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank}, [viem](/smart-contracts/libraries/viem/){target=\_blank} +- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\_blank}, [Foundry](/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/){target=\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} (just consider that for PVM bytecode, you will use the Polkadot version of the tooling) +- **Libraries**: [ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank}, [web3.js](/smart-contracts/libraries/web3-js/){target=\_blank}, [viem](/smart-contracts/libraries/viem/){target=\_blank} - **Testing tools**: Your existing test suites work Connect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow. diff --git a/.ai/site-index.json b/.ai/site-index.json index 04c1362da..0aac957f9 100644 --- a/.ai/site-index.json +++ b/.ai/site-index.json @@ -671,7 +671,28 @@ ], "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions.md", "html_url": "https://docs.polkadot.com/chain-interactions/", - "preview": "Chain interactions form the foundation of building applications on Polkadot. Whether you're querying on-chain data, executing transactions, enabling cross-chain communication, or managing accounts, understanding how to interact with Polkadot-based chains is essential for application developers.", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-send-messages", + "title": "Send XCM Messages", + "slug": "develop-interoperability-send-messages", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-send-messages.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/send-messages/", + "preview": "One of the core FRAME pallets that enables parachains to engage in cross-chain communication using the Cross-Consensus Message (XCM) format is [`pallet-xcm`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/index.html){target=\\_blank}. It facilitates the sending, execution, and management of XCM messages, thereby allowing parachains to interact with other chains within the ecosystem. Additionally, `pallet-xcm`, also referred to as the XCM pallet, supports essential operations l", "outline": [ { "depth": 2, @@ -695,436 +716,515 @@ }, { "depth": 3, - "title": "Send Cross-Chain Transactions", - "anchor": "send-cross-chain-transactions" - }, - { - "depth": 3, - "title": "Manage Tokens", - "anchor": "manage-tokens" - }, - { - "depth": 3, - "title": "Manage Accounts", - "anchor": "manage-accounts" + "title": "Send", + "anchor": "send" }, { "depth": 2, - "title": "Development Tools and SDKs", - "anchor": "development-tools-and-sdks" - }, - { - "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" + "title": "XCM Router", + "anchor": "xcm-router" } ], "stats": { - "chars": 6632, - "words": 831, - "headings": 9, - "estimated_token_count_total": 1488 + "chars": 7146, + "words": 978, + "headings": 7, + "estimated_token_count_total": 1635 }, - "hash": "sha256:ff1d106bd19f80de0c8108b0a658cfef83d73a4560a012ace9c842acdeefd1a5", + "hash": "sha256:46252e238b0b51105148dc622da6d8809c55ec11da7ec7b2953c35ca52f5f585", "token_estimator": "heuristic-v1" }, { - "id": "get-support-ai-ready-docs", - "title": "AI Ready Docs", - "slug": "get-support-ai-ready-docs", + "id": "develop-interoperability-test-and-debug", + "title": "Testing and Debugging", + "slug": "develop-interoperability-test-and-debug", "categories": [ - "Uncategorized" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-ai-ready-docs.md", - "html_url": "https://docs.polkadot.com/get-support/ai-ready-docs/", - "preview": "Polkadot provides files to make documentation content available in a structure optimized for use with large language models (LLMs) and AI tools. These resources help build AI assistants, power code search, or enable custom tooling trained on Polkadot’s documentation.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-test-and-debug.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/test-and-debug/", + "preview": "Cross-Consensus Messaging (XCM) is a core feature of the Polkadot ecosystem, enabling communication between parachains, relay chains, and system chains. To ensure the reliability of XCM-powered blockchains, thorough testing and debugging are essential before production deployment.", "outline": [ { "depth": 2, - "title": "How to Use These Files", - "anchor": "how-to-use-these-files" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Download LLM Files", - "anchor": "download-llm-files" + "title": "XCM Emulator", + "anchor": "xcm-emulator" + }, + { + "depth": 3, + "title": "Manage Tokens", + "anchor": "manage-tokens" + }, + { + "depth": 3, + "title": "How Does It Work?", + "anchor": "how-does-it-work" } ], "stats": { - "chars": 7998, - "words": 825, - "headings": 2, - "estimated_token_count_total": 2232 + "chars": 7750, + "words": 838, + "headings": 4, + "estimated_token_count_total": 1491 }, - "hash": "sha256:5a8da69a5cea8bd598ee4d102b9abed5d1a29153802a567e22bb4ee720410b32", + "hash": "sha256:db37b2f5888f283b5eb5bd84a5f8c81fc66b2313e3f94f510a73dfeb310ae3f0", "token_estimator": "heuristic-v1" }, { - "id": "get-support-explore-resources", - "title": "Subscribe to Updates", - "slug": "get-support-explore-resources", + "id": "develop-interoperability-versions-v5-asset-claimer", + "title": "Asset claimer", + "slug": "develop-interoperability-versions-v5-asset-claimer", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md", - "html_url": "https://docs.polkadot.com/get-support/explore-resources/", - "preview": "Looking for answers beyond the documentation? These platforms are full of useful content and experienced developers sharing insights.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-asset-claimer.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/asset-claimer/", + "preview": "XCMv5 introduces the [`AssetClaimer`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Hint.html#variant.AssetClaimer){target=\\_blank} execution hint through [`SetHints`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Instruction.html#variant.SetHints){target=\\_blank}, which significantly simplifies the process of recovering trapped assets when XCM execution fails.", "outline": [ { "depth": 2, - "title": "🧠 Stack Exchange", - "anchor": "stack-exchange" + "title": "The problem before v5", + "anchor": "the-problem-before-v5" }, { "depth": 2, - "title": "🧵 Reddit: r/Polkadot", - "anchor": "reddit-rpolkadot" + "title": "The V5 Solution: `AssetClaimer` Hint", + "anchor": "the-v5-solution-assetclaimer-hint" }, { "depth": 2, - "title": "💬 Discord (Community Threads Only)", - "anchor": "discord-community-threads-only" + "title": "How it Improves the Situation", + "anchor": "how-it-improves-the-situation" }, { "depth": 2, - "title": "🎥 YouTube: @PolkadotNetwork", - "anchor": "youtube-polkadotnetwork" + "title": "Key Improvements", + "anchor": "key-improvements" }, { "depth": 2, - "title": "Community-Led Platforms and Ecosystem Updates", - "anchor": "community-led-platforms-and-ecosystem-updates" - }, - { - "depth": 3, - "title": "🔷 X (Twitter): Official Accounts", - "anchor": "x-twitter-official-accounts" + "title": "Best Practices", + "anchor": "best-practices" }, { "depth": 3, - "title": "🔁 X (Twitter): Community Accounts", - "anchor": "x-twitter-community-accounts" + "title": "Set Hint Early", + "anchor": "set-hint-early" }, { "depth": 3, - "title": "🗣️ Polkadot Forum", - "anchor": "polkadot-forum" + "title": "Use for Cross-Chain Transfers", + "anchor": "use-for-cross-chain-transfers" }, { "depth": 3, - "title": "🧑‍⚖️ Polkassembly: OpenGov", - "anchor": "polkassembly-opengov" + "title": "Consider Origin Preservation", + "anchor": "consider-origin-preservation" }, { - "depth": 3, - "title": "📸 Instagram", - "anchor": "instagram" + "depth": 2, + "title": "Migration Impact", + "anchor": "migration-impact" } ], "stats": { - "chars": 2426, - "words": 295, - "headings": 10, - "estimated_token_count_total": 579 + "chars": 5080, + "words": 582, + "headings": 9, + "estimated_token_count_total": 955 }, - "hash": "sha256:670221ac20ab1f1b550ba2a1db06cd924c24bd3afc4d8a768b617d8a409243cb", + "hash": "sha256:72ee7394fd1308c111a8d548cb4dc63c6b9bc5b6e2bb556dd1baacbaedb92286", "token_estimator": "heuristic-v1" }, { - "id": "get-support-get-in-touch", - "title": "Get in Touch", - "slug": "get-support-get-in-touch", + "id": "develop-interoperability-versions-v5-fees", + "title": "Fees", + "slug": "develop-interoperability-versions-v5-fees", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-get-in-touch.md", - "html_url": "https://docs.polkadot.com/get-support/get-in-touch/", - "preview": "Use one of the channels below to get live technical support or ask questions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-fees.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/fees/", + "preview": "XCM V5 introduces a new fee payment mechanism that simplifies and unifies the handling of fees across various XCM operations.", "outline": [ { "depth": 2, - "title": "Need Help Fast?", - "anchor": "need-help-fast" + "title": "Key Changes from V4", + "anchor": "key-changes-from-v4" + }, + { + "depth": 3, + "title": "BuyExecution vs. PayFees", + "anchor": "buyexecution-vs-payfees" + }, + { + "depth": 3, + "title": "PayFees Instruction", + "anchor": "payfees-instruction" }, { "depth": 2, - "title": "📱 Telegram: Polkadot Developer Support", - "anchor": "telegram-polkadot-developer-support" + "title": "Backward Compatibility", + "anchor": "backward-compatibility" }, { "depth": 2, - "title": "🔌 Discord: Polkadot Official Server", - "anchor": "discord-polkadot-official-server" + "title": "Migration Considerations", + "anchor": "migration-considerations" }, { "depth": 2, - "title": "🧬 Matrix: Polkadot Developer Support", - "anchor": "matrix-polkadot-developer-support" + "title": "`RefundSurplus` Instruction", + "anchor": "refundsurplus-instruction" } ], "stats": { - "chars": 1949, - "words": 258, - "headings": 4, - "estimated_token_count_total": 557 + "chars": 4145, + "words": 531, + "headings": 6, + "estimated_token_count_total": 876 }, - "hash": "sha256:993e93b05c8fbdfc2f7510c61ac86bc4c2ff0f03e573695b2f260933c8b62f78", + "hash": "sha256:d6cb22337280a19bdf24981dcba98f337d48ee4f79ce7ac040466ef1cb4b330b", "token_estimator": "heuristic-v1" }, { - "id": "get-support", - "title": "Support", - "slug": "get-support", + "id": "develop-interoperability-versions-v5-migration-guide", + "title": "Migration Guide (XCM V4 → XCM V5)", + "slug": "develop-interoperability-versions-v5-migration-guide", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support.md", - "html_url": "https://docs.polkadot.com/get-support/", - "preview": "Use one of the channels below to get live technical support or ask questions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-migration-guide.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/migration-guide/", + "preview": "This guide helps migrate existing code that uses XCM from XCM V4 to XCM V5. Most XCM V4 code continues to work, but XCM V5 introduces powerful new patterns that improve flexibility and developer experience.", "outline": [ { "depth": 2, - "title": "Need More than Just Documentation?", - "anchor": "need-more-than-just-documentation" + "title": "When to migrate", + "anchor": "when-to-migrate" }, { "depth": 2, - "title": "What You Can Do Here", - "anchor": "what-you-can-do-here" + "title": "Key Changes", + "anchor": "key-changes" + }, + { + "depth": 3, + "title": "From Dedicated Extrinsics to Raw XCMs", + "anchor": "from-dedicated-extrinsics-to-raw-xcms" + }, + { + "depth": 3, + "title": "Unified Transfer Instructions", + "anchor": "unified-transfer-instructions" + }, + { + "depth": 3, + "title": "Predictable fee payment", + "anchor": "predictable-fee-payment" }, { "depth": 2, - "title": "Help Us Improve", - "anchor": "help-us-improve" + "title": "Migration Examples", + "anchor": "migration-examples" + }, + { + "depth": 3, + "title": "Simple Teleport", + "anchor": "simple-teleport" + }, + { + "depth": 3, + "title": "Example 2: Multi-Asset Transfer and a Transact", + "anchor": "example-2-multi-asset-transfer-and-a-transact" + }, + { + "depth": 2, + "title": "Breaking Changes to Watch Out For", + "anchor": "breaking-changes-to-watch-out-for" + }, + { + "depth": 3, + "title": "`fallback_max_weight` in `Transact`", + "anchor": "fallback_max_weight-in-transact" + }, + { + "depth": 3, + "title": "Network IDs Cleanup", + "anchor": "network-ids-cleanup" + }, + { + "depth": 2, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 1658, - "words": 244, - "headings": 3, - "estimated_token_count_total": 280 + "chars": 13459, + "words": 1562, + "headings": 12, + "estimated_token_count_total": 2744 }, - "hash": "sha256:5bdc575ac798a971867a15651c2b4d5139bf0b1fe6854d1865deff280ae6d7f6", + "hash": "sha256:1a2d34ccab19bd71263763bbc294977acf34f5800398f51398753594cfc7d7a6", "token_estimator": "heuristic-v1" }, { - "id": "index", - "title": "Polkadot Developer Docs", - "slug": "index", + "id": "develop-interoperability-versions-v5-transact", + "title": "Transact", + "slug": "develop-interoperability-versions-v5-transact", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/index.md", - "html_url": "https://docs.polkadot.com/index/", - "preview": "Explore everything you need to start building on top of Polkadot, a protocol that provides parachains with shared security and interoperability using XCM.", - "outline": [], - "stats": { - "chars": 0, - "words": 0, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-node-bootnode", - "title": "Set Up a Bootnode", - "slug": "nodes-and-validators-run-a-node-bootnode", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-bootnode.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/bootnode/", - "preview": "Bootnodes are essential for helping blockchain nodes discover peers and join the network. When a node starts, it needs to find other nodes, and bootnodes provide an initial point of contact. Once connected, a node can expand its peer connections and play its role in the network, like participating as a validator.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-transact.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/transact/", + "preview": "XCM V5 improves the [`Transact`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Instruction.html#variant.Transact){target=\\_blank} instruction by introducing optional weight specification through the `fallback_max_weight` parameter, making cross-chain calls more flexible and reliable.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Changes from V4", + "anchor": "changes-from-v4" }, { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "depth": 3, + "title": "Weight Parameter Evolution", + "anchor": "weight-parameter-evolution" }, { "depth": 2, - "title": "Accessing the Bootnode", - "anchor": "accessing-the-bootnode" + "title": "The `fallback_max_weight` Parameter", + "anchor": "the-fallback_max_weight-parameter" }, { - "depth": 2, - "title": "Node Key", - "anchor": "node-key" + "depth": 3, + "title": "When to Use `undefined`", + "anchor": "when-to-use-undefined" }, { - "depth": 2, - "title": "Running the Bootnode", - "anchor": "running-the-bootnode" + "depth": 3, + "title": "When to Specify Weight", + "anchor": "when-to-specify-weight" }, { "depth": 2, - "title": "Testing Bootnode Connection", - "anchor": "testing-bootnode-connection" + "title": "Benefits of the New Approach", + "anchor": "benefits-of-the-new-approach" }, { "depth": 3, - "title": "P2P", - "anchor": "p2p" + "title": "Problems Solved", + "anchor": "problems-solved" }, { "depth": 3, - "title": "P2P/WS", - "anchor": "p2pws" + "title": "XCM V5 Improvements", + "anchor": "xcm-v5-improvements" }, { - "depth": 3, - "title": "P2P/WSS", - "anchor": "p2pwss" + "depth": 2, + "title": "Migration Strategy", + "anchor": "migration-strategy" + }, + { + "depth": 2, + "title": "Fee Implications", + "anchor": "fee-implications" } ], "stats": { - "chars": 4538, - "words": 647, - "headings": 9, - "estimated_token_count_total": 1044 + "chars": 3637, + "words": 370, + "headings": 10, + "estimated_token_count_total": 608 }, - "hash": "sha256:d84a5af1a0237a911d25a68c077f508ebbce608f673ef4f9055e8e434daa96b9", + "hash": "sha256:7bba6105d99721373aa6f494627d20af97b1851c19703f26be26c32f0c83524b", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-node-full-node", - "title": "Set Up a Node", - "slug": "nodes-and-validators-run-a-node-full-node", + "id": "develop-interoperability-versions-v5-transfers", + "title": "Transfers", + "slug": "develop-interoperability-versions-v5-transfers", "categories": [ - "Infrastructure" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-full-node.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/full-node/", - "preview": "Running a node on Polkadot provides direct interaction with the network, enhanced privacy, and full control over RPC requests, transactions, and data queries. As the backbone of the network, nodes ensure decentralized data propagation, transaction validation, and seamless communication across the ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-transfers.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/transfers/", + "preview": "XCM V5 introduces the unified [`InitiateTransfer`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Instruction.html#variant.InitiateTransfer){target=\\_blank} instruction that consolidates and enhances cross-chain transfer capabilities.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Changes from v4", + "anchor": "changes-from-v4" }, { - "depth": 2, - "title": "Set Up a Node", - "anchor": "set-up-a-node" + "depth": 3, + "title": "Instruction Consolidation", + "anchor": "instruction-consolidation" }, { "depth": 3, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Enhanced Transfer Specification", + "anchor": "enhanced-transfer-specification" }, { - "depth": 3, - "title": "Install and Build the Polkadot Binary", - "anchor": "install-and-build-the-polkadot-binary" + "depth": 2, + "title": "Key Enhancements", + "anchor": "key-enhancements" }, { "depth": 3, - "title": "Use Docker", - "anchor": "use-docker" + "title": "Mixed Transfer Types", + "anchor": "mixed-transfer-types" }, { - "depth": 2, - "title": "Configure and Run Your Node", - "anchor": "configure-and-run-your-node" + "depth": 3, + "title": "Origin Preservation", + "anchor": "origin-preservation" }, { "depth": 3, - "title": "RPC Configurations", - "anchor": "rpc-configurations" + "title": "Integrated Fee Handling", + "anchor": "integrated-fee-handling" }, { "depth": 2, - "title": "Sync Your Node", - "anchor": "sync-your-node" + "title": "Backward Compatibility", + "anchor": "backward-compatibility" }, { - "depth": 3, - "title": "Connect to Your Node", - "anchor": "connect-to-your-node" + "depth": 2, + "title": "Migration Benefits", + "anchor": "migration-benefits" } ], "stats": { - "chars": 15944, - "words": 2481, + "chars": 3243, + "words": 336, "headings": 9, - "estimated_token_count_total": 4196 + "estimated_token_count_total": 1488 }, - "hash": "sha256:924fab837818610c825be5cefde0a7bacd46985b4fa05cfa0376a941105b9869", + "hash": "sha256:b79fe56c9604712825bdf30d17667fd8f237fce9691be0d8d042d38691dbba7a", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-node-secure-wss", - "title": "Set Up Secure WebSocket", - "slug": "nodes-and-validators-run-a-node-secure-wss", + "id": "develop-interoperability-versions-v5-writing-xcm-programs", + "title": "Writing XCM Programs", + "slug": "develop-interoperability-versions-v5-writing-xcm-programs", "categories": [ - "Infrastructure" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-secure-wss.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/secure-wss/", - "preview": "Ensuring secure WebSocket communication is crucial for maintaining the integrity and security of a Polkadot or Kusama node when interacting with remote clients. This guide walks you through setting up a secure WebSocket (WSS) connection for your node by leveraging SSL encryption with popular web server proxies like nginx or Apache.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-writing-xcm-programs.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/writing-xcm-programs/", + "preview": "XCM V5 shifts the recommended approach from using dedicated extrinsics to executing raw XCM programs directly.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "The Paradigm Shift", + "anchor": "the-paradigm-shift" }, { - "depth": 2, - "title": "Secure a WebSocket Port", - "anchor": "secure-a-websocket-port" + "depth": 3, + "title": "Previous Approach", + "anchor": "previous-approach" }, { "depth": 3, - "title": "Obtain an SSL Certificate", - "anchor": "obtain-an-ssl-certificate" + "title": "XCM V5 Recommendation", + "anchor": "xcm-v5-recommendation" }, { "depth": 2, - "title": "Install a Proxy Server", - "anchor": "install-a-proxy-server" + "title": "Execution Approach", + "anchor": "execution-approach" }, { - "depth": 3, - "title": "Use nginx", - "anchor": "use-nginx" + "depth": 2, + "title": "Benefits of Direct Execution", + "anchor": "benefits-of-direct-execution" }, { - "depth": 3, - "title": "Use Apache2", - "anchor": "use-apache2" - }, + "depth": 2, + "title": "Migration Considerations", + "anchor": "migration-considerations" + } + ], + "stats": { + "chars": 1830, + "words": 215, + "headings": 6, + "estimated_token_count_total": 348 + }, + "hash": "sha256:11cd8d428fa9c3e70490da5c63ce4597cd89ec46306d2bb49b016ced6aa68c3d", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-versions-v5", + "title": "XCMv5", + "slug": "develop-interoperability-versions-v5", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/", + "preview": "The latest iteration of XCM is version 5. The main RFCs defining the changes in version 5 are the following:", + "outline": [ { "depth": 2, - "title": "Connect to the Node", - "anchor": "connect-to-the-node" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 5568, - "words": 774, - "headings": 7, - "estimated_token_count_total": 1280 + "chars": 2970, + "words": 438, + "headings": 1, + "estimated_token_count_total": 12 }, - "hash": "sha256:992082e4ad87348b283f6c37ea886ae0e7bf016852b6470000876f3d169c65a4", + "hash": "sha256:3821c2ef97699091b76e1de58e6d95e866df69d39fca16f2a15c156b71da5b22", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", - "title": "Validator Key Management", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", + "id": "develop-interoperability-versions", + "title": "XCM Versions", + "slug": "develop-interoperability-versions", "categories": [ - "Infrastructure" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/", - "preview": "After setting up your node environment as shown in the [Setup](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/){target=\\_blank} section, you'll need to configure multiple keys for your validator to operate properly. This includes setting up session keys, which are essential for participating in the consensus process, and configuring a node key that maintains a stable network identity. This guide walks you through the key management process, showing you how to g", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/versions/", + "preview": "XCM is a versioned language that evolves to meet the growing needs of cross-chain communication in the Polkadot ecosystem. Understanding XCM versioning is essential for developers building interoperable applications to keep up with the latest improvements.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 835, + "words": 114, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:634e299f347beb8ad690697943bb7f99915d62d40cda4227179619ed18abe2ff", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-xcm-channels", + "title": "XCM Channels", + "slug": "develop-interoperability-xcm-channels", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-channels.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-channels/", + "preview": "Polkadot is designed to enable interoperability between its connected parachains. At the core of this interoperability is the [Cross-Consensus Message Format (XCM)](/parachains/interoperability/get-started/){target=\\_blank}, a standard language that allows parachains to communicate and interact with each other.", "outline": [ { "depth": 2, @@ -1133,59 +1233,45 @@ }, { "depth": 2, - "title": "Set Session Keys", - "anchor": "set-session-keys" - }, - { - "depth": 3, - "title": "Generate Session Keys", - "anchor": "generate-session-keys" + "title": "Establishing HRMP Channels", + "anchor": "establishing-hrmp-channels" }, { "depth": 3, - "title": "Submit Transaction to Set Keys", - "anchor": "submit-transaction-to-set-keys" + "title": "Relay Chain Parameters", + "anchor": "relay-chain-parameters" }, { "depth": 3, - "title": "Verify Session Key Setup", - "anchor": "verify-session-key-setup" + "title": "Dispatching Extrinsics", + "anchor": "dispatching-extrinsics" }, { "depth": 2, - "title": "Set the Node Key", - "anchor": "set-the-node-key" - }, - { - "depth": 3, - "title": "Generate the Node Key", - "anchor": "generate-the-node-key" - }, - { - "depth": 3, - "title": "Set Node Key", - "anchor": "set-node-key" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 8227, - "words": 1183, - "headings": 8, - "estimated_token_count_total": 1840 + "chars": 6422, + "words": 870, + "headings": 5, + "estimated_token_count_total": 1365 }, - "hash": "sha256:0fb5a83835aab263c0b9aa886028c8aa8a2d6d0897d7b9fff4b5258835d30dfe", + "hash": "sha256:5f8fa89fc725c5c559975012fe2f9ae92c3b62f10024b5688dcd118331118f1a", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", - "title": "Set Up a Validator", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", + "id": "develop-interoperability-xcm-config", + "title": "XCM Config", + "slug": "develop-interoperability-xcm-config", "categories": [ - "Infrastructure" + "Reference", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/", - "preview": "Setting up a Polkadot validator node is essential for securing the network and earning staking rewards. This guide walks you through the technical steps to set up a validator, from installing the necessary software to managing keys and synchronizing your node with the chain.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-config.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-config/", + "preview": "The [XCM executor](https://paritytech.github.io/polkadot-sdk/master/staging_xcm_executor/index.html){target=\\_blank} is a crucial component responsible for interpreting and executing XCM messages (XCMs) with Polkadot SDK-based chains. It processes and manages XCM instructions, ensuring they are executed correctly and in sequentially. Adhering to the [Cross-Consensus Virtual Machine (XCVM) specification](https://paritytech.github.io/xcm-docs/overview/xcvm.html#the-xcvm){target=\\_blank}, the XCM e", "outline": [ { "depth": 2, @@ -1194,79 +1280,49 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Initial Setup", - "anchor": "initial-setup" - }, - { - "depth": 3, - "title": "Install Network Time Protocol Client", - "anchor": "install-network-time-protocol-client" - }, - { - "depth": 3, - "title": "Verify Landlock is Activated", - "anchor": "verify-landlock-is-activated" + "title": "XCM Executor Configuration", + "anchor": "xcm-executor-configuration" }, { "depth": 2, - "title": "Install the Polkadot Binaries", - "anchor": "install-the-polkadot-binaries" - }, - { - "depth": 3, - "title": "Install from Official Releases", - "anchor": "install-from-official-releases" - }, - { - "depth": 3, - "title": "Install with Package Managers", - "anchor": "install-with-package-managers" - }, - { - "depth": 3, - "title": "Install with Ansible", - "anchor": "install-with-ansible" + "title": "Config Items", + "anchor": "config-items" }, { "depth": 3, - "title": "Install with Docker", - "anchor": "install-with-docker" + "title": "Inner Config", + "anchor": "inner-config" }, { "depth": 3, - "title": "Build from Sources", - "anchor": "build-from-sources" + "title": "Outer Config", + "anchor": "outer-config" }, { "depth": 2, - "title": "Verify Installation", - "anchor": "verify-installation" + "title": "Multiple Implementations", + "anchor": "multiple-implementations" } ], "stats": { - "chars": 11921, - "words": 1678, - "headings": 12, - "estimated_token_count_total": 2592 + "chars": 21710, + "words": 2458, + "headings": 6, + "estimated_token_count_total": 4979 }, - "hash": "sha256:d2c1c91734bc8185057d8eeec6829ea91e0316f7ba884c5dc3922a5e5778815e", + "hash": "sha256:ed3b7c8101b69f9c907cca7c5edfef67fdb5e7bc3c8df8d9fbad297f9dd3c80a", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", - "title": "Start Validating", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", + "id": "develop-interoperability-xcm-guides-from-apps-claiming-trapped-assets", + "title": "Claiming Trapped Assets", + "slug": "develop-interoperability-xcm-guides-from-apps-claiming-trapped-assets", "categories": [ - "Infrastructure" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/start-validating/", - "preview": "After configuring your node keys as shown in the [Key Management](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/){target=\\_blank} section and ensuring your system is set up, you're ready to begin the validator setup process. This guide will walk you through choosing a network, synchronizing your node with the blockchain, bonding your DOT tokens, and starting your validator.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps-claiming-trapped-assets.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/claiming-trapped-assets/", + "preview": "When XCM execution fails or succeeds, leftover assets can become \"trapped\" on the destination chain. These assets are held by the system but are not accessible through normal means. XCM provides mechanisms to claim these trapped assets and recover them. This guide details the process and required steps to claim trapped assets.", "outline": [ { "depth": 2, @@ -1275,84 +1331,54 @@ }, { "depth": 2, - "title": "Choose a Network", - "anchor": "choose-a-network" + "title": "Trapped Assets Causes", + "anchor": "trapped-assets-causes" }, { "depth": 2, - "title": "Synchronize Chain Data", - "anchor": "synchronize-chain-data" + "title": "The `ClaimAsset` Instruction", + "anchor": "the-claimasset-instruction" }, { "depth": 3, - "title": "Database Snapshot Services", - "anchor": "database-snapshot-services" - }, - { - "depth": 2, - "title": "Bond DOT", - "anchor": "bond-dot" + "title": "Parameters", + "anchor": "parameters" }, { "depth": 3, - "title": "Bonding DOT on Polkadot.js Apps", - "anchor": "bonding-dot-on-polkadotjs-apps" + "title": "Basic Claiming Process", + "anchor": "basic-claiming-process" }, { "depth": 2, - "title": "Validate", - "anchor": "validate" - }, - { - "depth": 3, - "title": "Verify Sync via Telemetry", - "anchor": "verify-sync-via-telemetry" - }, - { - "depth": 3, - "title": "Activate using Polkadot.js Apps", - "anchor": "activate-using-polkadotjs-apps" - }, - { - "depth": 3, - "title": "Monitor Validation Status and Slots", - "anchor": "monitor-validation-status-and-slots" + "title": "The `AssetClaimer` Hint", + "anchor": "the-assetclaimer-hint" }, { "depth": 2, - "title": "Run a Validator Using Systemd", - "anchor": "run-a-validator-using-systemd" - }, - { - "depth": 3, - "title": "Create the Systemd Service File", - "anchor": "create-the-systemd-service-file" - }, - { - "depth": 3, - "title": "Run the Service", - "anchor": "run-the-service" + "title": "Best practices", + "anchor": "best-practices" } ], "stats": { - "chars": 15820, - "words": 2446, - "headings": 13, - "estimated_token_count_total": 3861 + "chars": 8821, + "words": 958, + "headings": 7, + "estimated_token_count_total": 1781 }, - "hash": "sha256:67a43e787805244196e1e9cb962069292c69ed5fdb1110df57c942019892b953", + "hash": "sha256:35c71a215558cd0642d363e4515ad240093995d42720e6495cd2994c859243e4", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", - "title": "Stop Validating", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", + "id": "develop-interoperability-xcm-guides-from-apps-fees", + "title": "Fees", + "slug": "develop-interoperability-xcm-guides-from-apps-fees", "categories": [ - "Infrastructure" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/", - "preview": "If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps-fees.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/fees/", + "preview": "In blockchain systems, fees are crucial. They prevent malicious actors from exhausting the results of the network, making such attacks expensive. The XCM subsystem has its own way of dealing with fees, flexible enough to allow feeless execution in situations that warrant it.", "outline": [ { "depth": 2, @@ -1361,44 +1387,44 @@ }, { "depth": 2, - "title": "Pause Versus Stop", - "anchor": "pause-versus-stop" + "title": "Execution", + "anchor": "execution" }, { "depth": 2, - "title": "Chill Validator", - "anchor": "chill-validator" + "title": "Delivery", + "anchor": "delivery" }, { "depth": 2, - "title": "Purge Validator Session Keys", - "anchor": "purge-validator-session-keys" + "title": "PayFees", + "anchor": "payfees" }, { "depth": 2, - "title": "Unbond Your Tokens", - "anchor": "unbond-your-tokens" + "title": "Estimations", + "anchor": "estimations" } ], "stats": { - "chars": 3230, - "words": 500, + "chars": 6291, + "words": 925, "headings": 5, - "estimated_token_count_total": 629 + "estimated_token_count_total": 1447 }, - "hash": "sha256:0d6db361bfa7a3022849bbe39989bfdac0429537498d7f534adadec131afca98", + "hash": "sha256:0e39aee80fbcf3dfaa19133f31d664914ed45b42a1a929270f05d8ae876b89e2", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-operational-tasks-general-management", - "title": "General Management", - "slug": "nodes-and-validators-run-a-validator-operational-tasks-general-management", + "id": "develop-interoperability-xcm-guides-from-apps-transact", + "title": "Transact", + "slug": "develop-interoperability-xcm-guides-from-apps-transact", "categories": [ - "Infrastructure" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-general-management.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/general-management/", - "preview": "Validator performance is pivotal in maintaining the security and stability of the Polkadot network. As a validator, optimizing your setup ensures efficient transaction processing, minimizes latency, and maintains system reliability during high-demand periods. Proper configuration and proactive monitoring also help mitigate risks like slashing and service interruptions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps-transact.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/transact/", + "preview": "The [`Transact`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/opaque/type.Instruction.html#variant.Transact){target=\\_blank} instruction enables arbitrary cross-chain execution of pallet calls or smart contract functions. It's one of the most powerful XCM instructions because it allows you to perform any operation that would normally be done locally on a remote chain. However, it requires knowing the implementation details of the destination chain.", "outline": [ { "depth": 2, @@ -1407,83 +1433,214 @@ }, { "depth": 2, - "title": "Configuration Optimization", - "anchor": "configuration-optimization" + "title": "Chain-Specific Knowledge Required", + "anchor": "chain-specific-knowledge-required" }, { "depth": 3, - "title": "Deactivate Simultaneous Multithreading", - "anchor": "deactivate-simultaneous-multithreading" + "title": "Required Knowledge", + "anchor": "required-knowledge" }, { "depth": 3, - "title": "Deactivate Automatic NUMA Balancing", - "anchor": "deactivate-automatic-numa-balancing" + "title": "Examples of Chain-Specific Requirements", + "anchor": "examples-of-chain-specific-requirements" }, { - "depth": 3, - "title": "Spectre and Meltdown Mitigations", - "anchor": "spectre-and-meltdown-mitigations" + "depth": 2, + "title": "Origin Considerations", + "anchor": "origin-considerations" + } + ], + "stats": { + "chars": 4444, + "words": 562, + "headings": 5, + "estimated_token_count_total": 1082 + }, + "hash": "sha256:ec82957c768c2c07a272e7a28659c812b223df836e21372b1642f0bb249d7b39", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-xcm-guides-from-apps-transfers", + "title": "Transfers", + "slug": "develop-interoperability-xcm-guides-from-apps-transfers", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps-transfers.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/transfers/", + "preview": "The [`InitiateTransfer`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Instruction.html#variant.InitiateTransfer){target=\\_blank} instruction is the primary mechanism for cross-chain transfers in XCM. It provides a unified interface for different types of transfers and brings additional functionalities not possible with previous instruction versions.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Monitor Your Node", - "anchor": "monitor-your-node" + "title": "Transfer Types", + "anchor": "transfer-types" }, { - "depth": 3, - "title": "Environment Setup", - "anchor": "environment-setup" + "depth": 2, + "title": "Remote Fees", + "anchor": "remote-fees" }, { - "depth": 3, - "title": "Install and Configure Prometheus", - "anchor": "install-and-configure-prometheus" + "depth": 2, + "title": "Origin Preservation", + "anchor": "origin-preservation" + } + ], + "stats": { + "chars": 20264, + "words": 2291, + "headings": 4, + "estimated_token_count_total": 4178 + }, + "hash": "sha256:d480791a76082937b47c77f7cf3794e701f193452ed347fcb1c04c3c67577bf5", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-xcm-guides-from-apps", + "title": "From Apps", + "slug": "develop-interoperability-xcm-guides-from-apps", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/", + "preview": "This section shows how to interact with XCM from applications, providing practical guidance for implementing cross-chain functionality in your dApps and services.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 511, + "words": 70, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:63584f5b1dab7b67b18b35b47dfc19d00ad5c013804772f0d653a11ac3fca38d", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-xcm-guides", + "title": "XCM Guides", + "slug": "develop-interoperability-xcm-guides", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/", + "preview": "This section provides comprehensive guides for implementing XCM functionality, including application development patterns, fee management, asset transfers, and cross-chain transaction handling.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" }, { - "depth": 3, - "title": "Start Prometheus", - "anchor": "start-prometheus" + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1663, + "words": 215, + "headings": 2, + "estimated_token_count_total": 340 + }, + "hash": "sha256:d4c2d7fd46ddf60f638f948c88ba3940de6d69f140923ba8df52ed787b0afede", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability-xcm-runtime-apis", + "title": "XCM Runtime APIs", + "slug": "develop-interoperability-xcm-runtime-apis", + "categories": [ + "Reference", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-runtime-apis.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-runtime-apis/", + "preview": "Runtime APIs allow node-side code to extract information from the runtime state. While simple storage access retrieves stored values directly, runtime APIs enable arbitrary computation, making them a powerful tool for interacting with the chain's state.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Dry Run API", + "anchor": "dry-run-api" }, { "depth": 3, - "title": "Install and Configure Grafana", - "anchor": "install-and-configure-grafana" + "title": "Dry Run Call", + "anchor": "dry-run-call" }, { "depth": 3, - "title": "Install and Configure Alertmanager", - "anchor": "install-and-configure-alertmanager" + "title": "Dry Run XCM", + "anchor": "dry-run-xcm" }, { "depth": 2, - "title": "Secure Your Validator", - "anchor": "secure-your-validator" + "title": "XCM Payment API", + "anchor": "xcm-payment-api" }, { "depth": 3, - "title": "Key Management", - "anchor": "key-management" + "title": "Query Acceptable Payment Assets", + "anchor": "query-acceptable-payment-assets" }, { "depth": 3, - "title": "Signing Outside the Client", - "anchor": "signing-outside-the-client" + "title": "Query XCM Weight", + "anchor": "query-xcm-weight" }, { "depth": 3, - "title": "Secure-Validator Mode", - "anchor": "secure-validator-mode" + "title": "Query Weight to Asset Fee", + "anchor": "query-weight-to-asset-fee" }, { "depth": 3, - "title": "Linux Best Practices", - "anchor": "linux-best-practices" - }, + "title": "Query Delivery Fees", + "anchor": "query-delivery-fees" + } + ], + "stats": { + "chars": 33176, + "words": 3163, + "headings": 9, + "estimated_token_count_total": 6510 + }, + "hash": "sha256:353ad782303ef79bce1262bfa945e6f11b3c3c9ca1edf5705b778c46bada6200", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-interoperability", + "title": "Interoperability", + "slug": "develop-interoperability", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability.md", + "html_url": "https://docs.polkadot.com/develop/interoperability/", + "preview": "This section covers everything you need to know about building and implementing [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\\_blank} solutions in the Polkadot ecosystem. Whether you're working on establishing cross-chain channels, sending and receiving XCM messages, or testing and debugging your cross-chain configurations, you'll find the essential resources and tools here to support your interoperability needs, regardless of your development focus.", + "outline": [ { - "depth": 3, - "title": "Validator Best Practices", - "anchor": "validator-best-practices" + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, @@ -1492,24 +1649,25 @@ } ], "stats": { - "chars": 26673, - "words": 3357, - "headings": 18, - "estimated_token_count_total": 5866 + "chars": 2363, + "words": 323, + "headings": 2, + "estimated_token_count_total": 402 }, - "hash": "sha256:81eb0fe77f05155f1ec0511cd066120fc9994961e9d91e21b6666377e65b4586", + "hash": "sha256:5da6bdeec1deee5ef3d7ab1a43f546067bcef91acdc67df4ce114ee8f8669e82", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", - "title": "Pause Validating", - "slug": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", + "id": "develop-networks", + "title": "Networks", + "slug": "develop-networks", "categories": [ - "Infrastructure" + "Basics", + "Networks" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-pause-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/", - "preview": "If you need to temporarily stop participating in Polkadot staking activities without fully unbonding your funds, chilling your account allows you to do so efficiently. Chilling removes your node from active validation or nomination in the next era while keeping your funds bonded, making it ideal for planned downtimes or temporary pauses.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-networks.md", + "html_url": "https://docs.polkadot.com/develop/networks/", + "preview": "The Polkadot ecosystem consists of multiple networks designed to support different stages of blockchain development, from main networks to test networks. Each network serves a unique purpose, providing developers with flexible environments for building, testing, and deploying blockchain applications.", "outline": [ { "depth": 2, @@ -1518,49 +1676,60 @@ }, { "depth": 2, - "title": "Chilling Your Node", - "anchor": "chilling-your-node" + "title": "Production Networks", + "anchor": "production-networks" }, { - "depth": 2, - "title": "Staking Election Timing Considerations", - "anchor": "staking-election-timing-considerations" + "depth": 3, + "title": "Polkadot", + "anchor": "polkadot" }, { - "depth": 2, - "title": "Chilling as a Nominator", - "anchor": "chilling-as-a-nominator" + "depth": 3, + "title": "Kusama", + "anchor": "kusama" }, { "depth": 2, - "title": "Chilling as a Validator", - "anchor": "chilling-as-a-validator" + "title": "Test Networks", + "anchor": "test-networks" + }, + { + "depth": 3, + "title": "Westend", + "anchor": "westend" + }, + { + "depth": 3, + "title": "Paseo", + "anchor": "paseo" }, { "depth": 2, - "title": "Chill Other", - "anchor": "chill-other" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 4439, - "words": 679, - "headings": 6, - "estimated_token_count_total": 861 + "chars": 6097, + "words": 664, + "headings": 8, + "estimated_token_count_total": 1520 }, - "hash": "sha256:1af153570ce57bd5b52d08493a300996765686f2a6d04519a2e0aa91191612c1", + "hash": "sha256:ed09ef7a6abe21204006186fd5791ada7597688fad67e30244dc449c51330309", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", - "title": "Upgrade a Validator Node", - "slug": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", + "id": "develop-parachains-customize-parachain-overview", + "title": "Overview of FRAME", + "slug": "develop-parachains-customize-parachain-overview", "categories": [ - "Infrastructure" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/upgrade-your-node/", - "preview": "Upgrading a Polkadot validator node is essential for staying current with network updates and maintaining optimal performance. This guide covers routine and extended maintenance scenarios, including software upgrades and major server changes. Following these steps, you can manage session keys and transition smoothly between servers without risking downtime, slashing, or network disruptions. The process requires strategic planning, especially if you need to perform long-lead maintenance, ensuring", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain-overview.md", + "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/overview/", + "preview": "The runtime is the heart of any Polkadot SDK-based blockchain, handling the essential logic that governs state changes and transaction processing. With Polkadot SDK’s [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_bank}, developers gain access to a powerful suite of tools for building custom blockchain runtimes. FRAME offers a modular architecture, featuring reusable pallets and su", "outline": [ { "depth": 2, @@ -1569,54 +1738,95 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "FRAME Runtime Architecture", + "anchor": "frame-runtime-architecture" }, { - "depth": 2, - "title": "Session Keys", - "anchor": "session-keys" + "depth": 3, + "title": "Pallets", + "anchor": "pallets" + }, + { + "depth": 3, + "title": "Support Libraries", + "anchor": "support-libraries" }, { "depth": 2, - "title": "Keystore", - "anchor": "keystore" + "title": "Compose a Runtime with Pallets", + "anchor": "compose-a-runtime-with-pallets" }, { "depth": 2, - "title": "Upgrade Using Backup Validator", - "anchor": "upgrade-using-backup-validator" + "title": "Starting from Templates", + "anchor": "starting-from-templates" }, { "depth": 3, - "title": "Session `N`", - "anchor": "session-n" + "title": "Solochain Templates", + "anchor": "solochain-templates" }, { "depth": 3, - "title": "Session `N+3`", - "anchor": "session-n3" + "title": "Parachain Templates", + "anchor": "parachain-templates" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 5650, - "words": 851, - "headings": 7, - "estimated_token_count_total": 1185 + "chars": 9427, + "words": 1267, + "headings": 9, + "estimated_token_count_total": 2019 }, - "hash": "sha256:888230b128d8c648c4f06a18d3b1d1b06dd1bf22a0de4add1f28210ffccb2549", + "hash": "sha256:d03ea172f2af9f4648e730d60033a80c2c1e64efa9241fed0c1ba40a5f846ae5", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-requirements", - "title": "Validator Requirements", - "slug": "nodes-and-validators-run-a-validator-requirements", + "id": "develop-parachains-customize-parachain", + "title": "Customize Your Parachain", + "slug": "develop-parachains-customize-parachain", "categories": [ - "Infrastructure" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-requirements.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/requirements/", - "preview": "Running a validator in the Polkadot ecosystem is essential for maintaining network security and decentralization. Validators are responsible for validating transactions and adding new blocks to the chain, ensuring the system operates smoothly. In return for their services, validators earn rewards. However, the role comes with inherent risks, such as slashing penalties for misbehavior or technical failures. If you’re new to validation, starting on Kusama provides a lower-stakes environment to gai", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain.md", + "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/", + "preview": "Learn how to build a custom parachain with Polkadot SDK's FRAME framework, which includes pallet development, testing, smart contracts, and runtime customization. Pallets are modular components within the FRAME ecosystem that contain specific blockchain functionalities. This modularity grants developers increased flexibility and control around which behaviors to include in the core logic of their parachain.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1899, + "words": 259, + "headings": 2, + "estimated_token_count_total": 335 + }, + "hash": "sha256:9a08b66442c564c7116c686d8914b74ad617326f450d0894b05e753462f69aac", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-parachains-deployment-build-deterministic-runtime", + "title": "Build a deterministic runtime", + "slug": "develop-parachains-deployment-build-deterministic-runtime", + "categories": [ + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-build-deterministic-runtime.md", + "html_url": "https://docs.polkadot.com/develop/parachains/deployment/build-deterministic-runtime/", + "preview": "By default, the Rust compiler produces optimized Wasm binaries. These binaries are suitable for working in an isolated environment, such as local development. However, the Wasm binaries the compiler builds by default aren't guaranteed to be deterministically reproducible. Each time the compiler generates the Wasm runtime, it might produce a slightly different Wasm byte code. This is problematic in a blockchain network where all nodes must use exactly the same raw chain specification file.", "outline": [ { "depth": 2, @@ -1630,105 +1840,59 @@ }, { "depth": 2, - "title": "Minimum Hardware Requirements", - "anchor": "minimum-hardware-requirements" + "title": "Tooling for Wasm Runtime", + "anchor": "tooling-for-wasm-runtime" }, { "depth": 2, - "title": "VPS Provider List", - "anchor": "vps-provider-list" + "title": "Working with the Docker Container", + "anchor": "working-with-the-docker-container" }, { "depth": 2, - "title": "Minimum Bond Requirement", - "anchor": "minimum-bond-requirement" - } - ], - "stats": { - "chars": 6842, - "words": 944, - "headings": 5, - "estimated_token_count_total": 1485 - }, - "hash": "sha256:46435b97c37ef6798d2c75c69df31c5e5f07e04b218c370ec5af6b1838d43aac", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", - "title": "Offenses and Slashes", - "slug": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/offenses-and-slashes/", - "preview": "In Polkadot's Nominated Proof of Stake (NPoS) system, validator misconduct is deterred through a combination of slashing, disabling, and reputation penalties. Validators and nominators who stake tokens face consequences for validator misbehavior, which range from token slashes to restrictions on network participation.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Prepare the Environment", + "anchor": "prepare-the-environment" }, { "depth": 2, - "title": "Offenses", - "anchor": "offenses" - }, - { - "depth": 3, - "title": "Invalid Votes", - "anchor": "invalid-votes" - }, - { - "depth": 3, - "title": "Equivocations", - "anchor": "equivocations" + "title": "Start a Deterministic Build", + "anchor": "start-a-deterministic-build" }, { "depth": 2, - "title": "Penalties", - "anchor": "penalties" + "title": "Use srtool in GitHub Actions", + "anchor": "use-srtool-in-github-actions" }, { - "depth": 3, - "title": "Slashing", - "anchor": "slashing" - }, - { - "depth": 3, - "title": "Disabling", - "anchor": "disabling" - }, - { - "depth": 3, - "title": "Reputation Changes", - "anchor": "reputation-changes" + "depth": 2, + "title": "Use the srtool Image via Docker Hub", + "anchor": "use-the-srtool-image-via-docker-hub" }, { "depth": 3, - "title": "Penalties by Offense", - "anchor": "penalties-by-offense" + "title": "Naming Convention for Images", + "anchor": "naming-convention-for-images" } ], "stats": { - "chars": 15427, - "words": 2103, + "chars": 8470, + "words": 1227, "headings": 9, - "estimated_token_count_total": 3409 + "estimated_token_count_total": 1944 }, - "hash": "sha256:abe6bedab04f463ec07f554977b8d6355a5d2fad9bcda01cbe58568152295daa", + "hash": "sha256:4fc8cab40e982e860b64d9aede1058fe7fa82ec321ac215b919db00c4df0a9c0", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", - "title": "Rewards Payout", - "slug": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", + "id": "develop-parachains-deployment-coretime-renewal", + "title": "Coretime Renewal", + "slug": "develop-parachains-deployment-coretime-renewal", "categories": [ - "Infrastructure" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-rewards.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/rewards/", - "preview": "Understanding how rewards are distributed to validators and nominators is essential for network participants. In Polkadot and Kusama, validators earn rewards based on their era points, which are accrued through actions like block production and parachain validation.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-coretime-renewal.md", + "html_url": "https://docs.polkadot.com/develop/parachains/deployment/coretime-renewal/", + "preview": "Coretime can be purchased in bulk for a period of 28 days, providing access to Polkadot's shared security and interoperability for Polkadot parachains. The bulk purchase of coretime includes a rent-control mechanism that keeps future purchases within a predictable price range of the initial purchase. This allows cores to be renewed at a known price without competing against other participants in the open market.", "outline": [ { "depth": 2, @@ -1737,49 +1901,69 @@ }, { "depth": 2, - "title": "Era Points", - "anchor": "era-points" + "title": "Bulk Sale Phases", + "anchor": "bulk-sale-phases" }, { "depth": 2, - "title": "Reward Variance", - "anchor": "reward-variance" + "title": "Renewal Timing", + "anchor": "renewal-timing" }, { "depth": 2, - "title": "Payout Scheme", - "anchor": "payout-scheme" + "title": "Manual Renewal", + "anchor": "manual-renewal" }, { "depth": 2, - "title": "Running Multiple Validators", - "anchor": "running-multiple-validators" + "title": "Auto-Renewal", + "anchor": "auto-renewal" }, { - "depth": 2, - "title": "Nominators and Validator Payments", - "anchor": "nominators-and-validator-payments" + "depth": 3, + "title": "Set Up an HRMP Channel", + "anchor": "set-up-an-hrmp-channel" + }, + { + "depth": 3, + "title": "Fund Sovereign Account", + "anchor": "fund-sovereign-account" + }, + { + "depth": 3, + "title": "Auto-Renewal Configuration Extrinsics", + "anchor": "auto-renewal-configuration-extrinsics" + }, + { + "depth": 3, + "title": "Construct the Enable Auto-Renewal Extrinsic", + "anchor": "construct-the-enable-auto-renewal-extrinsic" + }, + { + "depth": 3, + "title": "Submit the XCM from Your Parachain", + "anchor": "submit-the-xcm-from-your-parachain" } ], "stats": { - "chars": 10976, - "words": 1753, - "headings": 6, - "estimated_token_count_total": 2588 + "chars": 13912, + "words": 1894, + "headings": 10, + "estimated_token_count_total": 3068 }, - "hash": "sha256:d5d6d72eb2cf10f624d84c65f2274f7df90acb5d071bf170bc8eae8d98a810a5", + "hash": "sha256:9918593a46c12a1756552ddfaf7421ad6262600735b6f1fec030911420fe1736", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-add-existing-pallets", - "title": "Add an Existing Pallet to the Runtime", - "slug": "parachains-customize-runtime-add-existing-pallets", + "id": "develop-parachains-deployment-generate-chain-specs", + "title": "Generate Chain Specs", + "slug": "develop-parachains-deployment-generate-chain-specs", "categories": [ "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-existing-pallets.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-existing-pallets/", - "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a functional runtime that includes default [FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} development modules ([pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}) to help you get started building a custo", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-generate-chain-specs.md", + "html_url": "https://docs.polkadot.com/develop/parachains/deployment/generate-chain-specs/", + "preview": "A chain specification collects information that describes a Polkadot SDK-based network. A chain specification is a crucial parameter when starting a node, providing the genesis configurations, bootnodes, and other parameters relating to that particular network. It identifies the network a blockchain node connects to, the other nodes it initially communicates with, and the initial state that nodes must agree on to produce blocks.", "outline": [ { "depth": 2, @@ -1788,63 +1972,53 @@ }, { "depth": 2, - "title": "Check Prerequisites", - "anchor": "check-prerequisites" + "title": "Node Settings Customization", + "anchor": "node-settings-customization" }, { "depth": 2, - "title": "Add an Existing Polkadot SDK Pallet to Your Runtime", - "anchor": "add-an-existing-polkadot-sdk-pallet-to-your-runtime" - }, - { - "depth": 3, - "title": "Add an Existing Pallet as a Dependency", - "anchor": "add-an-existing-pallet-as-a-dependency" + "title": "Genesis Configuration Customization", + "anchor": "genesis-configuration-customization" }, { - "depth": 3, - "title": "Enable Standard Library Features", - "anchor": "enable-standard-library-features" + "depth": 2, + "title": "Declaring Storage Items for a Runtime", + "anchor": "declaring-storage-items-for-a-runtime" }, { - "depth": 3, - "title": "Review the Config Trait", - "anchor": "review-the-config-trait" + "depth": 2, + "title": "Chain Specification JSON Format", + "anchor": "chain-specification-json-format" }, { - "depth": 3, - "title": "Implement the Config Trait", - "anchor": "implement-the-config-trait" + "depth": 2, + "title": "Creating a Custom Chain Specification", + "anchor": "creating-a-custom-chain-specification" }, { "depth": 3, - "title": "Add to Runtime Construct", - "anchor": "add-to-runtime-construct" + "title": "Plain Chain Specifications", + "anchor": "plain-chain-specifications" }, { "depth": 3, - "title": "Verify the Runtime Compiles", - "anchor": "verify-the-runtime-compiles" + "title": "Raw Chain Specifications", + "anchor": "raw-chain-specifications" }, { "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" - }, - { - "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" + "title": "Generate Custom Keys for Your Collator", + "anchor": "generate-custom-keys-for-your-collator" }, { "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" + "title": "Add Invulnerables", + "anchor": "add-invulnerables" }, { "depth": 3, - "title": "Interact with the Pallet", - "anchor": "interact-with-the-pallet" + "title": "Add Session Keys", + "anchor": "add-session-keys" }, { "depth": 2, @@ -1853,24 +2027,24 @@ } ], "stats": { - "chars": 11924, - "words": 1585, - "headings": 14, - "estimated_token_count_total": 2724 + "chars": 14573, + "words": 1931, + "headings": 12, + "estimated_token_count_total": 3025 }, - "hash": "sha256:93d123cbaaccc2515b4a70be8e1327b4f75b1051d16c5e3daf5a2035af7b7ca3", + "hash": "sha256:a60fe36a5ba6d1cafe12eab75300afd24a46d3ace1e791087adb7e3e538afcc3", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-add-pallet-instances", - "title": "Add Multiple Pallet Instances", - "slug": "parachains-customize-runtime-add-pallet-instances", + "id": "develop-parachains-deployment-manage-coretime", + "title": "Manage Coretime", + "slug": "develop-parachains-deployment-manage-coretime", "categories": [ "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-pallet-instances.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-pallet-instances/", - "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a solid foundation for building custom parachains. While most pallets are typically included as single instances within a runtime, some scenarios benefit from running multiple instances of the same pallet with different configurations. This approach lets you reuse pallet logic without reimplementing it, enabling diverse functionality from a single codebase.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-manage-coretime.md", + "html_url": "https://docs.polkadot.com/develop/parachains/deployment/manage-coretime/", + "preview": "Coretime management involves manipulating [bulk coretime](/parachains/launch-a-parachain/obtain-coretime/#bulk-coretime){target=\\_blank} regions to optimize resource allocation and usage. Regions represent allocated computational resources on cores and can be modified through various operations to meet different project requirements. This guide covers the essential operations for managing your coretime regions effectively.", "outline": [ { "depth": 2, @@ -1879,98 +2053,300 @@ }, { "depth": 2, - "title": "Check Prerequisites", - "anchor": "check-prerequisites" + "title": "Transfer", + "anchor": "transfer" }, { "depth": 2, - "title": "Understanding Instantiable Pallets", - "anchor": "understanding-instantiable-pallets" + "title": "Partition", + "anchor": "partition" }, { - "depth": 3, - "title": "Identifying an Instantiable Pallet", - "anchor": "identifying-an-instantiable-pallet" + "depth": 2, + "title": "Interlace", + "anchor": "interlace" }, { - "depth": 3, - "title": "How Instance Generics Work", - "anchor": "how-instance-generics-work" + "depth": 2, + "title": "Assign", + "anchor": "assign" }, { "depth": 2, - "title": "Add Multiple Instances of a Pallet to Your Runtime", - "anchor": "add-multiple-instances-of-a-pallet-to-your-runtime" - }, + "title": "Pool", + "anchor": "pool" + } + ], + "stats": { + "chars": 5736, + "words": 841, + "headings": 6, + "estimated_token_count_total": 1289 + }, + "hash": "sha256:39c58dbe2ddcd542d7074d08d72f1811318dc8a3130419025480fd5cbe9fc3e7", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-parachains-deployment", + "title": "Deployment", + "slug": "develop-parachains-deployment", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment.md", + "html_url": "https://docs.polkadot.com/develop/parachains/deployment/", + "preview": "Learn how to prepare your blockchain for deployment using the Polkadot SDK, including building deterministic Wasm runtimes and generating chain specifications.", + "outline": [ { - "depth": 3, - "title": "Add the Pallet as a Dependency", - "anchor": "add-the-pallet-as-a-dependency" + "depth": 2, + "title": "Deployment Process", + "anchor": "deployment-process" }, { - "depth": 3, - "title": "Enable Standard Library Features", - "anchor": "enable-standard-library-features" + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" }, { - "depth": 3, - "title": "Review the Config Trait", - "anchor": "review-the-config-trait" - }, + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 4818, + "words": 659, + "headings": 3, + "estimated_token_count_total": 966 + }, + "hash": "sha256:b25618dc598f4f946da06f854211645768214e0b51d06b684b0cab668b66124c", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-parachains-maintenance-configure-asynchronous-backing", + "title": "Configure Asynchronous Backing", + "slug": "develop-parachains-maintenance-configure-asynchronous-backing", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-maintenance-configure-asynchronous-backing.md", + "html_url": "https://docs.polkadot.com/develop/parachains/maintenance/configure-asynchronous-backing/", + "preview": "This guide applies to parachain projects based on Cumulus that started in 2023 or earlier, where the backing process was synchronous, allowing parablocks to be built only on the latest relay chain block. In contrast, async backing will enable collators to build parablocks on older relay chain blocks and create pipelines of multiple pending parablocks. This parallel block generation increases efficiency and throughput.", + "outline": [ { - "depth": 3, - "title": "Define Pallet Parameters", - "anchor": "define-pallet-parameters" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Create Instance Type Definitions", - "anchor": "create-instance-type-definitions" + "depth": 2, + "title": "Prerequisite", + "anchor": "prerequisite" }, { - "depth": 3, - "title": "Implement Config Trait for First Instance", - "anchor": "implement-config-trait-for-first-instance" + "depth": 2, + "title": "Phase 1 - Update Parachain Runtime", + "anchor": "phase-1-update-parachain-runtime" }, { - "depth": 3, - "title": "Implement Config Trait for Second Instance", - "anchor": "implement-config-trait-for-second-instance" + "depth": 2, + "title": "Phase 2 - Update Parachain Nodes", + "anchor": "phase-2-update-parachain-nodes" }, { - "depth": 3, - "title": "Add Instances to Runtime Construct", - "anchor": "add-instances-to-runtime-construct" + "depth": 2, + "title": "Phase 3 - Activate Async Backing", + "anchor": "phase-3-activate-async-backing" }, { - "depth": 3, - "title": "Verify the Runtime Compiles", - "anchor": "verify-the-runtime-compiles" + "depth": 2, + "title": "Timing by Block Number", + "anchor": "timing-by-block-number" + } + ], + "stats": { + "chars": 20813, + "words": 2382, + "headings": 6, + "estimated_token_count_total": 4719 + }, + "hash": "sha256:bfad885d8053d052c55dbffc3c09e6196586795c3a1d07ab6ad58f9006ec3345", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-parachains-maintenance-runtime-metrics-monitoring", + "title": "Runtime Metrics and Monitoring", + "slug": "develop-parachains-maintenance-runtime-metrics-monitoring", + "categories": [ + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-maintenance-runtime-metrics-monitoring.md", + "html_url": "https://docs.polkadot.com/develop/parachains/maintenance/runtime-metrics-monitoring/", + "preview": "Maintaining a stable, secure, and efficient network requires continuous monitoring. Polkadot SDK-based nodes are equipped with built-in telemetry components that automatically collect and transmit detailed data about node performance in real-time. This telemetry system is a core feature of the Substrate framework, allowing for easy monitoring of network health without complex setup.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" + "title": "Runtime Metrics", + "anchor": "runtime-metrics" }, { - "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" + "depth": 2, + "title": "Visual Monitoring", + "anchor": "visual-monitoring" }, { - "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" + "depth": 2, + "title": "Displaying Network-Wide Statistics", + "anchor": "displaying-network-wide-statistics" }, { - "depth": 3, - "title": "Interact with Both Pallet Instances", - "anchor": "interact-with-both-pallet-instances" + "depth": 2, + "title": "Customizing Monitoring Tools", + "anchor": "customizing-monitoring-tools" }, { "depth": 3, - "title": "Test Instance Independence", - "anchor": "test-instance-independence" + "title": "On-Chain Activity", + "anchor": "on-chain-activity" + }, + { + "depth": 2, + "title": "Monitoring Tools", + "anchor": "monitoring-tools" + }, + { + "depth": 3, + "title": "Change the Telemetry Server", + "anchor": "change-the-telemetry-server" + } + ], + "stats": { + "chars": 8458, + "words": 1202, + "headings": 8, + "estimated_token_count_total": 1819 + }, + "hash": "sha256:b0c1535fa8e969a9bdeee426a5a35a42b4649121fb8ce6fd2b15fdeba35b5d5f", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-parachains-maintenance", + "title": "Maintenance", + "slug": "develop-parachains-maintenance", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-maintenance.md", + "html_url": "https://docs.polkadot.com/develop/parachains/maintenance/", + "preview": "Learn how to maintain Polkadot SDK-based networks, focusing on runtime monitoring, upgrades, and storage migrations for optimal performance. Proper maintenance ensures your blockchain remains secure, efficient, and adaptable to changing needs. These sections will guide you through monitoring your network, using runtime versioning, and performing forkless upgrades to keep your blockchain secure and up-to-date without downtime.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1372, + "words": 174, + "headings": 2, + "estimated_token_count_total": 236 + }, + "hash": "sha256:3b0a9e8037c7634c33ac6674170bd763599fca914855d9d2fbf490d359140130", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-parachains-testing", + "title": "Testing Your Polkadot SDK-Based Blockchain", + "slug": "develop-parachains-testing", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-testing.md", + "html_url": "https://docs.polkadot.com/develop/parachains/testing/", + "preview": "Explore comprehensive testing strategies for Polkadot SDK-based blockchains, from setting up test environments to verifying runtime and pallet interactions. Testing is essential to feeling confident your network will behave the way you intend upon deployment.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1243, + "words": 157, + "headings": 2, + "estimated_token_count_total": 211 + }, + "hash": "sha256:0ce1fe38de00827a0735b9fa8076492205c2450c61da9fbd1937d9f38cfe7825", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-parachains", + "title": "Parachains", + "slug": "develop-parachains", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains.md", + "html_url": "https://docs.polkadot.com/develop/parachains/", + "preview": "This section provides a complete guide to working with the Polkadot SDK, from getting started to long-term network maintenance. Discover how to create custom blockchains, test and deploy your parachains, and ensure their continued performance and reliability.", + "outline": [ + { + "depth": 2, + "title": "Building Parachains with the Polkadot SDK", + "anchor": "building-parachains-with-the-polkadot-sdk" + }, + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 1994, + "words": 264, + "headings": 2, + "estimated_token_count_total": 330 + }, + "hash": "sha256:75a6fa2f21b67009be62e07bab01655a10b2c35a5292dc1f7ca57df846d709f3", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-smart-contracts-connect-to-kusama", + "title": "Connect to Kusama", + "slug": "develop-smart-contracts-connect-to-kusama", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-connect-to-kusama.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/connect-to-kusama/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", + "outline": [ + { + "depth": 2, + "title": "Networks Details", + "anchor": "networks-details" + }, + { + "depth": 2, + "title": "Important Deployment Considerations", + "anchor": "important-deployment-considerations" }, { "depth": 2, @@ -1979,499 +2355,678 @@ } ], "stats": { - "chars": 17923, - "words": 2203, - "headings": 21, - "estimated_token_count_total": 3811 + "chars": 3601, + "words": 476, + "headings": 3, + "estimated_token_count_total": 514 }, - "hash": "sha256:d83e574726c524fa017236eb5e3b8a0676d598be4da1ce4fe25a60141baeee49", + "hash": "sha256:e8ffeaa3a17e20437a59f2c95a63821eb75bf3c33001e748c23958b2b99ac3c2", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-add-smart-contract-functionality", - "title": "Add Smart Contract Functionality", - "slug": "parachains-customize-runtime-add-smart-contract-functionality", + "id": "develop-smart-contracts-dev-environments", + "title": "Dev Environments", + "slug": "develop-smart-contracts-dev-environments", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-smart-contract-functionality/", - "preview": "When building your custom blockchain with the Polkadot SDK, you can add smart contract capabilities through specialized pallets. These pallets enable users to deploy and execute smart contracts, enhancing your chain's programmability and allowing developers to build decentralized applications on your network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-dev-environments.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/dev-environments/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Explore the tools and frameworks available for building and testing smart contracts on the Polkadot network. These environments streamline the development process, from writing and compiling to testing and deploying smart contracts. The guides in this section will help you evaluate each tool's strengths, making it easier to choose t", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "What to Consider", + "anchor": "what-to-consider" }, { "depth": 2, - "title": "pallet-revive", - "anchor": "pallet-revive" + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 1601, + "words": 154, + "headings": 2, + "estimated_token_count_total": 323 + }, + "hash": "sha256:5c3a10769e30b4da62e6c188e99310354e6e9af4595c7920c2977a54b8e1853c", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-smart-contracts-faqs", + "title": "Polkadot Hub Smart Contract FAQs", + "slug": "develop-smart-contracts-faqs", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-faqs.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/faqs/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. !!! note For a list of known incompatibilities, please refer to the [Solidity and Yul IR translation incompatibilities](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#solidity-and-yul-ir-translation-incompatibilities){target=\\_blank} section.", + "outline": [ + { + "depth": 2, + "title": "General Questions", + "anchor": "general-questions" }, { "depth": 3, - "title": "Core Components", - "anchor": "core-components" + "title": "What are the different types of smart contracts I can build on Polkadot?", + "anchor": "what-are-the-different-types-of-smart-contracts-i-can-build-on-polkadot" }, { "depth": 3, - "title": "Supported Languages and Compilers", - "anchor": "supported-languages-and-compilers" + "title": "Should I build a smart contract or a parachain?", + "anchor": "should-i-build-a-smart-contract-or-a-parachain" }, { "depth": 3, - "title": "How It Works", - "anchor": "how-it-works" + "title": "What's the difference between Polkadot Hub smart contracts and other EVM chains?", + "anchor": "whats-the-difference-between-polkadot-hub-smart-contracts-and-other-evm-chains" + }, + { + "depth": 2, + "title": "Development Environment", + "anchor": "development-environment" }, { "depth": 3, - "title": "Key Benefits", - "anchor": "key-benefits" + "title": "Can I use my existing Ethereum development tools?", + "anchor": "can-i-use-my-existing-ethereum-development-tools" }, { "depth": 3, - "title": "Implementation Examples", - "anchor": "implementation-examples" + "title": "How do I set up local development?", + "anchor": "how-do-i-set-up-local-development" + }, + { + "depth": 3, + "title": "What networks are available for testing and deployment?", + "anchor": "what-networks-are-available-for-testing-and-deployment" }, { "depth": 2, - "title": "Frontier", - "anchor": "frontier" + "title": "Technical Implementation", + "anchor": "technical-implementation" }, { "depth": 3, - "title": "Integration Options", - "anchor": "integration-options" + "title": "How do Ethereum addresses work on Polkadot?", + "anchor": "how-do-ethereum-addresses-work-on-polkadot" }, { "depth": 3, - "title": "EVM Execution Only", - "anchor": "evm-execution-only" + "title": "What are the key differences in the gas model?", + "anchor": "what-are-the-key-differences-in-the-gas-model" }, { "depth": 3, - "title": "Full Ethereum Compatibility", - "anchor": "full-ethereum-compatibility" + "title": "How does contract deployment work?", + "anchor": "how-does-contract-deployment-work" }, { "depth": 3, - "title": "Key Benefits", - "anchor": "key-benefits-2" + "title": "Which Solidity features are not supported?", + "anchor": "which-solidity-features-are-not-supported" }, { "depth": 3, - "title": "Implementation Examples", - "anchor": "implementation-examples-2" + "title": "How do I handle the existential deposit requirement?", + "anchor": "how-do-i-handle-the-existential-deposit-requirement" }, { "depth": 2, - "title": "pallet-contracts (Legacy)", - "anchor": "pallet-contracts-legacy" + "title": "Migration and Compatibility", + "anchor": "migration-and-compatibility" }, { "depth": 3, - "title": "Implementation Example", - "anchor": "implementation-example" + "title": "Can I migrate my existing Ethereum contracts?", + "anchor": "can-i-migrate-my-existing-ethereum-contracts" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 6655, - "words": 833, - "headings": 16, - "estimated_token_count_total": 1631 - }, - "hash": "sha256:6297bb5e0809fdd0585d6170054599f7ab4a3ce7c687ad03ae43092057c493b7", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", - "title": "Add Pallets to the Runtime", - "slug": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", - "categories": [ - "Basics", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-add-pallet-to-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/", - "preview": "In previous tutorials, you learned how to [create a custom pallet](/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/){target=\\_blank} and [test it](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/){target=\\_blank}. The next step is to include this pallet in your runtime, integrating it into the core logic of your blockchain.", - "outline": [ + "title": "Troubleshooting", + "anchor": "troubleshooting" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Why are my gas calculations different?", + "anchor": "why-are-my-gas-calculations-different" }, { - "depth": 2, - "title": "Add the Pallets as Dependencies", - "anchor": "add-the-pallets-as-dependencies" + "depth": 3, + "title": "I deployed a contract with MetaMask, and got a `code size` error - why?", + "anchor": "i-deployed-a-contract-with-metamask-and-got-a-code-size-error-why" }, { "depth": 3, - "title": "Update the Runtime Configuration", - "anchor": "update-the-runtime-configuration" + "title": "I found a bug, where can I log it?", + "anchor": "i-found-a-bug-where-can-i-log-it" }, { "depth": 2, - "title": "Recompile the Runtime", - "anchor": "recompile-the-runtime" + "title": "Known Issues", + "anchor": "known-issues" }, { - "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" + "depth": 3, + "title": "Runtime Behavior", + "anchor": "runtime-behavior" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Development Tools", + "anchor": "development-tools" + }, + { + "depth": 3, + "title": "Contract Patterns", + "anchor": "contract-patterns" + }, + { + "depth": 3, + "title": "Compilation", + "anchor": "compilation" } ], "stats": { - "chars": 13091, - "words": 1522, - "headings": 6, - "estimated_token_count_total": 3091 + "chars": 7480, + "words": 984, + "headings": 25, + "estimated_token_count_total": 1618 }, - "hash": "sha256:87add0ae178e4970601a27efccadb58eff1375d19819201034ba2829914f1cd5", + "hash": "sha256:5cc63ff0a377ef0ec96a064748e13b88bc852bd1862c6e344066855a7fe93b19", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-pallet-development-benchmark-pallet", - "title": "Benchmark Your Pallet", - "slug": "parachains-customize-runtime-pallet-development-benchmark-pallet", + "id": "develop-smart-contracts-libraries", + "title": "Libraries", + "slug": "develop-smart-contracts-libraries", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/benchmark-pallet/", - "preview": "Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-libraries.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/libraries/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Explore the key libraries for interacting with smart contracts on Polkadot-based networks. These libraries simplify contract calls, event listening, and transaction handling.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Library Comparison", + "anchor": "library-comparison" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 2056, + "words": 203, + "headings": 2, + "estimated_token_count_total": 415 + }, + "hash": "sha256:23137f6c74412fd98c0b6aeee3ff59938e44b817ec42974c453f9b0f66e36513", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-smart-contracts-precompiles-interact-with-precompiles", + "title": "Interact with Precompiles", + "slug": "develop-smart-contracts-precompiles-interact-with-precompiles", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-precompiles-interact-with-precompiles.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/precompiles/interact-with-precompiles/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ { "depth": 2, - "title": "Create the Benchmarking Module", - "anchor": "create-the-benchmarking-module" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Define the Weight Trait", - "anchor": "define-the-weight-trait" + "title": "Basic Precompile Interaction Pattern", + "anchor": "basic-precompile-interaction-pattern" }, { "depth": 2, - "title": "Add WeightInfo to Config", - "anchor": "add-weightinfo-to-config" + "title": "ECRecover (0x01)", + "anchor": "ecrecover-0x01" }, { "depth": 2, - "title": "Update Extrinsic Weight Annotations", - "anchor": "update-extrinsic-weight-annotations" + "title": "SHA-256 (0x02)", + "anchor": "sha-256-0x02" }, { "depth": 2, - "title": "Include the Benchmarking Module", - "anchor": "include-the-benchmarking-module" + "title": "RIPEMD-160 (0x03)", + "anchor": "ripemd-160-0x03" }, { "depth": 2, - "title": "Configure Pallet Dependencies", - "anchor": "configure-pallet-dependencies" + "title": "Identity (Data Copy) (0x04)", + "anchor": "identity-data-copy-0x04" }, { "depth": 2, - "title": "Update Mock Runtime", - "anchor": "update-mock-runtime" + "title": "Modular Exponentiation (0x05)", + "anchor": "modular-exponentiation-0x05" }, { "depth": 2, - "title": "Configure Runtime Benchmarking", - "anchor": "configure-runtime-benchmarking" + "title": "BN128 Addition (0x06)", + "anchor": "bn128-addition-0x06" }, { "depth": 2, - "title": "Test Benchmark Compilation", - "anchor": "test-benchmark-compilation" + "title": "BN128 Scalar Multiplication (0x07)", + "anchor": "bn128-scalar-multiplication-0x07" }, { "depth": 2, - "title": "Build the Runtime with Benchmarks", - "anchor": "build-the-runtime-with-benchmarks" + "title": "BN128 Pairing Check (0x08)", + "anchor": "bn128-pairing-check-0x08" }, { "depth": 2, - "title": "Install the Benchmarking Tool", - "anchor": "install-the-benchmarking-tool" + "title": "Blake2F (0x09)", + "anchor": "blake2f-0x09" }, { "depth": 2, - "title": "Download the Weight Template", - "anchor": "download-the-weight-template" - }, - { - "depth": 2, - "title": "Execute Benchmarks", - "anchor": "execute-benchmarks" - }, - { - "depth": 2, - "title": "Use Generated Weights", - "anchor": "use-generated-weights" - }, - { - "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" - }, - { - "depth": 2, - "title": "Related Resources", - "anchor": "related-resources" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 22752, - "words": 2813, - "headings": 18, - "estimated_token_count_total": 5191 + "chars": 18054, + "words": 2190, + "headings": 12, + "estimated_token_count_total": 3847 }, - "hash": "sha256:c1b53ecbfc3dea02097104c7a4c652e61ccc42ad56325a9c80684850a198fbdd", + "hash": "sha256:4b705b8dbe9b0ad8d19a897d91f3c64dbc4541297dadacbea2a31b4778e50a46", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-pallet-development-create-a-pallet", - "title": "Create a Custom Pallet", - "slug": "parachains-customize-runtime-pallet-development-create-a-pallet", + "id": "develop-smart-contracts", + "title": "Smart Contracts", + "slug": "develop-smart-contracts", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/create-a-pallet/", - "preview": "[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functional", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts.md", + "html_url": "https://docs.polkadot.com/develop/smart-contracts/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Polkadot allows scalable execution of smart contracts, offering cross-chain compatibility and lower fees than legacy L1 platforms. Polkadot provides developers with flexibility in building smart contracts, supporting both Solidity contracts executed by the [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\\_blank} (a Polkadot", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Smart Contract Development Process", + "anchor": "smart-contract-development-process" }, { "depth": 2, - "title": "Core Pallet Components", - "anchor": "core-pallet-components" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1867, + "words": 247, + "headings": 2, + "estimated_token_count_total": 189 + }, + "hash": "sha256:4b56a119cbc63d87de98554cf4019e48ddb4f7cee11a51553ea234f91d78f8b8", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-api-libraries", + "title": "API Libraries", + "slug": "develop-toolkit-api-libraries", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/", + "preview": "Explore the powerful API libraries designed for interacting with the Polkadot network. These libraries offer developers versatile tools to build, query, and manage blockchain interactions. Whether you’re working with JavaScript, TypeScript, Python, or RESTful services, they provide the flexibility to efficiently interact with and retrieve data from Polkadot-based chains.", + "outline": [ { "depth": 2, - "title": "Create the Pallet Project", - "anchor": "create-the-pallet-project" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Configure Dependencies", - "anchor": "configure-dependencies" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1082, + "words": 139, + "headings": 2, + "estimated_token_count_total": 187 + }, + "hash": "sha256:746788d1068fe3eaafc34eb461566d1682c27fcad7d448e65810b9662b45dd85", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-integrations-storage", + "title": "Storage", + "slug": "develop-toolkit-integrations-storage", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-storage.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/storage/", + "preview": "Polkadot offers developers a range of decentralized storage solutions to manage dApp data, host front ends, and store large files in a censorship-resistant and resilient manner. These integrations are essential for building fully decentralized applications, ensuring that all components of your dApp, from the front end to the data, are not reliant on centralized servers.", + "outline": [ { "depth": 2, - "title": "Initialize the Pallet Structure", - "anchor": "initialize-the-pallet-structure" + "title": "Key Storage Solutions", + "anchor": "key-storage-solutions" }, { "depth": 2, - "title": "Configure the Pallet", - "anchor": "configure-the-pallet" + "title": "Crust Network", + "anchor": "crust-network" }, { - "depth": 2, - "title": "Define Events", - "anchor": "define-events" + "depth": 3, + "title": "Key Features of Crust", + "anchor": "key-features-of-crust" }, { - "depth": 2, - "title": "Define Errors", - "anchor": "define-errors" + "depth": 3, + "title": "Use Cases", + "anchor": "use-cases" }, { "depth": 2, - "title": "Add Storage Items", - "anchor": "add-storage-items" + "title": "IPFS", + "anchor": "ipfs" }, { - "depth": 2, - "title": "Configure Genesis State", - "anchor": "configure-genesis-state" + "depth": 3, + "title": "Using IPFS with Polkadot", + "anchor": "using-ipfs-with-polkadot" }, { "depth": 2, - "title": "Implement Dispatchable Functions", - "anchor": "implement-dispatchable-functions" - }, - { - "depth": 3, - "title": "Dispatchable Function Details", - "anchor": "dispatchable-function-details" - }, + "title": "Other Solutions", + "anchor": "other-solutions" + } + ], + "stats": { + "chars": 4369, + "words": 642, + "headings": 7, + "estimated_token_count_total": 847 + }, + "hash": "sha256:a206dd86fc3d80aed22384000839ca0c9c75c69ad461abd9810d96c03cf6a3bd", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-integrations-transaction-construction", + "title": "Transaction Construction", + "slug": "develop-toolkit-integrations-transaction-construction", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-transaction-construction.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/transaction-construction/", + "preview": "This page will discuss the transaction format in Polkadot and how to create, sign, and broadcast transactions, as well as highlight some of the commands and tools available for integrators.", + "outline": [ { "depth": 2, - "title": "Verify Pallet Compilation", - "anchor": "verify-pallet-compilation" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Add the Pallet to Your Runtime", - "anchor": "add-the-pallet-to-your-runtime" + "title": "Transaction Format", + "anchor": "transaction-format" }, { "depth": 3, - "title": "Add Runtime Dependency", - "anchor": "add-runtime-dependency" + "title": "Mode and Metadata Hash", + "anchor": "mode-and-metadata-hash" }, { "depth": 3, - "title": "Implement the Config Trait", - "anchor": "implement-the-config-trait" + "title": "Serialized Transactions and Metadata", + "anchor": "serialized-transactions-and-metadata" }, { "depth": 3, - "title": "Add to Runtime Construct", - "anchor": "add-to-runtime-construct" + "title": "Transaction Flow", + "anchor": "transaction-flow" }, { - "depth": 3, - "title": "Configure Genesis for Your Runtime", - "anchor": "configure-genesis-for-your-runtime" + "depth": 2, + "title": "Polkadot-JS Tools", + "anchor": "polkadot-js-tools" }, { "depth": 3, - "title": "Verify Runtime Compilation", - "anchor": "verify-runtime-compilation" + "title": "Creating a Transaction, Signing, and Submitting", + "anchor": "creating-a-transaction-signing-and-submitting" }, { "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" + "title": "Txwrapper", + "anchor": "txwrapper" }, { "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" + "title": "Creating a Transaction, Signing, and Submitting", + "anchor": "creating-a-transaction-signing-and-submitting-2" }, { - "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" - }, + "depth": 2, + "title": "Additional Libraries for Submitting a Transaction", + "anchor": "additional-libraries-for-submitting-a-transaction" + } + ], + "stats": { + "chars": 27671, + "words": 2949, + "headings": 10, + "estimated_token_count_total": 6280 + }, + "hash": "sha256:9b03477d13a285fced6bf845c3827084f790a626989dc2c09ef9ff53643045f4", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-integrations", + "title": "Integrations", + "slug": "develop-toolkit-integrations", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/", + "preview": "Polkadot offers a wide range of integrations that allow developers to enhance their decentralized applications (dApps) and leverage the full capabilities of the ecosystem. Whether you’re looking to extend your application’s functionality, integrate with other chains, or access specialized services, these integrations provide the tools and resources you need to build efficiently and effectively. Explore the available options to find the solutions that best suit your development needs.", + "outline": [ { "depth": 2, - "title": "Interact with Your Pallet", - "anchor": "interact-with-your-pallet" + "title": "Key Integration Solutions", + "anchor": "key-integration-solutions" }, { "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 988, + "words": 135, + "headings": 2, + "estimated_token_count_total": 92 + }, + "hash": "sha256:0de8c1655a1524784010b6cec5fa522b2f764e32f18913f0d262283e0ec0779e", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-interoperability", + "title": "Interoperability", + "slug": "develop-toolkit-interoperability", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-interoperability.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/interoperability/", + "preview": "Polkadot's XCM tooling ecosystem redefines the boundaries of cross-chain communication and asset movement. With unparalleled flexibility and scalability, these advanced tools empower developers to build decentralized applications that connect parachains, relay chains, and external networks. By bridging siloed blockchains, Polkadot paves the way for a unified, interoperable ecosystem that accelerates innovation and collaboration.", + "outline": [ { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 26958, - "words": 3085, - "headings": 26, - "estimated_token_count_total": 6194 + "chars": 1010, + "words": 128, + "headings": 1, + "estimated_token_count_total": 12 }, - "hash": "sha256:dad68ea59fd05fd60dc8890c4cf5615243c7ea879830b0dcf3a5e5e53c3ccec7", + "hash": "sha256:c72d7d30a019fe1db8ab3993f91dfd4f1bdb4a932aaa685d3baaa0578091d5ce", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-pallet-development-mock-runtime", - "title": "Mock Your Runtime", - "slug": "parachains-customize-runtime-pallet-development-mock-runtime", + "id": "develop-toolkit-parachains-e2e-testing", + "title": "E2E Testing on Polkadot SDK Chains", + "slug": "develop-toolkit-parachains-e2e-testing", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/", - "preview": "Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-e2e-testing.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/e2e-testing/", + "preview": ":::INSERT_IN_THIS_SECTION:::", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 64, + "words": 6, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:cc49fdcc63a43247d80de2f309b9c7501d3054782746d80c003d95f3c43da90d", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains-fork-chains-chopsticks", + "title": "Chopsticks", + "slug": "develop-toolkit-parachains-fork-chains-chopsticks", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-fork-chains-chopsticks.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/fork-chains/chopsticks/", + "preview": "Chopsticks is a powerful tool that lets you create local copies of running Polkadot SDK-based networks. By forking live chains locally, you can safely test features, analyze network behavior, and simulate complex scenarios without affecting production networks.", + "outline": [ { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "What Can I Do with Chopsticks?", + "anchor": "what-can-i-do-with-chopsticks" }, { "depth": 2, - "title": "Understand Mock Runtimes", - "anchor": "understand-mock-runtimes" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Create the Mock Runtime Module", - "anchor": "create-the-mock-runtime-module" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1495, + "words": 201, + "headings": 3, + "estimated_token_count_total": 291 + }, + "hash": "sha256:b568596033cdf68e60d72bcb7ee62a794def2bd3ff5b3317ef15895f58a12c57", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains-fork-chains", + "title": "Fork Chains for Testing", + "slug": "develop-toolkit-parachains-fork-chains", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-fork-chains.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/fork-chains/", + "preview": "Explore tools for forking live blockchain networks. These tools enable you to replicate real-world conditions in a local environment for accurate testing and debugging. They also allow you to analyze network behavior, test new features, and simulate complex scenarios in a controlled environment without affecting production systems.", + "outline": [ { "depth": 2, - "title": "Set Up Basic Mock", - "anchor": "set-up-basic-mock" + "title": "Why Fork a Live Chain?", + "anchor": "why-fork-a-live-chain" }, { "depth": 2, - "title": "Implement Essential Configuration", - "anchor": "implement-essential-configuration" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Implement Your Pallet's Configuration", - "anchor": "implement-your-pallets-configuration" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1269, + "words": 173, + "headings": 3, + "estimated_token_count_total": 183 + }, + "hash": "sha256:d29a845b00b24e03f9877a5331c33619918decf453657969115d5ec18033ba28", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains-quickstart-pop-cli", + "title": "Quickstart Parachain Development with Pop CLI", + "slug": "develop-toolkit-parachains-quickstart-pop-cli", + "categories": [ + "Parachains", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-quickstart-pop-cli.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/quickstart/pop-cli/", + "preview": "[Pop CLI](https://onpop.io/cli/){target=\\_blank} is a powerful command-line tool designed explicitly for rapid parachain development within the Polkadot ecosystem. It addresses essential developer needs by providing streamlined commands to set up development environments, scaffold parachain templates, and manage local blockchain networks.", + "outline": [ { "depth": 2, - "title": "Configure Genesis Storage", - "anchor": "configure-genesis-storage" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 3, - "title": "Basic Test Environment", - "anchor": "basic-test-environment" + "title": "Install Pop CLI", + "anchor": "install-pop-cli" }, { "depth": 3, - "title": "Custom Genesis Configurations", - "anchor": "custom-genesis-configurations" - }, - { - "depth": 2, - "title": "Verify Mock Compilation", - "anchor": "verify-mock-compilation" + "title": "Set Up Your Development Environment", + "anchor": "set-up-your-development-environment" }, { - "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" + "depth": 3, + "title": "Initialize a Project", + "anchor": "initialize-a-project" }, { "depth": 2, @@ -2480,24 +3035,50 @@ } ], "stats": { - "chars": 11766, - "words": 1369, - "headings": 13, - "estimated_token_count_total": 2514 + "chars": 4236, + "words": 610, + "headings": 5, + "estimated_token_count_total": 999 }, - "hash": "sha256:dd784a5d2daebb9a885fe09f6a967e6c84958d96ddb38d8366eabe9d860fa539", + "hash": "sha256:6d6c66430a7302f29113924c5208e64d7c244497e50c61ab2f45c4b5141620e4", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-pallet-development-pallet-testing", - "title": "Unit Test Pallets", - "slug": "parachains-customize-runtime-pallet-development-pallet-testing", + "id": "develop-toolkit-parachains-quickstart", + "title": "Quickstart Parachain Development", + "slug": "develop-toolkit-parachains-quickstart", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/", - "preview": "Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-quickstart.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/quickstart/", + "preview": ":::INSERT_IN_THIS_SECTION:::", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 85, + "words": 7, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:91de375b7f822ed56b5e6b4d609d0d36e806d3f77041b4e180b6679b10a3e1c8", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains-remote-proxies", + "title": "Remote Proxies", + "slug": "develop-toolkit-parachains-remote-proxies", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-remote-proxies.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/remote-proxies/", + "preview": "!!!warning \"Kusama Implementation Only\" Remote proxies are currently only available on Kusama and its parachains (such as Kusama Asset Hub). This feature is not yet deployed on Polkadot MainNet. The examples and implementations described in this guide are specific to the Kusama ecosystem.", "outline": [ { "depth": 2, @@ -2506,55 +3087,59 @@ }, { "depth": 2, - "title": "Writing Unit Tests", - "anchor": "writing-unit-tests" + "title": "Remote Proxy Architecture", + "anchor": "remote-proxy-architecture" }, { - "depth": 3, - "title": "Test Initialization", - "anchor": "test-initialization" + "depth": 2, + "title": "Implementation Workflow", + "anchor": "implementation-workflow" + }, + { + "depth": 2, + "title": "Practical Implementation", + "anchor": "practical-implementation" }, { "depth": 3, - "title": "Function Call Testing", - "anchor": "function-call-testing" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 3, - "title": "Storage Testing", - "anchor": "storage-testing" + "title": "Installation and Setup", + "anchor": "installation-and-setup" }, { "depth": 3, - "title": "Event Testing", - "anchor": "event-testing" + "title": "Implementation Example", + "anchor": "implementation-example" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Resources", + "anchor": "resources" } ], "stats": { - "chars": 6895, - "words": 912, - "headings": 7, - "estimated_token_count_total": 1563 + "chars": 9063, + "words": 1113, + "headings": 8, + "estimated_token_count_total": 1863 }, - "hash": "sha256:041ccd82f0c1ddfb93be05feb6cf9d7d4a7e37af6caa8fa8fdab5d5538017122", + "hash": "sha256:7086406b31e7aa9089b221ffaa548ee5540a3d147ec1e93136f481c883f2e434", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime", - "title": "Overview of FRAME", - "slug": "parachains-customize-runtime", + "id": "develop-toolkit-parachains-rpc-calls", + "title": "RPC Calls to Polkadot SDK chains.", + "slug": "develop-toolkit-parachains-rpc-calls", "categories": [ - "Basics", - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/", - "preview": "A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a run", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-rpc-calls.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/rpc-calls/", + "preview": "[Remote Procedure Call](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\\_blank} (RPC) interfaces are the primary way to interact programmatically with Polkadot SDK-based parachains and relay chains. RPC calls allow you to query chain state, submit transactions, and monitor network health from external applications or scripts.", "outline": [ { "depth": 2, @@ -2563,105 +3148,156 @@ }, { "depth": 2, - "title": "Understanding Your Runtime", - "anchor": "understanding-your-runtime" + "title": "How Do RPC Calls Work?", + "anchor": "how-do-rpc-calls-work" }, { "depth": 2, - "title": "Runtime Architecture", - "anchor": "runtime-architecture" + "title": "Making RPC Calls with Curl", + "anchor": "making-rpc-calls-with-curl" }, { "depth": 2, - "title": "Building Blocks: Pallets", - "anchor": "building-blocks-pallets" + "title": "Essential RPC Methods", + "anchor": "essential-rpc-methods" }, { "depth": 3, - "title": "Pre-Built Pallets vs. Custom Pallets", - "anchor": "pre-built-pallets-vs-custom-pallets" + "title": "system_health", + "anchor": "system_health" }, { "depth": 3, - "title": "Pallet Structure", - "anchor": "pallet-structure" + "title": "chain_getBlock", + "anchor": "chain_getblock" }, { - "depth": 2, - "title": "How Runtime Customization Works", - "anchor": "how-runtime-customization-works" + "depth": 3, + "title": "state_getStorage", + "anchor": "state_getstorage" + }, + { + "depth": 3, + "title": "author_submitExtrinsic", + "anchor": "author_submitextrinsic" + }, + { + "depth": 3, + "title": "state_getMetadata", + "anchor": "state_getmetadata" }, { "depth": 2, - "title": "Starting Templates", - "anchor": "starting-templates" + "title": "Check Available RPC Calls", + "anchor": "check-available-rpc-calls" + }, + { + "depth": 3, + "title": "Using curl", + "anchor": "using-curl" + }, + { + "depth": 3, + "title": "Using Polkadot.js Apps", + "anchor": "using-polkadotjs-apps" }, { "depth": 2, - "title": "Key Customization Scenarios", - "anchor": "key-customization-scenarios" + "title": "Resources", + "anchor": "resources" } ], "stats": { - "chars": 8237, - "words": 1101, - "headings": 9, - "estimated_token_count_total": 1828 + "chars": 6496, + "words": 909, + "headings": 13, + "estimated_token_count_total": 1870 }, - "hash": "sha256:28501589d5290f932b55cd3319f6a3fd78d7297ba42810da5ad2784a297224fd", + "hash": "sha256:3b766e00e55a224201bc6744386a6dabc7da54ed9199b16abab3b94cff449eca", "token_estimator": "heuristic-v1" }, { - "id": "parachains-get-started", - "title": "Get Started with Parachain Development", - "slug": "parachains-get-started", + "id": "develop-toolkit-parachains-spawn-chains-zombienet-write-tests", + "title": "Write Tests", + "slug": "develop-toolkit-parachains-spawn-chains-zombienet-write-tests", "categories": [ - "Basics", - "Parachains" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md", - "html_url": "https://docs.polkadot.com/parachains/get-started/", - "preview": "The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet-write-tests.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/", + "preview": "Testing is a critical step in blockchain development, ensuring reliability, performance, and security. Zombienet simplifies this process with its intuitive Domain Specific Language (DSL), enabling developers to write natural-language test scripts tailored to their network needs.", "outline": [ { "depth": 2, - "title": "Quick Start Guides", - "anchor": "quick-start-guides" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Launch a Simple Parachain", - "anchor": "launch-a-simple-parachain" + "title": "Testing DSL", + "anchor": "testing-dsl" }, { "depth": 2, - "title": "Customize Your Runtime", - "anchor": "customize-your-runtime" + "title": "The Test File", + "anchor": "the-test-file" }, { "depth": 3, - "title": "Pallet Development", - "anchor": "pallet-development" + "title": "Name", + "anchor": "name" }, { - "depth": 2, - "title": "Testing", - "anchor": "testing" + "depth": 3, + "title": "Assertions", + "anchor": "assertions" + }, + { + "depth": 3, + "title": "Commands", + "anchor": "commands" }, { "depth": 2, - "title": "Runtime Upgrades and Maintenance", - "anchor": "runtime-upgrades-and-maintenance" + "title": "Running a Test", + "anchor": "running-a-test" }, { "depth": 2, - "title": "Interoperability", - "anchor": "interoperability" + "title": "Example Test Files", + "anchor": "example-test-files" + } + ], + "stats": { + "chars": 11297, + "words": 1491, + "headings": 8, + "estimated_token_count_total": 2661 + }, + "hash": "sha256:04e85c4cddb58252f8253d78a3924bb56952dac2a3e9a057704a91a0d1f21d75", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains-spawn-chains-zombienet", + "title": "Zombienet", + "slug": "develop-toolkit-parachains-spawn-chains-zombienet", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/zombienet/", + "preview": "Zombienet is a testing framework that lets you quickly spin up ephemeral blockchain networks for development and testing. With support for multiple deployment targets, such as Kubernetes, Podman, and native environments, Zombienet makes it easy to validate your blockchain implementation in a controlled environment.", + "outline": [ + { + "depth": 2, + "title": "What Can I Do with Zombienet?", + "anchor": "what-can-i-do-with-zombienet" }, { "depth": 2, - "title": "Integrations", - "anchor": "integrations" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, @@ -2670,257 +3306,367 @@ } ], "stats": { - "chars": 7941, - "words": 631, - "headings": 9, - "estimated_token_count_total": 2292 + "chars": 1237, + "words": 164, + "headings": 3, + "estimated_token_count_total": 193 }, - "hash": "sha256:759ed27cf3d473445e33141089b652082c42a2c59eb822d6b506146fd9555e13", + "hash": "sha256:1355969b6b0e723b42815b960c15eb128e4d936d0d707cd66e43820cff765ee3", "token_estimator": "heuristic-v1" }, { - "id": "parachains-install-polkadot-sdk", - "title": "Install Polkadot SDK", - "slug": "parachains-install-polkadot-sdk", + "id": "develop-toolkit-parachains-spawn-chains", + "title": "Spawn Networks for Testing", + "slug": "develop-toolkit-parachains-spawn-chains", "categories": [ - "Basics", - "Tooling" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md", - "html_url": "https://docs.polkadot.com/parachains/install-polkadot-sdk/", - "preview": "This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/", + "preview": "Testing blockchain networks in a controlled environment is essential for development and validation. The Polkadot ecosystem provides specialized tools that enable you to spawn test networks, helping you verify functionality and catch issues before deploying to production.", "outline": [ { "depth": 2, - "title": "Install Dependencies: macOS", - "anchor": "install-dependencies-macos" - }, - { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-mac-os }", - "anchor": "before-you-begin-before-you-begin-mac-os" + "title": "Why Spawn a Network?", + "anchor": "why-spawn-a-network" }, { - "depth": 3, - "title": "Install Homebrew", - "anchor": "install-homebrew" + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" }, { - "depth": 3, - "title": "Support for Apple Silicon", - "anchor": "support-for-apple-silicon" - }, + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1180, + "words": 155, + "headings": 3, + "estimated_token_count_total": 171 + }, + "hash": "sha256:f11bfd20cb9a0932ce263b2dd763729320261bb25e1fa0039a45ccc609541391", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit-parachains", + "title": "Parachains", + "slug": "develop-toolkit-parachains", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/", + "preview": "Within the Polkadot ecosystem, you'll find a robust set of development tools that empower developers to build, test, and deploy blockchain applications efficiently. Whether you're designing a custom parachain, testing new features, or validating network configurations, these tools streamline the development process and ensure your blockchain setup is secure and optimized.", + "outline": [ { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-mac-os" + "depth": 2, + "title": "Quick Links", + "anchor": "quick-links" }, { "depth": 2, - "title": "Install Dependencies: Linux", - "anchor": "install-dependencies-linux" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 986, + "words": 136, + "headings": 2, + "estimated_token_count_total": 106 + }, + "hash": "sha256:88dda8aeab06294ccb773d8732d4791b052351ed0b1307d62019a637c9be341a", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop-toolkit", + "title": "Toolkit", + "slug": "develop-toolkit", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit.md", + "html_url": "https://docs.polkadot.com/develop/toolkit/", + "preview": "Explore Polkadot's core development toolkit, designed to support a variety of developers and use cases within the ecosystem. Whether you're building blockchain infrastructure, developing cross-chain applications, or integrating with external services, this section offers essential tools and resources to help you succeed.", + "outline": [ { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-linux }", - "anchor": "before-you-begin-before-you-begin-linux" - }, + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 902, + "words": 113, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:20c667a337791538e3997f1f449bf69b248ccc4cc806e22615075f24fd3f0202", + "token_estimator": "heuristic-v1" + }, + { + "id": "develop", + "title": "Develop", + "slug": "develop", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop.md", + "html_url": "https://docs.polkadot.com/develop/", + "preview": "This guide is a starting point for developers who wish to build in the Polkadot ecosystem. To get the most from this section:", + "outline": [ { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-linux }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-linux" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Install Dependencies: Windows (WSL)", - "anchor": "install-dependencies-windows-wsl" + "title": "Development Pathways", + "anchor": "development-pathways" }, { "depth": 3, - "title": "Before You Begin {: #before-you-begin-windows-wls }", - "anchor": "before-you-begin-before-you-begin-windows-wls" + "title": "Parachain Developers", + "anchor": "parachain-developers" }, { "depth": 3, - "title": "Set Up Windows Subsystem for Linux", - "anchor": "set-up-windows-subsystem-for-linux" + "title": "Smart Contract Developers", + "anchor": "smart-contract-developers" }, { "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-windows-wls" + "title": "Application Developers", + "anchor": "application-developers" }, { "depth": 2, - "title": "Build the Polkadot SDK", - "anchor": "build-the-polkadot-sdk" + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 6923, + "words": 882, + "headings": 6, + "estimated_token_count_total": 1843 + }, + "hash": "sha256:1784f7b9e0552ab893c9d7d252299d53e36b6f57ef57c49cd5e36805399675ab", + "token_estimator": "heuristic-v1" + }, + { + "id": "get-support-ai-ready-docs", + "title": "AI Ready Docs", + "slug": "get-support-ai-ready-docs", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-ai-ready-docs.md", + "html_url": "https://docs.polkadot.com/get-support/ai-ready-docs/", + "preview": "Polkadot provides files to make documentation content available in a structure optimized for use with large language models (LLMs) and AI tools. These resources help build AI assistants, power code search, or enable custom tooling trained on Polkadot’s documentation.", + "outline": [ + { + "depth": 2, + "title": "How to Use These Files", + "anchor": "how-to-use-these-files" }, { - "depth": 3, - "title": "Clone the Polkadot SDK", - "anchor": "clone-the-polkadot-sdk" + "depth": 2, + "title": "Download LLM Files", + "anchor": "download-llm-files" + } + ], + "stats": { + "chars": 7998, + "words": 825, + "headings": 2, + "estimated_token_count_total": 2232 + }, + "hash": "sha256:5a8da69a5cea8bd598ee4d102b9abed5d1a29153802a567e22bb4ee720410b32", + "token_estimator": "heuristic-v1" + }, + { + "id": "get-support-explore-resources", + "title": "Subscribe to Updates", + "slug": "get-support-explore-resources", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md", + "html_url": "https://docs.polkadot.com/get-support/explore-resources/", + "preview": "Looking for answers beyond the documentation? These platforms are full of useful content and experienced developers sharing insights.", + "outline": [ + { + "depth": 2, + "title": "🧠 Stack Exchange", + "anchor": "stack-exchange" }, { - "depth": 3, - "title": "Compile the Polkadot SDK", - "anchor": "compile-the-polkadot-sdk" + "depth": 2, + "title": "🧵 Reddit: r/Polkadot", + "anchor": "reddit-rpolkadot" }, { - "depth": 3, - "title": "Verify the Build", - "anchor": "verify-the-build" + "depth": 2, + "title": "💬 Discord (Community Threads Only)", + "anchor": "discord-community-threads-only" }, { "depth": 2, - "title": "Optional: Run the Kitchensink Node", - "anchor": "optional-run-the-kitchensink-node" + "title": "🎥 YouTube: @PolkadotNetwork", + "anchor": "youtube-polkadotnetwork" + }, + { + "depth": 2, + "title": "Community-Led Platforms and Ecosystem Updates", + "anchor": "community-led-platforms-and-ecosystem-updates" }, { "depth": 3, - "title": "Run the Kitchensink Node in Development Mode", - "anchor": "run-the-kitchensink-node-in-development-mode" + "title": "🔷 X (Twitter): Official Accounts", + "anchor": "x-twitter-official-accounts" }, { "depth": 3, - "title": "Interact with the Kitchensink Node", - "anchor": "interact-with-the-kitchensink-node" + "title": "🔁 X (Twitter): Community Accounts", + "anchor": "x-twitter-community-accounts" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "🗣️ Polkadot Forum", + "anchor": "polkadot-forum" + }, + { + "depth": 3, + "title": "🧑‍⚖️ Polkassembly: OpenGov", + "anchor": "polkassembly-opengov" + }, + { + "depth": 3, + "title": "📸 Instagram", + "anchor": "instagram" } ], "stats": { - "chars": 16051, - "words": 2312, - "headings": 20, - "estimated_token_count_total": 3345 + "chars": 2426, + "words": 295, + "headings": 10, + "estimated_token_count_total": 579 }, - "hash": "sha256:a52c05b623f3780f14be3a5f36b3d79a6c1965c2fbfd6864b512a9a70c47cd60", + "hash": "sha256:4c33d0ec5026128b3bfdb1dfc1f4b29487404eaa8043071d536e8638356c6e1f", "token_estimator": "heuristic-v1" }, { - "id": "parachains-integrations-indexers", - "title": "Indexers", - "slug": "parachains-integrations-indexers", + "id": "get-support-get-in-touch", + "title": "Get in Touch", + "slug": "get-support-get-in-touch", "categories": [ - "Tooling", - "Dapps" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/indexers/", - "preview": "Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-get-in-touch.md", + "html_url": "https://docs.polkadot.com/get-support/get-in-touch/", + "preview": "Use one of the channels below to get live technical support or ask questions.", "outline": [ { "depth": 2, - "title": "The Challenge of Blockchain Data Access", - "anchor": "the-challenge-of-blockchain-data-access" + "title": "Need Help Fast?", + "anchor": "need-help-fast" }, { "depth": 2, - "title": "What is a Blockchain Indexer?", - "anchor": "what-is-a-blockchain-indexer" + "title": "📱 Telegram: Polkadot Developer Support", + "anchor": "telegram-polkadot-developer-support" }, { "depth": 2, - "title": "Indexer Implementations", - "anchor": "indexer-implementations" + "title": "🔌 Discord: Polkadot Official Server", + "anchor": "discord-polkadot-official-server" + }, + { + "depth": 2, + "title": "🧬 Matrix: Polkadot Developer Support", + "anchor": "matrix-polkadot-developer-support" } ], "stats": { - "chars": 2230, - "words": 302, - "headings": 3, - "estimated_token_count_total": 428 + "chars": 1949, + "words": 258, + "headings": 4, + "estimated_token_count_total": 557 }, - "hash": "sha256:cfcc76bb24779c9b613f2c046b6f99a0f2529c25fd82287d804f6b945b936227", + "hash": "sha256:993e93b05c8fbdfc2f7510c61ac86bc4c2ff0f03e573695b2f260933c8b62f78", "token_estimator": "heuristic-v1" }, { - "id": "parachains-integrations-oracles", - "title": "Oracles", - "slug": "parachains-integrations-oracles", + "id": "get-support", + "title": "Support", + "slug": "get-support", "categories": [ - "Tooling", - "Dapps" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/oracles/", - "preview": "Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the \"blockchain oracle problem.\" Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support.md", + "html_url": "https://docs.polkadot.com/get-support/", + "preview": "Use one of the channels below to get live technical support or ask questions.", "outline": [ { "depth": 2, - "title": "What is a Blockchain Oracle?", - "anchor": "what-is-a-blockchain-oracle" + "title": "Need More than Just Documentation?", + "anchor": "need-more-than-just-documentation" }, { "depth": 2, - "title": "Oracle Implementations", - "anchor": "oracle-implementations" + "title": "What You Can Do Here", + "anchor": "what-you-can-do-here" + }, + { + "depth": 2, + "title": "Help Us Improve", + "anchor": "help-us-improve" } ], "stats": { - "chars": 1343, - "words": 181, - "headings": 2, - "estimated_token_count_total": 245 + "chars": 1658, + "words": 244, + "headings": 3, + "estimated_token_count_total": 280 }, - "hash": "sha256:6d8e01281a5895fd2bc4438b24c170c72a496de0b838626a53e87685aea4aa25", + "hash": "sha256:5bdc575ac798a971867a15651c2b4d5139bf0b1fe6854d1865deff280ae6d7f6", "token_estimator": "heuristic-v1" }, { - "id": "parachains-integrations-wallets", - "title": "Wallets", - "slug": "parachains-integrations-wallets", + "id": "index", + "title": "Polkadot Developer Docs", + "slug": "index", "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/wallets/", - "preview": "A wallet serves as your gateway to interacting with blockchain networks. Rather than storing funds, wallets secure your private keys, controlling access to your blockchain assets. Your private key provides complete control over all permitted transactions on your blockchain account, making it essential to keep it secure.", - "outline": [ - { - "depth": 2, - "title": "What is a Blockchain Wallet?", - "anchor": "what-is-a-blockchain-wallet" - }, - { - "depth": 2, - "title": "Hot Wallets", - "anchor": "hot-wallets" - }, - { - "depth": 2, - "title": "Cold Wallets", - "anchor": "cold-wallets" - }, - { - "depth": 2, - "title": "Wallet Tools", - "anchor": "wallet-tools" - } + "Uncategorized" ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/index.md", + "html_url": "https://docs.polkadot.com/index/", + "preview": "Explore everything you need to start building on top of Polkadot, a protocol that provides parachains with shared security and interoperability using XCM.", + "outline": [], "stats": { - "chars": 3588, - "words": 489, - "headings": 4, - "estimated_token_count_total": 786 + "chars": 0, + "words": 0, + "headings": 0, + "estimated_token_count_total": 0 }, - "hash": "sha256:1c65342056983806d639fb8393fdfbdf2ef644ffd41ed749947a16fb3839753d", + "hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "token_estimator": "heuristic-v1" }, { - "id": "parachains-interoperability-channels-between-parachains", - "title": "Opening HRMP Channels Between Parachains", - "slug": "parachains-interoperability-channels-between-parachains", + "id": "nodes-and-validators-run-a-node-bootnode", + "title": "Set Up a Bootnode", + "slug": "nodes-and-validators-run-a-node-bootnode", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/", - "preview": "For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-bootnode.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/bootnode/", + "preview": "Bootnodes are essential for helping blockchain nodes discover peers and join the network. When a node starts, it needs to find other nodes, and bootnodes provide an initial point of contact. Once connected, a node can expand its peer connections and play its role in the network, like participating as a validator.", "outline": [ { "depth": 2, @@ -2934,64 +3680,59 @@ }, { "depth": 2, - "title": "Procedure to Initiate an HRMP Channel", - "anchor": "procedure-to-initiate-an-hrmp-channel" + "title": "Accessing the Bootnode", + "anchor": "accessing-the-bootnode" }, { - "depth": 3, - "title": "Fund Sender Sovereign Account", - "anchor": "fund-sender-sovereign-account" - }, - { - "depth": 3, - "title": "Create Channel Opening Extrinsic", - "anchor": "create-channel-opening-extrinsic" + "depth": 2, + "title": "Node Key", + "anchor": "node-key" }, { - "depth": 3, - "title": "Craft and Submit the XCM Message from the Sender", - "anchor": "craft-and-submit-the-xcm-message-from-the-sender" + "depth": 2, + "title": "Running the Bootnode", + "anchor": "running-the-bootnode" }, { "depth": 2, - "title": "Procedure to Accept an HRMP Channel", - "anchor": "procedure-to-accept-an-hrmp-channel" + "title": "Testing Bootnode Connection", + "anchor": "testing-bootnode-connection" }, { "depth": 3, - "title": "Fund Receiver Sovereign Account", - "anchor": "fund-receiver-sovereign-account" + "title": "P2P", + "anchor": "p2p" }, { "depth": 3, - "title": "Create Channel Accepting Extrinsic", - "anchor": "create-channel-accepting-extrinsic" + "title": "P2P/WS", + "anchor": "p2pws" }, { "depth": 3, - "title": "Craft and Submit the XCM Message from the Receiver", - "anchor": "craft-and-submit-the-xcm-message-from-the-receiver" + "title": "P2P/WSS", + "anchor": "p2pwss" } ], "stats": { - "chars": 10934, - "words": 1549, - "headings": 10, - "estimated_token_count_total": 2285 + "chars": 4538, + "words": 647, + "headings": 9, + "estimated_token_count_total": 1044 }, - "hash": "sha256:b8de1228b9976765accd18ff724038bed6f2449367f500bc3177ab2a053abe63", + "hash": "sha256:d84a5af1a0237a911d25a68c077f508ebbce608f673ef4f9055e8e434daa96b9", "token_estimator": "heuristic-v1" }, { - "id": "parachains-interoperability-channels-with-system-parachains", - "title": "Opening HRMP Channels with System Parachains", - "slug": "parachains-interoperability-channels-with-system-parachains", + "id": "nodes-and-validators-run-a-node-full-node", + "title": "Set Up a Node", + "slug": "nodes-and-validators-run-a-node-full-node", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/", - "preview": "While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-full-node.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/full-node/", + "preview": "Running a node on Polkadot provides direct interaction with the network, enhanced privacy, and full control over RPC requests, transactions, and data queries. As the backbone of the network, nodes ensure decentralized data propagation, transaction validation, and seamless communication across the ecosystem.", "outline": [ { "depth": 2, @@ -3000,50 +3741,64 @@ }, { "depth": 2, + "title": "Set Up a Node", + "anchor": "set-up-a-node" + }, + { + "depth": 3, "title": "Prerequisites", "anchor": "prerequisites" }, { - "depth": 2, - "title": "Procedure to Establish an HRMP Channel", - "anchor": "procedure-to-establish-an-hrmp-channel" + "depth": 3, + "title": "Install and Build the Polkadot Binary", + "anchor": "install-and-build-the-polkadot-binary" }, { "depth": 3, - "title": "Fund Parachain Sovereign Account", - "anchor": "fund-parachain-sovereign-account" + "title": "Use Docker", + "anchor": "use-docker" + }, + { + "depth": 2, + "title": "Configure and Run Your Node", + "anchor": "configure-and-run-your-node" }, { "depth": 3, - "title": "Create Establish Channel with System Extrinsic", - "anchor": "create-establish-channel-with-system-extrinsic" + "title": "RPC Configurations", + "anchor": "rpc-configurations" + }, + { + "depth": 2, + "title": "Sync Your Node", + "anchor": "sync-your-node" }, { "depth": 3, - "title": "Craft and Submit the XCM Message", - "anchor": "craft-and-submit-the-xcm-message" + "title": "Connect to Your Node", + "anchor": "connect-to-your-node" } ], "stats": { - "chars": 7203, - "words": 889, - "headings": 6, - "estimated_token_count_total": 1427 + "chars": 15944, + "words": 2481, + "headings": 9, + "estimated_token_count_total": 4196 }, - "hash": "sha256:b501d99c464fb049d46676827b6a325a195c90617becc4a7db305441c115350a", + "hash": "sha256:b83e3f77bd30ac8c8fb00a193bbec33cd641d94f1a37ac611dea32326c3d77b0", "token_estimator": "heuristic-v1" }, { - "id": "parachains-interoperability-get-started", - "title": "Introduction to XCM", - "slug": "parachains-interoperability-get-started", + "id": "nodes-and-validators-run-a-node-secure-wss", + "title": "Set Up Secure WebSocket", + "slug": "nodes-and-validators-run-a-node-secure-wss", "categories": [ - "Basics", - "Polkadot Protocol" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/get-started/", - "preview": "Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-secure-wss.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/secure-wss/", + "preview": "Ensuring secure WebSocket communication is crucial for maintaining the integrity and security of a Polkadot or Kusama node when interacting with remote clients. This guide walks you through setting up a secure WebSocket (WSS) connection for your node by leveraging SSL encryption with popular web server proxies like nginx or Apache.", "outline": [ { "depth": 2, @@ -3052,54 +3807,54 @@ }, { "depth": 2, - "title": "Messaging Format", - "anchor": "messaging-format" + "title": "Secure a WebSocket Port", + "anchor": "secure-a-websocket-port" }, { - "depth": 2, - "title": "The Four Principles of XCM", - "anchor": "the-four-principles-of-xcm" + "depth": 3, + "title": "Obtain an SSL Certificate", + "anchor": "obtain-an-ssl-certificate" }, { "depth": 2, - "title": "The XCM Tech Stack", - "anchor": "the-xcm-tech-stack" + "title": "Install a Proxy Server", + "anchor": "install-a-proxy-server" }, { - "depth": 2, - "title": "Core Functionalities of XCM", - "anchor": "core-functionalities-of-xcm" + "depth": 3, + "title": "Use nginx", + "anchor": "use-nginx" }, { - "depth": 2, - "title": "XCM Example", - "anchor": "xcm-example" + "depth": 3, + "title": "Use Apache2", + "anchor": "use-apache2" }, { "depth": 2, - "title": "Overview", - "anchor": "overview" + "title": "Connect to the Node", + "anchor": "connect-to-the-node" } ], "stats": { - "chars": 7450, - "words": 974, + "chars": 5568, + "words": 774, "headings": 7, - "estimated_token_count_total": 1501 + "estimated_token_count_total": 1280 }, - "hash": "sha256:3b26606dd5310c4b8ade5d05270ebf1e06f59afcda4ca2b985e07948215a197e", + "hash": "sha256:992082e4ad87348b283f6c37ea886ae0e7bf016852b6470000876f3d169c65a4", "token_estimator": "heuristic-v1" }, { - "id": "parachains-launch-a-parachain-deploy-to-polkadot", - "title": "Deploy on Polkadot", - "slug": "parachains-launch-a-parachain-deploy-to-polkadot", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", + "title": "Validator Key Management", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-deploy-to-polkadot.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/deploy-to-polkadot/", - "preview": "Previously, you learned how to [choose and set up a parachain template](/parachains/launch-a-parachain/choose-a-template/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to the Polkadot TestNet. Deploying to a TestNet is a crucial step for validating your parachain's functionality and preparing it for eventual MainNet deployment.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/", + "preview": "After setting up your node environment as shown in the [Setup](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/){target=\\_blank} section, you'll need to configure multiple keys for your validator to operate properly. This includes setting up session keys, which are essential for participating in the consensus process, and configuring a node key that maintains a stable network identity. This guide walks you through the key management process, showing you how to g", "outline": [ { "depth": 2, @@ -3108,64 +3863,59 @@ }, { "depth": 2, - "title": "Get Started with an Account and Tokens", - "anchor": "get-started-with-an-account-and-tokens" - }, - { - "depth": 2, - "title": "Reserve a Parachain Identifier", - "anchor": "reserve-a-parachain-identifier" + "title": "Set Session Keys", + "anchor": "set-session-keys" }, { - "depth": 2, - "title": "Generate Custom Keys for Your Collators", - "anchor": "generate-custom-keys-for-your-collators" + "depth": 3, + "title": "Generate Session Keys", + "anchor": "generate-session-keys" }, { - "depth": 2, - "title": "Generate the Chain Specification", - "anchor": "generate-the-chain-specification" + "depth": 3, + "title": "Submit Transaction to Set Keys", + "anchor": "submit-transaction-to-set-keys" }, { - "depth": 2, - "title": "Export Required Files", - "anchor": "export-required-files" + "depth": 3, + "title": "Verify Session Key Setup", + "anchor": "verify-session-key-setup" }, { "depth": 2, - "title": "Register a Parathread", - "anchor": "register-a-parathread" + "title": "Set the Node Key", + "anchor": "set-the-node-key" }, { - "depth": 2, - "title": "Start the Collator Node", - "anchor": "start-the-collator-node" + "depth": 3, + "title": "Generate the Node Key", + "anchor": "generate-the-node-key" }, { - "depth": 2, - "title": "Producing Blocks", - "anchor": "producing-blocks" + "depth": 3, + "title": "Set Node Key", + "anchor": "set-node-key" } ], "stats": { - "chars": 20252, - "words": 2357, - "headings": 9, - "estimated_token_count_total": 4129 + "chars": 8227, + "words": 1183, + "headings": 8, + "estimated_token_count_total": 1840 }, - "hash": "sha256:7309d3487c653951bf264013eb3402a72a1cbb5e0b6f89ae4e678f239cd63b80", + "hash": "sha256:0fb5a83835aab263c0b9aa886028c8aa8a2d6d0897d7b9fff4b5258835d30dfe", "token_estimator": "heuristic-v1" }, { - "id": "parachains-launch-a-parachain-obtain-coretime", - "title": "Obtain Coretime", - "slug": "parachains-launch-a-parachain-obtain-coretime", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", + "title": "Set Up a Validator", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/", - "preview": "After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/", + "preview": "Setting up a Polkadot validator node is essential for securing the network and earning staking rewards. This guide walks you through the technical steps to set up a validator, from installing the necessary software to managing keys and synchronizing your node with the chain.", "outline": [ { "depth": 2, @@ -3179,75 +3929,74 @@ }, { "depth": 2, - "title": "Order On-Demand Coretime", - "anchor": "order-on-demand-coretime" + "title": "Initial Setup", + "anchor": "initial-setup" }, { "depth": 3, - "title": "On-Demand Extrinsics", - "anchor": "on-demand-extrinsics" + "title": "Install Network Time Protocol Client", + "anchor": "install-network-time-protocol-client" }, { "depth": 3, - "title": "Place an On-Demand Order", - "anchor": "place-an-on-demand-order" + "title": "Verify Landlock is Activated", + "anchor": "verify-landlock-is-activated" }, { "depth": 2, - "title": "Purchase Bulk Coretime", - "anchor": "purchase-bulk-coretime" + "title": "Install the Polkadot Binaries", + "anchor": "install-the-polkadot-binaries" }, { "depth": 3, - "title": "Connect Your Wallet to RegionX", - "anchor": "connect-your-wallet-to-regionx" + "title": "Install from Official Releases", + "anchor": "install-from-official-releases" }, { "depth": 3, - "title": "Obtain Coretime Chain Funds", - "anchor": "obtain-coretime-chain-funds" + "title": "Install with Package Managers", + "anchor": "install-with-package-managers" }, { "depth": 3, - "title": "Purchase a Core", - "anchor": "purchase-a-core" + "title": "Install with Ansible", + "anchor": "install-with-ansible" }, { "depth": 3, - "title": "Verify Your Purchase", - "anchor": "verify-your-purchase" + "title": "Install with Docker", + "anchor": "install-with-docker" }, { "depth": 3, - "title": "Assign Your Parachain to the Core", - "anchor": "assign-your-parachain-to-the-core" + "title": "Build from Sources", + "anchor": "build-from-sources" }, { "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" + "title": "Verify Installation", + "anchor": "verify-installation" } ], "stats": { - "chars": 9049, - "words": 1345, + "chars": 11921, + "words": 1678, "headings": 12, - "estimated_token_count_total": 2103 + "estimated_token_count_total": 2592 }, - "hash": "sha256:15154f211753665d9af70dc81d15ceb3f0954e3febf9282c68c0074881d620c6", + "hash": "sha256:d2c1c91734bc8185057d8eeec6829ea91e0316f7ba884c5dc3922a5e5778815e", "token_estimator": "heuristic-v1" }, { - "id": "parachains-launch-a-parachain-set-up-the-parachain-template", - "title": "Set Up the Polkadot SDK Parachain Template", - "slug": "parachains-launch-a-parachain-set-up-the-parachain-template", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", + "title": "Start Validating", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", "categories": [ - "Basics", - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/", - "preview": "The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/start-validating/", + "preview": "After configuring your node keys as shown in the [Key Management](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/){target=\\_blank} section and ensuring your system is set up, you're ready to begin the validator setup process. This guide will walk you through choosing a network, synchronizing your node with the blockchain, bonding your DOT tokens, and starting your validator.", "outline": [ { "depth": 2, @@ -3256,74 +4005,84 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Choose a Network", + "anchor": "choose-a-network" }, { "depth": 2, - "title": "Polkadot SDK Utility Tools", - "anchor": "polkadot-sdk-utility-tools" + "title": "Synchronize Chain Data", + "anchor": "synchronize-chain-data" }, { - "depth": 2, - "title": "Clone the Template", - "anchor": "clone-the-template" + "depth": 3, + "title": "Database Snapshot Services", + "anchor": "database-snapshot-services" }, { "depth": 2, - "title": "Explore the Project Structure", - "anchor": "explore-the-project-structure" + "title": "Bond DOT", + "anchor": "bond-dot" }, { - "depth": 2, - "title": "Compile the Runtime", - "anchor": "compile-the-runtime" + "depth": 3, + "title": "Bonding DOT on Polkadot.js Apps", + "anchor": "bonding-dot-on-polkadotjs-apps" }, { "depth": 2, - "title": "Verify the Build", - "anchor": "verify-the-build" + "title": "Validate", + "anchor": "validate" }, { - "depth": 2, - "title": "Run the Node Locally", - "anchor": "run-the-node-locally" + "depth": 3, + "title": "Verify Sync via Telemetry", + "anchor": "verify-sync-via-telemetry" }, { - "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" + "depth": 3, + "title": "Activate using Polkadot.js Apps", + "anchor": "activate-using-polkadotjs-apps" }, { - "depth": 2, - "title": "Stop the Node", - "anchor": "stop-the-node" + "depth": 3, + "title": "Monitor Validation Status and Slots", + "anchor": "monitor-validation-status-and-slots" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Run a Validator Using Systemd", + "anchor": "run-a-validator-using-systemd" + }, + { + "depth": 3, + "title": "Create the Systemd Service File", + "anchor": "create-the-systemd-service-file" + }, + { + "depth": 3, + "title": "Run the Service", + "anchor": "run-the-service" } ], "stats": { - "chars": 10588, - "words": 1510, - "headings": 11, - "estimated_token_count_total": 2375 + "chars": 15820, + "words": 2446, + "headings": 13, + "estimated_token_count_total": 3861 }, - "hash": "sha256:380063fe7c00ae8bde05fa76688b8ae4902e6566147f1cfe0e0260ad1aa05aa6", + "hash": "sha256:c74cfa542fe7a5235b81120f0004576aea83e0d35458201689b68d87f2969749", "token_estimator": "heuristic-v1" }, { - "id": "parachains-runtime-maintenance-runtime-upgrades", - "title": "Runtime Upgrades", - "slug": "parachains-runtime-maintenance-runtime-upgrades", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", + "title": "Stop Validating", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/", - "preview": "One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/", + "preview": "If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability.", "outline": [ { "depth": 2, @@ -3332,44 +4091,44 @@ }, { "depth": 2, - "title": "How Runtime Upgrades Work", - "anchor": "how-runtime-upgrades-work" + "title": "Pause Versus Stop", + "anchor": "pause-versus-stop" }, { - "depth": 3, - "title": "Runtime Versioning", - "anchor": "runtime-versioning" + "depth": 2, + "title": "Chill Validator", + "anchor": "chill-validator" }, { - "depth": 3, - "title": "Accessing the Runtime Version", - "anchor": "accessing-the-runtime-version" + "depth": 2, + "title": "Purge Validator Session Keys", + "anchor": "purge-validator-session-keys" }, { "depth": 2, - "title": "Storage Migrations", - "anchor": "storage-migrations" + "title": "Unbond Your Tokens", + "anchor": "unbond-your-tokens" } ], "stats": { - "chars": 5837, - "words": 811, + "chars": 3230, + "words": 500, "headings": 5, - "estimated_token_count_total": 1161 + "estimated_token_count_total": 629 }, - "hash": "sha256:ec31270001a6cd9d0a8ecb7974ad161d5c1ef4d3023d5a6af9fbc5a6ca46cbca", + "hash": "sha256:0d6db361bfa7a3022849bbe39989bfdac0429537498d7f534adadec131afca98", "token_estimator": "heuristic-v1" }, { - "id": "parachains-runtime-maintenance-storage-migrations", - "title": "Storage Migrations", - "slug": "parachains-runtime-maintenance-storage-migrations", + "id": "nodes-and-validators-run-a-validator-operational-tasks-general-management", + "title": "General Management", + "slug": "nodes-and-validators-run-a-validator-operational-tasks-general-management", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/", - "preview": "Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-general-management.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/general-management/", + "preview": "Validator performance is pivotal in maintaining the security and stability of the Polkadot network. As a validator, optimizing your setup ensures efficient transaction processing, minimizes latency, and maintains system reliability during high-demand periods. Proper configuration and proactive monitoring also help mitigate risks like slashing and service interruptions.", "outline": [ { "depth": 2, @@ -3378,121 +4137,109 @@ }, { "depth": 2, - "title": "Storage Migration Scenarios", - "anchor": "storage-migration-scenarios" + "title": "Configuration Optimization", + "anchor": "configuration-optimization" }, { - "depth": 2, - "title": "Implement Storage Migrations", - "anchor": "implement-storage-migrations" + "depth": 3, + "title": "Deactivate Simultaneous Multithreading", + "anchor": "deactivate-simultaneous-multithreading" }, { "depth": 3, - "title": "Core Migration Function", - "anchor": "core-migration-function" + "title": "Deactivate Automatic NUMA Balancing", + "anchor": "deactivate-automatic-numa-balancing" }, { "depth": 3, - "title": "Migration Testing Hooks", - "anchor": "migration-testing-hooks" + "title": "Spectre and Meltdown Mitigations", + "anchor": "spectre-and-meltdown-mitigations" + }, + { + "depth": 2, + "title": "Monitor Your Node", + "anchor": "monitor-your-node" }, { "depth": 3, - "title": "Migration Structure", - "anchor": "migration-structure" + "title": "Environment Setup", + "anchor": "environment-setup" }, { "depth": 3, - "title": "Migration Organization", - "anchor": "migration-organization" + "title": "Install and Configure Prometheus", + "anchor": "install-and-configure-prometheus" }, { "depth": 3, - "title": "Scheduling Migrations", - "anchor": "scheduling-migrations" + "title": "Start Prometheus", + "anchor": "start-prometheus" }, { - "depth": 2, - "title": "Single-Block Migrations", - "anchor": "single-block-migrations" + "depth": 3, + "title": "Install and Configure Grafana", + "anchor": "install-and-configure-grafana" }, { - "depth": 2, - "title": "Multi Block Migrations", - "anchor": "multi-block-migrations" - } - ], - "stats": { - "chars": 18500, - "words": 2363, - "headings": 10, - "estimated_token_count_total": 4014 - }, - "hash": "sha256:55dc252fdecf1590048ce8d009b822e90231442abe81e9593cf1635944a31336", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-runtime-maintenance-unlock-parachains", - "title": "Unlock a Parachain", - "slug": "parachains-runtime-maintenance-unlock-parachains", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-unlock-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/unlock-parachains/", - "preview": "Parachain locks are a critical security mechanism in the Polkadot ecosystem designed to maintain decentralization during the parachain lifecycle. These locks prevent potential centralization risks that could emerge during the early stages of parachain operation.", - "outline": [ + "depth": 3, + "title": "Install and Configure Alertmanager", + "anchor": "install-and-configure-alertmanager" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Secure Your Validator", + "anchor": "secure-your-validator" }, { - "depth": 2, - "title": "Check If the Parachain Is Locked", - "anchor": "check-if-the-parachain-is-locked" + "depth": 3, + "title": "Key Management", + "anchor": "key-management" }, { - "depth": 2, - "title": "How to Unlock a Parachain", - "anchor": "how-to-unlock-a-parachain" + "depth": 3, + "title": "Signing Outside the Client", + "anchor": "signing-outside-the-client" }, { "depth": 3, - "title": "Prepare the Unlock Call", - "anchor": "prepare-the-unlock-call" + "title": "Secure-Validator Mode", + "anchor": "secure-validator-mode" }, { "depth": 3, - "title": "Fund the Sovereign Account", - "anchor": "fund-the-sovereign-account" + "title": "Linux Best Practices", + "anchor": "linux-best-practices" }, { "depth": 3, - "title": "Craft and Submit the XCM", - "anchor": "craft-and-submit-the-xcm" - } + "title": "Validator Best Practices", + "anchor": "validator-best-practices" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } ], "stats": { - "chars": 9232, - "words": 1276, - "headings": 6, - "estimated_token_count_total": 2028 + "chars": 26673, + "words": 3357, + "headings": 18, + "estimated_token_count_total": 5866 }, - "hash": "sha256:e408d05199cc184fc6fe8bb212efb3c9aa6cb79258977e07566692176c912def", + "hash": "sha256:81eb0fe77f05155f1ec0511cd066120fc9994961e9d91e21b6666377e65b4586", "token_estimator": "heuristic-v1" }, { - "id": "parachains-testing-fork-a-parachain", - "title": "Get Started", - "slug": "parachains-testing-fork-a-parachain", + "id": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", + "title": "Pause Validating", + "slug": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", "categories": [ - "Parachains", - "Tooling" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md", - "html_url": "https://docs.polkadot.com/parachains/testing/fork-a-parachain/", - "preview": "[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-pause-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/", + "preview": "If you need to temporarily stop participating in Polkadot staking activities without fully unbonding your funds, chilling your account allows you to do so efficiently. Chilling removes your node from active validation or nomination in the next era while keeping your funds bonded, making it ideal for planned downtimes or temporary pauses.", "outline": [ { "depth": 2, @@ -3501,70 +4248,49 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Chilling Your Node", + "anchor": "chilling-your-node" }, { "depth": 2, - "title": "Install Chopsticks", - "anchor": "install-chopsticks" - }, - { - "depth": 3, - "title": "Global Installation", - "anchor": "global-installation" - }, - { - "depth": 3, - "title": "Local Installation", - "anchor": "local-installation" + "title": "Staking Election Timing Considerations", + "anchor": "staking-election-timing-considerations" }, { "depth": 2, - "title": "Configure Chopsticks", - "anchor": "configure-chopsticks" - }, - { - "depth": 3, - "title": "Configuration File", - "anchor": "configuration-file" - }, - { - "depth": 3, - "title": "CLI Flags", - "anchor": "cli-flags" + "title": "Chilling as a Nominator", + "anchor": "chilling-as-a-nominator" }, { "depth": 2, - "title": "WebSocket Commands", - "anchor": "websocket-commands" + "title": "Chilling as a Validator", + "anchor": "chilling-as-a-validator" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Chill Other", + "anchor": "chill-other" } ], "stats": { - "chars": 10894, - "words": 1330, - "headings": 10, - "estimated_token_count_total": 2614 + "chars": 4439, + "words": 679, + "headings": 6, + "estimated_token_count_total": 861 }, - "hash": "sha256:4325cdd697814b8043db808da3dee86d3d9c6fc7dd523aae7fe8914d59d1b39c", + "hash": "sha256:1af153570ce57bd5b52d08493a300996765686f2a6d04519a2e0aa91191612c1", "token_estimator": "heuristic-v1" }, { - "id": "parachains-testing-run-a-parachain-network", - "title": "Get Started", - "slug": "parachains-testing-run-a-parachain-network", + "id": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", + "title": "Upgrade a Validator Node", + "slug": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", "categories": [ - "Parachains", - "Tooling" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md", - "html_url": "https://docs.polkadot.com/parachains/testing/run-a-parachain-network/", - "preview": "Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/upgrade-your-node/", + "preview": "Upgrading a Polkadot validator node is essential for staying current with network updates and maintaining optimal performance. This guide covers routine and extended maintenance scenarios, including software upgrades and major server changes. Following these steps, you can manage session keys and transition smoothly between servers without risking downtime, slashing, or network disruptions. The process requires strategic planning, especially if you need to perform long-lead maintenance, ensuring", "outline": [ { "depth": 2, @@ -3573,425 +4299,536 @@ }, { "depth": 2, - "title": "Install Zombienet", - "anchor": "install-zombienet" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Providers", - "anchor": "providers" - }, - { - "depth": 3, - "title": "Kubernetes", - "anchor": "kubernetes" - }, - { - "depth": 3, - "title": "Podman", - "anchor": "podman" + "title": "Session Keys", + "anchor": "session-keys" }, { - "depth": 3, - "title": "Local Provider", - "anchor": "local-provider" + "depth": 2, + "title": "Keystore", + "anchor": "keystore" }, { "depth": 2, - "title": "Configure Zombienet", - "anchor": "configure-zombienet" + "title": "Upgrade Using Backup Validator", + "anchor": "upgrade-using-backup-validator" }, { "depth": 3, - "title": "Configuration Files", - "anchor": "configuration-files" + "title": "Session `N`", + "anchor": "session-n" }, { "depth": 3, - "title": "CLI Usage", - "anchor": "cli-usage" - }, + "title": "Session `N+3`", + "anchor": "session-n3" + } + ], + "stats": { + "chars": 5650, + "words": 851, + "headings": 7, + "estimated_token_count_total": 1185 + }, + "hash": "sha256:888230b128d8c648c4f06a18d3b1d1b06dd1bf22a0de4add1f28210ffccb2549", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-validator-requirements", + "title": "Validator Requirements", + "slug": "nodes-and-validators-run-a-validator-requirements", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-requirements.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/requirements/", + "preview": "Running a validator in the Polkadot ecosystem is essential for maintaining network security and decentralization. Validators are responsible for validating transactions and adding new blocks to the chain, ensuring the system operates smoothly. In return for their services, validators earn rewards. However, the role comes with inherent risks, such as slashing penalties for misbehavior or technical failures. If you’re new to validation, starting on Kusama provides a lower-stakes environment to gai", + "outline": [ { - "depth": 3, - "title": "Settings", - "anchor": "settings" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Relay Chain Configuration", - "anchor": "relay-chain-configuration" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Parachain Configuration", - "anchor": "parachain-configuration" + "depth": 2, + "title": "Minimum Hardware Requirements", + "anchor": "minimum-hardware-requirements" }, { - "depth": 3, - "title": "XCM Configuration", - "anchor": "xcm-configuration" + "depth": 2, + "title": "VPS Provider List", + "anchor": "vps-provider-list" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Minimum Bond Requirement", + "anchor": "minimum-bond-requirement" } ], "stats": { - "chars": 41636, - "words": 4599, - "headings": 14, - "estimated_token_count_total": 9871 + "chars": 6842, + "words": 944, + "headings": 5, + "estimated_token_count_total": 1485 }, - "hash": "sha256:0d7e04fd952cc9d5bd8cdbfd87cc4004c5f95e896a16bc7f89dfc4caeac8f371", + "hash": "sha256:46435b97c37ef6798d2c75c69df31c5e5f07e04b218c370ec5af6b1838d43aac", "token_estimator": "heuristic-v1" }, { - "id": "reference-glossary", - "title": "Glossary", - "slug": "reference-glossary", + "id": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", + "title": "Offenses and Slashes", + "slug": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", "categories": [ - "Reference" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md", - "html_url": "https://docs.polkadot.com/reference/glossary/", - "preview": "Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/offenses-and-slashes/", + "preview": "In Polkadot's Nominated Proof of Stake (NPoS) system, validator misconduct is deterred through a combination of slashing, disabling, and reputation penalties. Validators and nominators who stake tokens face consequences for validator misbehavior, which range from token slashes to restrictions on network participation.", "outline": [ { "depth": 2, - "title": "Authority", - "anchor": "authority" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Authority Round (Aura)", - "anchor": "authority-round-aura" + "title": "Offenses", + "anchor": "offenses" }, { - "depth": 2, - "title": "Blind Assignment of Blockchain Extension (BABE)", - "anchor": "blind-assignment-of-blockchain-extension-babe" + "depth": 3, + "title": "Invalid Votes", + "anchor": "invalid-votes" }, { - "depth": 2, - "title": "Block Author", - "anchor": "block-author" + "depth": 3, + "title": "Equivocations", + "anchor": "equivocations" }, { "depth": 2, - "title": "Byzantine Fault Tolerance (BFT)", - "anchor": "byzantine-fault-tolerance-bft" + "title": "Penalties", + "anchor": "penalties" }, { "depth": 3, - "title": "Byzantine Failure", - "anchor": "byzantine-failure" + "title": "Slashing", + "anchor": "slashing" }, { "depth": 3, - "title": "Practical Byzantine Fault Tolerance (pBFT)", - "anchor": "practical-byzantine-fault-tolerance-pbft" + "title": "Disabling", + "anchor": "disabling" }, { "depth": 3, - "title": "Preimage", - "anchor": "preimage" - }, - { - "depth": 2, - "title": "Call", - "anchor": "call" - }, - { - "depth": 2, - "title": "Chain Specification", - "anchor": "chain-specification" + "title": "Reputation Changes", + "anchor": "reputation-changes" }, { - "depth": 2, - "title": "Collator", - "anchor": "collator" - }, + "depth": 3, + "title": "Penalties by Offense", + "anchor": "penalties-by-offense" + } + ], + "stats": { + "chars": 15427, + "words": 2103, + "headings": 9, + "estimated_token_count_total": 3409 + }, + "hash": "sha256:abe6bedab04f463ec07f554977b8d6355a5d2fad9bcda01cbe58568152295daa", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", + "title": "Rewards Payout", + "slug": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-rewards.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/rewards/", + "preview": "Understanding how rewards are distributed to validators and nominators is essential for network participants. In Polkadot and Kusama, validators earn rewards based on their era points, which are accrued through actions like block production and parachain validation.", + "outline": [ { "depth": 2, - "title": "Collective", - "anchor": "collective" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Consensus", - "anchor": "consensus" + "title": "Era Points", + "anchor": "era-points" }, { "depth": 2, - "title": "Consensus Algorithm", - "anchor": "consensus-algorithm" + "title": "Reward Variance", + "anchor": "reward-variance" }, { "depth": 2, - "title": "Consensus Engine", - "anchor": "consensus-engine" + "title": "Payout Scheme", + "anchor": "payout-scheme" }, { "depth": 2, - "title": "Coretime", - "anchor": "coretime" + "title": "Running Multiple Validators", + "anchor": "running-multiple-validators" }, { "depth": 2, - "title": "Development Phrase", - "anchor": "development-phrase" - }, + "title": "Nominators and Validator Payments", + "anchor": "nominators-and-validator-payments" + } + ], + "stats": { + "chars": 10976, + "words": 1753, + "headings": 6, + "estimated_token_count_total": 2588 + }, + "hash": "sha256:d5d6d72eb2cf10f624d84c65f2274f7df90acb5d071bf170bc8eae8d98a810a5", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-customize-runtime-add-existing-pallets", + "title": "Add an Existing Pallet to the Runtime", + "slug": "parachains-customize-runtime-add-existing-pallets", + "categories": [ + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-existing-pallets.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-existing-pallets/", + "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a functional runtime that includes default [FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} development modules ([pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}) to help you get started building a custo", + "outline": [ { "depth": 2, - "title": "Digest", - "anchor": "digest" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Dispatchable", - "anchor": "dispatchable" + "title": "Check Prerequisites", + "anchor": "check-prerequisites" }, { "depth": 2, - "title": "Events", - "anchor": "events" + "title": "Add an Existing Polkadot SDK Pallet to Your Runtime", + "anchor": "add-an-existing-polkadot-sdk-pallet-to-your-runtime" }, { - "depth": 2, - "title": "Executor", - "anchor": "executor" + "depth": 3, + "title": "Add an Existing Pallet as a Dependency", + "anchor": "add-an-existing-pallet-as-a-dependency" }, { - "depth": 2, - "title": "Existential Deposit", - "anchor": "existential-deposit" + "depth": 3, + "title": "Enable Standard Library Features", + "anchor": "enable-standard-library-features" }, { - "depth": 2, - "title": "Extrinsic", - "anchor": "extrinsic" + "depth": 3, + "title": "Review the Config Trait", + "anchor": "review-the-config-trait" }, { - "depth": 2, - "title": "Fork Choice Rule/Strategy", - "anchor": "fork-choice-rulestrategy" + "depth": 3, + "title": "Implement the Config Trait", + "anchor": "implement-the-config-trait" }, { - "depth": 2, - "title": "FRAME (Framework for Runtime Aggregation of Modularized Entities)", - "anchor": "frame-framework-for-runtime-aggregation-of-modularized-entities" + "depth": 3, + "title": "Add to Runtime Construct", + "anchor": "add-to-runtime-construct" }, { - "depth": 2, - "title": "Full Node", - "anchor": "full-node" + "depth": 3, + "title": "Verify the Runtime Compiles", + "anchor": "verify-the-runtime-compiles" }, { "depth": 2, - "title": "Genesis Configuration", - "anchor": "genesis-configuration" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { - "depth": 2, - "title": "GRANDPA", - "anchor": "grandpa" + "depth": 3, + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" }, { - "depth": 2, - "title": "Header", - "anchor": "header" + "depth": 3, + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" }, { - "depth": 2, - "title": "Hybrid Consensus", - "anchor": "hybrid-consensus" + "depth": 3, + "title": "Interact with the Pallet", + "anchor": "interact-with-the-pallet" }, { "depth": 2, - "title": "Inherent Transactions", - "anchor": "inherent-transactions" - }, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 11924, + "words": 1585, + "headings": 14, + "estimated_token_count_total": 2724 + }, + "hash": "sha256:93d123cbaaccc2515b4a70be8e1327b4f75b1051d16c5e3daf5a2035af7b7ca3", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-customize-runtime-add-pallet-instances", + "title": "Add Multiple Pallet Instances", + "slug": "parachains-customize-runtime-add-pallet-instances", + "categories": [ + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-pallet-instances.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-pallet-instances/", + "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a solid foundation for building custom parachains. While most pallets are typically included as single instances within a runtime, some scenarios benefit from running multiple instances of the same pallet with different configurations. This approach lets you reuse pallet logic without reimplementing it, enabling diverse functionality from a single codebase.", + "outline": [ { "depth": 2, - "title": "JSON-RPC", - "anchor": "json-rpc" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Keystore", - "anchor": "keystore" + "title": "Check Prerequisites", + "anchor": "check-prerequisites" }, { "depth": 2, - "title": "Kusama", - "anchor": "kusama" + "title": "Understanding Instantiable Pallets", + "anchor": "understanding-instantiable-pallets" }, { - "depth": 2, - "title": "libp2p", - "anchor": "libp2p" + "depth": 3, + "title": "Identifying an Instantiable Pallet", + "anchor": "identifying-an-instantiable-pallet" }, { - "depth": 2, - "title": "Light Client", - "anchor": "light-client" + "depth": 3, + "title": "How Instance Generics Work", + "anchor": "how-instance-generics-work" }, { "depth": 2, - "title": "Metadata", - "anchor": "metadata" + "title": "Add Multiple Instances of a Pallet to Your Runtime", + "anchor": "add-multiple-instances-of-a-pallet-to-your-runtime" }, { - "depth": 2, - "title": "Nominated Proof of Stake (NPoS)", - "anchor": "nominated-proof-of-stake-npos" + "depth": 3, + "title": "Add the Pallet as a Dependency", + "anchor": "add-the-pallet-as-a-dependency" }, { - "depth": 2, - "title": "Oracle", - "anchor": "oracle" + "depth": 3, + "title": "Enable Standard Library Features", + "anchor": "enable-standard-library-features" }, { - "depth": 2, - "title": "Origin", - "anchor": "origin" + "depth": 3, + "title": "Review the Config Trait", + "anchor": "review-the-config-trait" }, { - "depth": 2, - "title": "Pallet", - "anchor": "pallet" + "depth": 3, + "title": "Define Pallet Parameters", + "anchor": "define-pallet-parameters" }, { - "depth": 2, - "title": "Parachain", - "anchor": "parachain" + "depth": 3, + "title": "Create Instance Type Definitions", + "anchor": "create-instance-type-definitions" }, { - "depth": 2, - "title": "Paseo", - "anchor": "paseo" + "depth": 3, + "title": "Implement Config Trait for First Instance", + "anchor": "implement-config-trait-for-first-instance" }, { - "depth": 2, - "title": "Polkadot", - "anchor": "polkadot" + "depth": 3, + "title": "Implement Config Trait for Second Instance", + "anchor": "implement-config-trait-for-second-instance" }, { - "depth": 2, - "title": "Polkadot Cloud", - "anchor": "polkadot-cloud" + "depth": 3, + "title": "Add Instances to Runtime Construct", + "anchor": "add-instances-to-runtime-construct" }, { - "depth": 2, - "title": "Polkadot Hub", - "anchor": "polkadot-hub" + "depth": 3, + "title": "Verify the Runtime Compiles", + "anchor": "verify-the-runtime-compiles" }, { "depth": 2, - "title": "PolkaVM", - "anchor": "polkavm" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { - "depth": 2, - "title": "Relay Chain", - "anchor": "relay-chain" + "depth": 3, + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" }, { - "depth": 2, - "title": "Rococo", - "anchor": "rococo" + "depth": 3, + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" }, { - "depth": 2, - "title": "Runtime", - "anchor": "runtime" + "depth": 3, + "title": "Interact with Both Pallet Instances", + "anchor": "interact-with-both-pallet-instances" }, { - "depth": 2, - "title": "Slot", - "anchor": "slot" + "depth": 3, + "title": "Test Instance Independence", + "anchor": "test-instance-independence" }, { "depth": 2, - "title": "Sovereign Account", - "anchor": "sovereign-account" - }, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 17923, + "words": 2203, + "headings": 21, + "estimated_token_count_total": 3811 + }, + "hash": "sha256:d83e574726c524fa017236eb5e3b8a0676d598be4da1ce4fe25a60141baeee49", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-customize-runtime-add-smart-contract-functionality", + "title": "Add Smart Contract Functionality", + "slug": "parachains-customize-runtime-add-smart-contract-functionality", + "categories": [ + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-smart-contract-functionality/", + "preview": "When building your custom blockchain with the Polkadot SDK, you can add smart contract capabilities through specialized pallets. These pallets enable users to deploy and execute smart contracts, enhancing your chain's programmability and allowing developers to build decentralized applications on your network.", + "outline": [ { "depth": 2, - "title": "SS58 Address Format", - "anchor": "ss58-address-format" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "State Transition Function (STF)", - "anchor": "state-transition-function-stf" + "title": "pallet-revive", + "anchor": "pallet-revive" }, { - "depth": 2, - "title": "Storage Item", - "anchor": "storage-item" + "depth": 3, + "title": "Core Components", + "anchor": "core-components" }, { - "depth": 2, - "title": "Substrate", - "anchor": "substrate" + "depth": 3, + "title": "Supported Languages and Compilers", + "anchor": "supported-languages-and-compilers" }, { - "depth": 2, - "title": "Transaction", - "anchor": "transaction" + "depth": 3, + "title": "How It Works", + "anchor": "how-it-works" }, { - "depth": 2, - "title": "Transaction Era", - "anchor": "transaction-era" + "depth": 3, + "title": "Key Benefits", + "anchor": "key-benefits" }, { - "depth": 2, - "title": "Trie (Patricia Merkle Tree)", - "anchor": "trie-patricia-merkle-tree" + "depth": 3, + "title": "Implementation Examples", + "anchor": "implementation-examples" }, { "depth": 2, - "title": "Validator", - "anchor": "validator" + "title": "Frontier", + "anchor": "frontier" }, { - "depth": 2, - "title": "WebAssembly (Wasm)", - "anchor": "webassembly-wasm" + "depth": 3, + "title": "Integration Options", + "anchor": "integration-options" + }, + { + "depth": 3, + "title": "EVM Execution Only", + "anchor": "evm-execution-only" + }, + { + "depth": 3, + "title": "Full Ethereum Compatibility", + "anchor": "full-ethereum-compatibility" + }, + { + "depth": 3, + "title": "Key Benefits", + "anchor": "key-benefits-2" + }, + { + "depth": 3, + "title": "Implementation Examples", + "anchor": "implementation-examples-2" }, { "depth": 2, - "title": "Weight", - "anchor": "weight" + "title": "pallet-contracts (Legacy)", + "anchor": "pallet-contracts-legacy" + }, + { + "depth": 3, + "title": "Implementation Example", + "anchor": "implementation-example" }, { "depth": 2, - "title": "Westend", - "anchor": "westend" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 24739, - "words": 3626, - "headings": 63, - "estimated_token_count_total": 5273 + "chars": 6655, + "words": 833, + "headings": 16, + "estimated_token_count_total": 1631 }, - "hash": "sha256:40bd67811e7eabc79ca5d105eae388b19380d9f035022da17fc0d6bb173c817c", + "hash": "sha256:6297bb5e0809fdd0585d6170054599f7ab4a3ce7c687ad03ae43092057c493b7", "token_estimator": "heuristic-v1" }, { - "id": "reference-governance-origins-tracks", - "title": "Origins and Tracks", - "slug": "reference-governance-origins-tracks", + "id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", + "title": "Add Pallets to the Runtime", + "slug": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "categories": [ - "Polkadot Protocol" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance-origins-tracks.md", - "html_url": "https://docs.polkadot.com/reference/governance/origins-tracks/", - "preview": "Polkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-add-pallet-to-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/", + "preview": "In previous tutorials, you learned how to [create a custom pallet](/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/){target=\\_blank} and [test it](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/){target=\\_blank}. The next step is to include this pallet in your runtime, integrating it into the core logic of your blockchain.", "outline": [ { "depth": 2, @@ -4000,40 +4837,49 @@ }, { "depth": 2, - "title": "Origins", - "anchor": "origins" + "title": "Add the Pallets as Dependencies", + "anchor": "add-the-pallets-as-dependencies" + }, + { + "depth": 3, + "title": "Update the Runtime Configuration", + "anchor": "update-the-runtime-configuration" }, { "depth": 2, - "title": "Tracks", - "anchor": "tracks" + "title": "Recompile the Runtime", + "anchor": "recompile-the-runtime" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 3333, - "words": 469, - "headings": 4, - "estimated_token_count_total": 631 + "chars": 13091, + "words": 1522, + "headings": 6, + "estimated_token_count_total": 3091 }, - "hash": "sha256:baba9dd41091b792d09005d55d3df0bf65b35f42b40ebe63caf425a0978a22b0", + "hash": "sha256:87add0ae178e4970601a27efccadb58eff1375d19819201034ba2829914f1cd5", "token_estimator": "heuristic-v1" }, { - "id": "reference-governance", - "title": "On-Chain Governance Overview", - "slug": "reference-governance", + "id": "parachains-customize-runtime-pallet-development-benchmark-pallet", + "title": "Benchmark Your Pallet", + "slug": "parachains-customize-runtime-pallet-development-benchmark-pallet", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md", - "html_url": "https://docs.polkadot.com/reference/governance/", - "preview": "Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/benchmark-pallet/", + "preview": "Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.", "outline": [ { "depth": 2, @@ -4042,162 +4888,109 @@ }, { "depth": 2, - "title": "Governance Evolution", - "anchor": "governance-evolution" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "OpenGov Key Features", - "anchor": "opengov-key-features" + "title": "Create the Benchmarking Module", + "anchor": "create-the-benchmarking-module" }, { "depth": 2, - "title": "Origins and Tracks", - "anchor": "origins-and-tracks" + "title": "Define the Weight Trait", + "anchor": "define-the-weight-trait" }, { "depth": 2, - "title": "Referendums", - "anchor": "referendums" + "title": "Add WeightInfo to Config", + "anchor": "add-weightinfo-to-config" }, { - "depth": 3, - "title": "Vote on Referendums", - "anchor": "vote-on-referendums" + "depth": 2, + "title": "Update Extrinsic Weight Annotations", + "anchor": "update-extrinsic-weight-annotations" }, { - "depth": 3, - "title": "Delegate Voting Power", - "anchor": "delegate-voting-power" + "depth": 2, + "title": "Include the Benchmarking Module", + "anchor": "include-the-benchmarking-module" }, { - "depth": 3, - "title": "Cancel a Referendum", - "anchor": "cancel-a-referendum" + "depth": 2, + "title": "Configure Pallet Dependencies", + "anchor": "configure-pallet-dependencies" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 7493, - "words": 1019, - "headings": 9, - "estimated_token_count_total": 1611 - }, - "hash": "sha256:62beec261e72529f70e07a641177d489d2c8872f9c9d618cbadf1ac0fd881986", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-accounts", - "title": "Polkadot SDK Accounts", - "slug": "reference-parachains-accounts", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md", - "html_url": "https://docs.polkadot.com/reference/parachains/accounts/", - "preview": "Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Update Mock Runtime", + "anchor": "update-mock-runtime" }, { "depth": 2, - "title": "Account Data Structure", - "anchor": "account-data-structure" - }, - { - "depth": 3, - "title": "Account", - "anchor": "account" - }, - { - "depth": 3, - "title": "Account Info", - "anchor": "account-info" - }, - { - "depth": 3, - "title": "Account Reference Counters", - "anchor": "account-reference-counters" + "title": "Configure Runtime Benchmarking", + "anchor": "configure-runtime-benchmarking" }, { "depth": 2, - "title": "Account Balance Types", - "anchor": "account-balance-types" - }, - { - "depth": 3, - "title": "Balance Types", - "anchor": "balance-types" - }, - { - "depth": 3, - "title": "Locks", - "anchor": "locks" + "title": "Test Benchmark Compilation", + "anchor": "test-benchmark-compilation" }, { - "depth": 3, - "title": "Balance Types on Polkadot.js", - "anchor": "balance-types-on-polkadotjs" + "depth": 2, + "title": "Build the Runtime with Benchmarks", + "anchor": "build-the-runtime-with-benchmarks" }, { "depth": 2, - "title": "Address Formats", - "anchor": "address-formats" + "title": "Install the Benchmarking Tool", + "anchor": "install-the-benchmarking-tool" }, { - "depth": 3, - "title": "Basic Format", - "anchor": "basic-format" + "depth": 2, + "title": "Download the Weight Template", + "anchor": "download-the-weight-template" }, { - "depth": 3, - "title": "Address Type", - "anchor": "address-type" + "depth": 2, + "title": "Execute Benchmarks", + "anchor": "execute-benchmarks" }, { - "depth": 3, - "title": "Address Length", - "anchor": "address-length" + "depth": 2, + "title": "Use Generated Weights", + "anchor": "use-generated-weights" }, { - "depth": 3, - "title": "Checksum Types", - "anchor": "checksum-types" + "depth": 2, + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { - "depth": 3, - "title": "Validating Addresses", - "anchor": "validating-addresses" + "depth": 2, + "title": "Related Resources", + "anchor": "related-resources" } ], "stats": { - "chars": 29604, - "words": 4194, - "headings": 15, - "estimated_token_count_total": 6507 + "chars": 22752, + "words": 2813, + "headings": 18, + "estimated_token_count_total": 5191 }, - "hash": "sha256:0104a9132a69345a2faac37fca0e2853a2ded1efb009511a83a98d44509ab887", + "hash": "sha256:c1b53ecbfc3dea02097104c7a4c652e61ccc42ad56325a9c80684850a198fbdd", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-blocks", - "title": "Blocks", - "slug": "reference-parachains-blocks-transactions-fees-blocks", + "id": "parachains-customize-runtime-pallet-development-create-a-pallet", + "title": "Create a Custom Pallet", + "slug": "parachains-customize-runtime-pallet-development-create-a-pallet", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/", - "preview": "In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/create-a-pallet/", + "preview": "[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functional", "outline": [ { "depth": 2, @@ -4206,157 +4999,149 @@ }, { "depth": 2, - "title": "What is a Block?", - "anchor": "what-is-a-block" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Block Production", - "anchor": "block-production" + "title": "Core Pallet Components", + "anchor": "core-pallet-components" }, { - "depth": 3, - "title": "Initialize Block", - "anchor": "initialize-block" + "depth": 2, + "title": "Create the Pallet Project", + "anchor": "create-the-pallet-project" }, { - "depth": 3, - "title": "Finalize Block", - "anchor": "finalize-block" + "depth": 2, + "title": "Configure Dependencies", + "anchor": "configure-dependencies" }, { "depth": 2, - "title": "Block Authoring and Import", - "anchor": "block-authoring-and-import" + "title": "Initialize the Pallet Structure", + "anchor": "initialize-the-pallet-structure" }, { - "depth": 3, - "title": "Block Import Queue", - "anchor": "block-import-queue" + "depth": 2, + "title": "Configure the Pallet", + "anchor": "configure-the-pallet" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 6252, - "words": 910, - "headings": 8, - "estimated_token_count_total": 1395 - }, - "hash": "sha256:424783c102bea5dae5b8749635858c6c59055563442a98f57521f0027dafa8d3", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-blocks-transactions-fees-fees", - "title": "Transactions Weights and Fees", - "slug": "reference-parachains-blocks-transactions-fees-fees", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/", - "preview": "When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop th", - "outline": [ + "title": "Define Events", + "anchor": "define-events" + }, { "depth": 2, - "title": "Introductions", - "anchor": "introductions" + "title": "Define Errors", + "anchor": "define-errors" }, { "depth": 2, - "title": "How Fees are Calculated", - "anchor": "how-fees-are-calculated" + "title": "Add Storage Items", + "anchor": "add-storage-items" }, { "depth": 2, - "title": "Using the Transaction Payment Pallet", - "anchor": "using-the-transaction-payment-pallet" + "title": "Configure Genesis State", + "anchor": "configure-genesis-state" }, { - "depth": 3, - "title": "Understanding the Inclusion Fee", - "anchor": "understanding-the-inclusion-fee" + "depth": 2, + "title": "Implement Dispatchable Functions", + "anchor": "implement-dispatchable-functions" }, { "depth": 3, - "title": "Accounts with an Insufficient Balance", - "anchor": "accounts-with-an-insufficient-balance" + "title": "Dispatchable Function Details", + "anchor": "dispatchable-function-details" }, { - "depth": 3, - "title": "Fee Multipliers", - "anchor": "fee-multipliers" + "depth": 2, + "title": "Verify Pallet Compilation", + "anchor": "verify-pallet-compilation" }, { "depth": 2, - "title": "Transactions with Special Requirements", - "anchor": "transactions-with-special-requirements" + "title": "Add the Pallet to Your Runtime", + "anchor": "add-the-pallet-to-your-runtime" }, { - "depth": 2, - "title": "Default Weight Annotations", - "anchor": "default-weight-annotations" + "depth": 3, + "title": "Add Runtime Dependency", + "anchor": "add-runtime-dependency" }, { "depth": 3, - "title": "Weights and Database Read/Write Operations", - "anchor": "weights-and-database-readwrite-operations" + "title": "Implement the Config Trait", + "anchor": "implement-the-config-trait" }, { "depth": 3, - "title": "Dispatch Classes", - "anchor": "dispatch-classes" + "title": "Add to Runtime Construct", + "anchor": "add-to-runtime-construct" }, { "depth": 3, - "title": "Dynamic Weights", - "anchor": "dynamic-weights" + "title": "Configure Genesis for Your Runtime", + "anchor": "configure-genesis-for-your-runtime" }, { - "depth": 2, - "title": "Post Dispatch Weight Correction", - "anchor": "post-dispatch-weight-correction" + "depth": 3, + "title": "Verify Runtime Compilation", + "anchor": "verify-runtime-compilation" }, { "depth": 2, - "title": "Custom Fees", - "anchor": "custom-fees" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { "depth": 3, - "title": "Custom Weights", - "anchor": "custom-weights" + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" + }, + { + "depth": 3, + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Interact with Your Pallet", + "anchor": "interact-with-your-pallet" + }, + { + "depth": 2, + "title": "Key Takeaways", + "anchor": "key-takeaways" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 20800, - "words": 2917, - "headings": 15, - "estimated_token_count_total": 4464 + "chars": 26958, + "words": 3085, + "headings": 26, + "estimated_token_count_total": 6194 }, - "hash": "sha256:7d0c3fa7982b3e1843adb8f27422456397580b3a3eba5047b381da8517742536", + "hash": "sha256:dad68ea59fd05fd60dc8890c4cf5615243c7ea879830b0dcf3a5e5e53c3ccec7", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-transactions", - "title": "Transactions", - "slug": "reference-parachains-blocks-transactions-fees-transactions", + "id": "parachains-customize-runtime-pallet-development-mock-runtime", + "title": "Mock Your Runtime", + "slug": "parachains-customize-runtime-pallet-development-mock-runtime", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/", - "preview": "Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/", + "preview": "Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node.", "outline": [ { "depth": 2, @@ -4365,130 +5150,141 @@ }, { "depth": 2, - "title": "What Is a Transaction?", - "anchor": "what-is-a-transaction" - }, - { - "depth": 3, - "title": "Signed Transactions", - "anchor": "signed-transactions" - }, - { - "depth": 3, - "title": "Unsigned Transactions", - "anchor": "unsigned-transactions" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Inherent Transactions", - "anchor": "inherent-transactions" + "depth": 2, + "title": "Understand Mock Runtimes", + "anchor": "understand-mock-runtimes" }, { "depth": 2, - "title": "Transaction Formats", - "anchor": "transaction-formats" + "title": "Create the Mock Runtime Module", + "anchor": "create-the-mock-runtime-module" }, { - "depth": 3, - "title": "Types of Transaction Formats", - "anchor": "types-of-transaction-formats" + "depth": 2, + "title": "Set Up Basic Mock", + "anchor": "set-up-basic-mock" }, { - "depth": 3, - "title": "Signed Transaction Data Structure", - "anchor": "signed-transaction-data-structure" + "depth": 2, + "title": "Implement Essential Configuration", + "anchor": "implement-essential-configuration" }, { - "depth": 3, - "title": "Signed Extensions", - "anchor": "signed-extensions" + "depth": 2, + "title": "Implement Your Pallet's Configuration", + "anchor": "implement-your-pallets-configuration" }, { "depth": 2, - "title": "Transaction Construction", - "anchor": "transaction-construction" + "title": "Configure Genesis Storage", + "anchor": "configure-genesis-storage" }, { "depth": 3, - "title": "Construct a Signed Transaction", - "anchor": "construct-a-signed-transaction" + "title": "Basic Test Environment", + "anchor": "basic-test-environment" }, { "depth": 3, - "title": "Transaction Encoding", - "anchor": "transaction-encoding" + "title": "Custom Genesis Configurations", + "anchor": "custom-genesis-configurations" }, { - "depth": 3, - "title": "Customize Transaction Construction", - "anchor": "customize-transaction-construction" + "depth": 2, + "title": "Verify Mock Compilation", + "anchor": "verify-mock-compilation" }, { "depth": 2, - "title": "Lifecycle of a Transaction", - "anchor": "lifecycle-of-a-transaction" + "title": "Key Takeaways", + "anchor": "key-takeaways" }, { - "depth": 3, - "title": "Define Transaction Properties", - "anchor": "define-transaction-properties" - }, + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 11766, + "words": 1369, + "headings": 13, + "estimated_token_count_total": 2514 + }, + "hash": "sha256:dd784a5d2daebb9a885fe09f6a967e6c84958d96ddb38d8366eabe9d860fa539", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-customize-runtime-pallet-development-pallet-testing", + "title": "Unit Test Pallets", + "slug": "parachains-customize-runtime-pallet-development-pallet-testing", + "categories": [ + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/", + "preview": "Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.", + "outline": [ { - "depth": 3, - "title": "Process on a Block Authoring Node", - "anchor": "process-on-a-block-authoring-node" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Validate and Queue", - "anchor": "validate-and-queue" + "depth": 2, + "title": "Writing Unit Tests", + "anchor": "writing-unit-tests" }, { "depth": 3, - "title": "Transaction Ordering and Priority", - "anchor": "transaction-ordering-and-priority" + "title": "Test Initialization", + "anchor": "test-initialization" }, { "depth": 3, - "title": "Transaction Execution", - "anchor": "transaction-execution" + "title": "Function Call Testing", + "anchor": "function-call-testing" }, { - "depth": 2, - "title": "Transaction Mortality", - "anchor": "transaction-mortality" + "depth": 3, + "title": "Storage Testing", + "anchor": "storage-testing" }, { - "depth": 2, - "title": "Unique Identifiers for Extrinsics", - "anchor": "unique-identifiers-for-extrinsics" + "depth": 3, + "title": "Event Testing", + "anchor": "event-testing" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 23610, - "words": 3333, - "headings": 22, - "estimated_token_count_total": 4708 + "chars": 6895, + "words": 912, + "headings": 7, + "estimated_token_count_total": 1563 }, - "hash": "sha256:66726634d3a51cd9c471621054a6e5f09c8061dca6144b64c8bcf45626359617", + "hash": "sha256:041ccd82f0c1ddfb93be05feb6cf9d7d4a7e37af6caa8fa8fdab5d5538017122", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-chain-data", - "title": "Chain Data", - "slug": "reference-parachains-chain-data", + "id": "parachains-customize-runtime", + "title": "Overview of FRAME", + "slug": "parachains-customize-runtime", "categories": [ "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md", - "html_url": "https://docs.polkadot.com/reference/parachains/chain-data/", - "preview": "Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/", + "preview": "A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a run", "outline": [ { "depth": 2, @@ -4497,408 +5293,364 @@ }, { "depth": 2, - "title": "Application Development", - "anchor": "application-development" - }, - { - "depth": 2, - "title": "Understand Metadata", - "anchor": "understand-metadata" - }, - { - "depth": 2, - "title": "Expose Runtime Information as Metadata", - "anchor": "expose-runtime-information-as-metadata" + "title": "Understanding Your Runtime", + "anchor": "understanding-your-runtime" }, { "depth": 2, - "title": "Generate Metadata", - "anchor": "generate-metadata" + "title": "Runtime Architecture", + "anchor": "runtime-architecture" }, { "depth": 2, - "title": "Retrieve Runtime Metadata", - "anchor": "retrieve-runtime-metadata" - }, - { - "depth": 3, - "title": "Use Polkadot.js", - "anchor": "use-polkadotjs" + "title": "Building Blocks: Pallets", + "anchor": "building-blocks-pallets" }, { "depth": 3, - "title": "Use Curl", - "anchor": "use-curl" + "title": "Pre-Built Pallets vs. Custom Pallets", + "anchor": "pre-built-pallets-vs-custom-pallets" }, { "depth": 3, - "title": "Use Subxt", - "anchor": "use-subxt" - }, - { - "depth": 2, - "title": "Client Applications and Metadata", - "anchor": "client-applications-and-metadata" + "title": "Pallet Structure", + "anchor": "pallet-structure" }, { "depth": 2, - "title": "Metadata Format", - "anchor": "metadata-format" - }, - { - "depth": 3, - "title": "Pallets", - "anchor": "pallets" - }, - { - "depth": 3, - "title": "Extrinsic", - "anchor": "extrinsic" + "title": "How Runtime Customization Works", + "anchor": "how-runtime-customization-works" }, { "depth": 2, - "title": "Included RPC APIs", - "anchor": "included-rpc-apis" + "title": "Starting Templates", + "anchor": "starting-templates" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Key Customization Scenarios", + "anchor": "key-customization-scenarios" } ], "stats": { - "chars": 18650, - "words": 2216, - "headings": 15, - "estimated_token_count_total": 3774 + "chars": 8236, + "words": 1101, + "headings": 9, + "estimated_token_count_total": 1828 }, - "hash": "sha256:49238d1e9e2c33e0fcd3a84b5e30f0d3840d7d23a783b538875e0a23f38efc1d", + "hash": "sha256:ad58d1c942b567acc4519abc35c0a049ab3e04711c2a49089ceba6324a5aa7ea", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-consensus-async-backing", - "title": "reference-parachains-consensus-async-backing", - "slug": "reference-parachains-consensus-async-backing", + "id": "parachains-get-started", + "title": "Get Started with Parachain Development", + "slug": "parachains-get-started", "categories": [ - "Uncategorized" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-async-backing.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/async-backing/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-consensus-elastic-scaling", - "title": "Elastic Scaling", - "slug": "reference-parachains-consensus-elastic-scaling", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-elastic-scaling.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/elastic-scaling/", - "preview": "Polkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md", + "html_url": "https://docs.polkadot.com/parachains/get-started/", + "preview": "The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Quick Start Guides", + "anchor": "quick-start-guides" }, { "depth": 2, - "title": "How Elastic Scaling Works", - "anchor": "how-elastic-scaling-works" + "title": "Launch a Simple Parachain", + "anchor": "launch-a-simple-parachain" }, { "depth": 2, - "title": "Benefits of Elastic Scaling", - "anchor": "benefits-of-elastic-scaling" + "title": "Customize Your Runtime", + "anchor": "customize-your-runtime" + }, + { + "depth": 3, + "title": "Pallet Development", + "anchor": "pallet-development" }, { "depth": 2, - "title": "Use Cases", - "anchor": "use-cases" + "title": "Testing", + "anchor": "testing" }, { - "depth": 3, - "title": "Handling Sudden Traffic Spikes", - "anchor": "handling-sudden-traffic-spikes" + "depth": 2, + "title": "Runtime Upgrades and Maintenance", + "anchor": "runtime-upgrades-and-maintenance" }, { - "depth": 3, - "title": "Supporting Early-Stage Growth", - "anchor": "supporting-early-stage-growth" + "depth": 2, + "title": "Interoperability", + "anchor": "interoperability" }, { - "depth": 3, - "title": "Scaling Massive IoT Networks", - "anchor": "scaling-massive-iot-networks" + "depth": 2, + "title": "Integrations", + "anchor": "integrations" }, { - "depth": 3, - "title": "Powering Real-Time, Low-Latency Systems", - "anchor": "powering-real-time-low-latency-systems" + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 7871, - "words": 1047, - "headings": 8, - "estimated_token_count_total": 1440 - }, - "hash": "sha256:2d228c52844df8952520fafdd3e6f0e26bfd2f32b5ee60c6241cf7d38603643c", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-consensus", - "title": "reference-parachains-consensus", - "slug": "reference-parachains-consensus", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 7941, + "words": 631, + "headings": 9, + "estimated_token_count_total": 2292 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:759ed27cf3d473445e33141089b652082c42a2c59eb822d6b506146fd9555e13", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-cryptography", - "title": "Cryptography", - "slug": "reference-parachains-cryptography", + "id": "parachains-install-polkadot-sdk", + "title": "Install Polkadot SDK", + "slug": "parachains-install-polkadot-sdk", "categories": [ "Basics", - "Polkadot Protocol" + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md", - "html_url": "https://docs.polkadot.com/reference/parachains/cryptography/", - "preview": "Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md", + "html_url": "https://docs.polkadot.com/parachains/install-polkadot-sdk/", + "preview": "This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts:", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Install Dependencies: macOS", + "anchor": "install-dependencies-macos" }, { - "depth": 2, - "title": "Hash Functions", - "anchor": "hash-functions" + "depth": 3, + "title": "Before You Begin {: #before-you-begin-mac-os }", + "anchor": "before-you-begin-before-you-begin-mac-os" }, { "depth": 3, - "title": "Key Properties of Hash Functions", - "anchor": "key-properties-of-hash-functions" + "title": "Install Homebrew", + "anchor": "install-homebrew" }, { "depth": 3, - "title": "Blake2", - "anchor": "blake2" + "title": "Support for Apple Silicon", + "anchor": "support-for-apple-silicon" }, { - "depth": 2, - "title": "Types of Cryptography", - "anchor": "types-of-cryptography" + "depth": 3, + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-mac-os" }, { - "depth": 3, - "title": "Symmetric Cryptography", - "anchor": "symmetric-cryptography" + "depth": 2, + "title": "Install Dependencies: Linux", + "anchor": "install-dependencies-linux" }, { "depth": 3, - "title": "Asymmetric Cryptography", - "anchor": "asymmetric-cryptography" + "title": "Before You Begin {: #before-you-begin-linux }", + "anchor": "before-you-begin-before-you-begin-linux" }, { "depth": 3, - "title": "Trade-offs and Compromises", - "anchor": "trade-offs-and-compromises" + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-linux }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-linux" }, { "depth": 2, - "title": "Digital Signatures", - "anchor": "digital-signatures" + "title": "Install Dependencies: Windows (WSL)", + "anchor": "install-dependencies-windows-wsl" }, { "depth": 3, - "title": "Example of Creating a Digital Signature", - "anchor": "example-of-creating-a-digital-signature" + "title": "Before You Begin {: #before-you-begin-windows-wls }", + "anchor": "before-you-begin-before-you-begin-windows-wls" }, { - "depth": 2, - "title": "Elliptic Curve", - "anchor": "elliptic-curve" + "depth": 3, + "title": "Set Up Windows Subsystem for Linux", + "anchor": "set-up-windows-subsystem-for-linux" }, { "depth": 3, - "title": "Various Implementations", - "anchor": "various-implementations" - } - ], - "stats": { - "chars": 8860, - "words": 1293, - "headings": 12, - "estimated_token_count_total": 1797 - }, - "hash": "sha256:259dcef86aadc513675258b665cc3940db65af6eb32a5db85da6ac339966fa60", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-data-encoding", - "title": "Data Encoding", - "slug": "reference-parachains-data-encoding", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md", - "html_url": "https://docs.polkadot.com/reference/parachains/data-encoding/", - "preview": "The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-windows-wls" }, { "depth": 2, - "title": "SCALE Codec", - "anchor": "scale-codec" + "title": "Build the Polkadot SDK", + "anchor": "build-the-polkadot-sdk" }, { "depth": 3, - "title": "Encode", - "anchor": "encode" + "title": "Clone the Polkadot SDK", + "anchor": "clone-the-polkadot-sdk" }, { "depth": 3, - "title": "Decode", - "anchor": "decode" + "title": "Compile the Polkadot SDK", + "anchor": "compile-the-polkadot-sdk" }, { "depth": 3, - "title": "CompactAs", - "anchor": "compactas" + "title": "Verify the Build", + "anchor": "verify-the-build" }, { - "depth": 3, - "title": "HasCompact", - "anchor": "hascompact" + "depth": 2, + "title": "Optional: Run the Kitchensink Node", + "anchor": "optional-run-the-kitchensink-node" }, { "depth": 3, - "title": "EncodeLike", - "anchor": "encodelike" + "title": "Run the Kitchensink Node in Development Mode", + "anchor": "run-the-kitchensink-node-in-development-mode" }, { "depth": 3, - "title": "Data Types", - "anchor": "data-types" - }, - { - "depth": 2, - "title": "Encode and Decode Rust Trait Implementations", - "anchor": "encode-and-decode-rust-trait-implementations" + "title": "Interact with the Kitchensink Node", + "anchor": "interact-with-the-kitchensink-node" }, { "depth": 2, - "title": "SCALE Codec Libraries", - "anchor": "scale-codec-libraries" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 13629, - "words": 1314, - "headings": 10, - "estimated_token_count_total": 3213 + "chars": 16051, + "words": 2312, + "headings": 20, + "estimated_token_count_total": 3345 }, - "hash": "sha256:e448294b6e52291ac0add5fa6533572814e6cd27af42bdaccc2000b86f52d775", + "hash": "sha256:a52c05b623f3780f14be3a5f36b3d79a6c1965c2fbfd6864b512a9a70c47cd60", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-interoperability", - "title": "Interoperability", - "slug": "reference-parachains-interoperability", + "id": "parachains-integrations-indexers", + "title": "Indexers", + "slug": "parachains-integrations-indexers", "categories": [ - "Basics", - "Polkadot Protocol" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md", - "html_url": "https://docs.polkadot.com/reference/parachains/interoperability/", - "preview": "Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/indexers/", + "preview": "Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges:", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "The Challenge of Blockchain Data Access", + "anchor": "the-challenge-of-blockchain-data-access" }, { "depth": 2, - "title": "Why Interoperability Matters", - "anchor": "why-interoperability-matters" + "title": "What is a Blockchain Indexer?", + "anchor": "what-is-a-blockchain-indexer" }, { "depth": 2, - "title": "Key Mechanisms for Interoperability", - "anchor": "key-mechanisms-for-interoperability" + "title": "Indexer Implementations", + "anchor": "indexer-implementations" + } + ], + "stats": { + "chars": 2230, + "words": 302, + "headings": 3, + "estimated_token_count_total": 428 + }, + "hash": "sha256:cfcc76bb24779c9b613f2c046b6f99a0f2529c25fd82287d804f6b945b936227", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-integrations-oracles", + "title": "Oracles", + "slug": "parachains-integrations-oracles", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/oracles/", + "preview": "Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the \"blockchain oracle problem.\" Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain.", + "outline": [ + { + "depth": 2, + "title": "What is a Blockchain Oracle?", + "anchor": "what-is-a-blockchain-oracle" }, { - "depth": 3, - "title": "Cross-Consensus Messaging (XCM): The Backbone of Communication", - "anchor": "cross-consensus-messaging-xcm-the-backbone-of-communication" + "depth": 2, + "title": "Oracle Implementations", + "anchor": "oracle-implementations" + } + ], + "stats": { + "chars": 1343, + "words": 181, + "headings": 2, + "estimated_token_count_total": 245 + }, + "hash": "sha256:6d8e01281a5895fd2bc4438b24c170c72a496de0b838626a53e87685aea4aa25", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-integrations-wallets", + "title": "Wallets", + "slug": "parachains-integrations-wallets", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/wallets/", + "preview": "A wallet serves as your gateway to interacting with blockchain networks. Rather than storing funds, wallets secure your private keys, controlling access to your blockchain assets. Your private key provides complete control over all permitted transactions on your blockchain account, making it essential to keep it secure.", + "outline": [ + { + "depth": 2, + "title": "What is a Blockchain Wallet?", + "anchor": "what-is-a-blockchain-wallet" }, { - "depth": 3, - "title": "Bridges: Connecting External Networks", - "anchor": "bridges-connecting-external-networks" + "depth": 2, + "title": "Hot Wallets", + "anchor": "hot-wallets" }, { "depth": 2, - "title": "The Polkadot Advantage", - "anchor": "the-polkadot-advantage" + "title": "Cold Wallets", + "anchor": "cold-wallets" }, { "depth": 2, - "title": "Looking Ahead", - "anchor": "looking-ahead" + "title": "Wallet Tools", + "anchor": "wallet-tools" } ], "stats": { - "chars": 4635, - "words": 584, - "headings": 7, - "estimated_token_count_total": 772 + "chars": 3588, + "words": 489, + "headings": 4, + "estimated_token_count_total": 786 }, - "hash": "sha256:11bb4f113bdda5852a3115e64d5ba47f8eccd4e3619a05ad960ab3a541f31346", + "hash": "sha256:62c5ad101282227f79eac0e30a3ba9ce3ae1bf9e358bd58c0b17ef45db29c2ff", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-networks", - "title": "Networks", - "slug": "reference-parachains-networks", + "id": "parachains-interoperability-channels-between-parachains", + "title": "Opening HRMP Channels Between Parachains", + "slug": "parachains-interoperability-channels-between-parachains", "categories": [ - "Basics", - "Polkadot Protocol", - "Networks" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md", - "html_url": "https://docs.polkadot.com/reference/parachains/networks/", - "preview": "The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's va", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/", + "preview": "For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required:", "outline": [ { "depth": 2, @@ -4907,70 +5659,69 @@ }, { "depth": 2, - "title": "Network Overview", - "anchor": "network-overview" - }, - { - "depth": 2, - "title": "Polkadot Development Networks", - "anchor": "polkadot-development-networks" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Kusama Network", - "anchor": "kusama-network" + "title": "Procedure to Initiate an HRMP Channel", + "anchor": "procedure-to-initiate-an-hrmp-channel" }, { - "depth": 2, - "title": "Test Networks", - "anchor": "test-networks" + "depth": 3, + "title": "Fund Sender Sovereign Account", + "anchor": "fund-sender-sovereign-account" }, { "depth": 3, - "title": "Westend", - "anchor": "westend" + "title": "Create Channel Opening Extrinsic", + "anchor": "create-channel-opening-extrinsic" }, { "depth": 3, - "title": "Paseo", - "anchor": "paseo" + "title": "Craft and Submit the XCM Message from the Sender", + "anchor": "craft-and-submit-the-xcm-message-from-the-sender" }, { "depth": 2, - "title": "Local Test Networks", - "anchor": "local-test-networks" + "title": "Procedure to Accept an HRMP Channel", + "anchor": "procedure-to-accept-an-hrmp-channel" }, { "depth": 3, - "title": "Zombienet", - "anchor": "zombienet" + "title": "Fund Receiver Sovereign Account", + "anchor": "fund-receiver-sovereign-account" }, { "depth": 3, - "title": "Chopsticks", - "anchor": "chopsticks" + "title": "Create Channel Accepting Extrinsic", + "anchor": "create-channel-accepting-extrinsic" + }, + { + "depth": 3, + "title": "Craft and Submit the XCM Message from the Receiver", + "anchor": "craft-and-submit-the-xcm-message-from-the-receiver" } ], "stats": { - "chars": 7834, - "words": 1111, + "chars": 10934, + "words": 1549, "headings": 10, - "estimated_token_count_total": 1473 + "estimated_token_count_total": 2285 }, - "hash": "sha256:e49e063a2cc0fb5a48c6cdc3de266bb6e025a006940fea8e90cc4d5f9884900f", + "hash": "sha256:b8de1228b9976765accd18ff724038bed6f2449367f500bc3177ab2a053abe63", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-node-and-runtime", - "title": "Node and Runtime", - "slug": "reference-parachains-node-and-runtime", + "id": "parachains-interoperability-channels-with-system-parachains", + "title": "Opening HRMP Channels with System Parachains", + "slug": "parachains-interoperability-channels-with-system-parachains", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md", - "html_url": "https://docs.polkadot.com/reference/parachains/node-and-runtime/", - "preview": "Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/", + "preview": "While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach.", "outline": [ { "depth": 2, @@ -4979,70 +5730,50 @@ }, { "depth": 2, - "title": "Architectural Principles", - "anchor": "architectural-principles" - }, - { - "depth": 3, - "title": "Advantages of this Architecture", - "anchor": "advantages-of-this-architecture" - }, - { - "depth": 2, - "title": "Node (Client)", - "anchor": "node-client" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Runtime", - "anchor": "runtime" - }, - { - "depth": 3, - "title": "Characteristics", - "anchor": "characteristics" + "title": "Procedure to Establish an HRMP Channel", + "anchor": "procedure-to-establish-an-hrmp-channel" }, { "depth": 3, - "title": "Key Functions", - "anchor": "key-functions" - }, - { - "depth": 2, - "title": "Communication Between Node and Runtime", - "anchor": "communication-between-node-and-runtime" + "title": "Fund Parachain Sovereign Account", + "anchor": "fund-parachain-sovereign-account" }, { "depth": 3, - "title": "Runtime APIs", - "anchor": "runtime-apis" + "title": "Create Establish Channel with System Extrinsic", + "anchor": "create-establish-channel-with-system-extrinsic" }, { "depth": 3, - "title": "Host Functions", - "anchor": "host-functions" + "title": "Craft and Submit the XCM Message", + "anchor": "craft-and-submit-the-xcm-message" } ], "stats": { - "chars": 4937, - "words": 628, - "headings": 10, - "estimated_token_count_total": 914 + "chars": 7203, + "words": 889, + "headings": 6, + "estimated_token_count_total": 1427 }, - "hash": "sha256:8122e21c149d0863cfe3b37fc5606bcdb91668e9d265f0f05451a61ff70e4e93", + "hash": "sha256:b501d99c464fb049d46676827b6a325a195c90617becc4a7db305441c115350a", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-randomness", - "title": "Randomness", - "slug": "reference-parachains-randomness", + "id": "parachains-interoperability-get-started", + "title": "Introduction to XCM", + "slug": "parachains-interoperability-get-started", "categories": [ "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md", - "html_url": "https://docs.polkadot.com/reference/parachains/randomness/", - "preview": "Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as \"random\" numbers on a computer are actually pseudo-random. These numbers rely on an initial \"seed,\" which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\\_blank}, [heart rates](https://m", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/get-started/", + "preview": "Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.", "outline": [ { "depth": 2, @@ -5051,50 +5782,54 @@ }, { "depth": 2, - "title": "VRF", - "anchor": "vrf" + "title": "Messaging Format", + "anchor": "messaging-format" }, { - "depth": 3, - "title": "How VRF Works", - "anchor": "how-vrf-works" + "depth": 2, + "title": "The Four Principles of XCM", + "anchor": "the-four-principles-of-xcm" }, { "depth": 2, - "title": "RANDAO", - "anchor": "randao" + "title": "The XCM Tech Stack", + "anchor": "the-xcm-tech-stack" }, { "depth": 2, - "title": "VDFs", - "anchor": "vdfs" + "title": "Core Functionalities of XCM", + "anchor": "core-functionalities-of-xcm" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "XCM Example", + "anchor": "xcm-example" + }, + { + "depth": 2, + "title": "Overview", + "anchor": "overview" } ], "stats": { - "chars": 6503, - "words": 1005, - "headings": 6, - "estimated_token_count_total": 1388 + "chars": 7450, + "words": 974, + "headings": 7, + "estimated_token_count_total": 1501 }, - "hash": "sha256:c7d8a5a4263fd21af458ab0bd102377104affdf2431b4fe74eeff4ebe62a4a81", + "hash": "sha256:3b26606dd5310c4b8ade5d05270ebf1e06f59afcda4ca2b985e07948215a197e", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains", - "title": "Parachains Overview", - "slug": "reference-parachains", + "id": "parachains-launch-a-parachain-deploy-to-polkadot", + "title": "Deploy on Polkadot", + "slug": "parachains-launch-a-parachain-deploy-to-polkadot", "categories": [ - "Basics", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md", - "html_url": "https://docs.polkadot.com/reference/parachains/", - "preview": "A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-deploy-to-polkadot.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/deploy-to-polkadot/", + "preview": "Previously, you learned how to [choose and set up a parachain template](/parachains/launch-a-parachain/choose-a-template/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to the Polkadot TestNet. Deploying to a TestNet is a crucial step for validating your parachain's functionality and preparing it for eventual MainNet deployment.", "outline": [ { "depth": 2, @@ -5103,49 +5838,64 @@ }, { "depth": 2, - "title": "Polkadot SDK: Parachain Architecture", - "anchor": "polkadot-sdk-parachain-architecture" + "title": "Get Started with an Account and Tokens", + "anchor": "get-started-with-an-account-and-tokens" }, { - "depth": 3, - "title": "Substrate: The Foundation", - "anchor": "substrate-the-foundation" + "depth": 2, + "title": "Reserve a Parachain Identifier", + "anchor": "reserve-a-parachain-identifier" }, { - "depth": 3, - "title": "FRAME: Building Blocks for Your Runtime", - "anchor": "frame-building-blocks-for-your-runtime" + "depth": 2, + "title": "Generate Custom Keys for Your Collators", + "anchor": "generate-custom-keys-for-your-collators" }, { - "depth": 3, - "title": "Cumulus: Parachain-Specific Functionality", - "anchor": "cumulus-parachain-specific-functionality" + "depth": 2, + "title": "Generate the Chain Specification", + "anchor": "generate-the-chain-specification" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Export Required Files", + "anchor": "export-required-files" + }, + { + "depth": 2, + "title": "Register a Parathread", + "anchor": "register-a-parathread" + }, + { + "depth": 2, + "title": "Start the Collator Node", + "anchor": "start-the-collator-node" + }, + { + "depth": 2, + "title": "Producing Blocks", + "anchor": "producing-blocks" } ], "stats": { - "chars": 8495, - "words": 1029, - "headings": 6, - "estimated_token_count_total": 1759 + "chars": 20252, + "words": 2357, + "headings": 9, + "estimated_token_count_total": 4129 }, - "hash": "sha256:ecb0d9459e08920db7d2d59dc7c01aba7a91ce8c9e39256bd0c3efa473dbaa17", + "hash": "sha256:fde940bced4380fc01b1840907059d03f6d47b6cb54bf78c95269ac57adbc99e", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-assets-and-smart-contracts", - "title": "Asset Hub", - "slug": "reference-polkadot-hub-assets-and-smart-contracts", + "id": "parachains-launch-a-parachain-obtain-coretime", + "title": "Obtain Coretime", + "slug": "parachains-launch-a-parachain-obtain-coretime", "categories": [ - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/assets-and-smart-contracts/", - "preview": "The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integra", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/", + "preview": "After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime.", "outline": [ { "depth": 2, @@ -5154,98 +5904,130 @@ }, { "depth": 2, - "title": "Assets Basics", - "anchor": "assets-basics" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Assets Pallet", - "anchor": "assets-pallet" + "title": "Order On-Demand Coretime", + "anchor": "order-on-demand-coretime" }, { "depth": 3, - "title": "Key Features", - "anchor": "key-features" + "title": "On-Demand Extrinsics", + "anchor": "on-demand-extrinsics" }, { "depth": 3, - "title": "Main Functions", - "anchor": "main-functions" + "title": "Place an On-Demand Order", + "anchor": "place-an-on-demand-order" }, { - "depth": 3, - "title": "Querying Functions", - "anchor": "querying-functions" + "depth": 2, + "title": "Purchase Bulk Coretime", + "anchor": "purchase-bulk-coretime" }, { "depth": 3, - "title": "Permission Models and Roles", - "anchor": "permission-models-and-roles" + "title": "Connect Your Wallet to RegionX", + "anchor": "connect-your-wallet-to-regionx" }, { "depth": 3, - "title": "Asset Freezing", - "anchor": "asset-freezing" + "title": "Obtain Coretime Chain Funds", + "anchor": "obtain-coretime-chain-funds" }, { "depth": 3, - "title": "Non-Custodial Transfers (Approval API)", - "anchor": "non-custodial-transfers-approval-api" + "title": "Purchase a Core", + "anchor": "purchase-a-core" }, { - "depth": 2, - "title": "Foreign Assets", - "anchor": "foreign-assets" + "depth": 3, + "title": "Verify Your Purchase", + "anchor": "verify-your-purchase" }, { "depth": 3, - "title": "Handling Foreign Assets", - "anchor": "handling-foreign-assets" + "title": "Assign Your Parachain to the Core", + "anchor": "assign-your-parachain-to-the-core" }, { "depth": 2, - "title": "Integration", - "anchor": "integration" + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 9049, + "words": 1345, + "headings": 12, + "estimated_token_count_total": 2103 + }, + "hash": "sha256:15154f211753665d9af70dc81d15ceb3f0954e3febf9282c68c0074881d620c6", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-launch-a-parachain-set-up-the-parachain-template", + "title": "Set Up the Polkadot SDK Parachain Template", + "slug": "parachains-launch-a-parachain-set-up-the-parachain-template", + "categories": [ + "Basics", + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/", + "preview": "The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "API Sidecar", - "anchor": "api-sidecar" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "TxWrapper", - "anchor": "txwrapper" + "depth": 2, + "title": "Polkadot SDK Utility Tools", + "anchor": "polkadot-sdk-utility-tools" }, { - "depth": 3, - "title": "Parachain Node", - "anchor": "parachain-node" + "depth": 2, + "title": "Clone the Template", + "anchor": "clone-the-template" }, { "depth": 2, - "title": "XCM Transfer Monitoring", - "anchor": "xcm-transfer-monitoring" + "title": "Explore the Project Structure", + "anchor": "explore-the-project-structure" }, { - "depth": 3, - "title": "Monitor XCM Deposits", - "anchor": "monitor-xcm-deposits" + "depth": 2, + "title": "Compile the Runtime", + "anchor": "compile-the-runtime" }, { - "depth": 3, - "title": "Track XCM Information Back to the Source", - "anchor": "track-xcm-information-back-to-the-source" + "depth": 2, + "title": "Verify the Build", + "anchor": "verify-the-build" }, { - "depth": 3, - "title": "Practical Monitoring Examples", - "anchor": "practical-monitoring-examples" + "depth": 2, + "title": "Run the Node Locally", + "anchor": "run-the-node-locally" }, { - "depth": 3, - "title": "Monitor for Failed XCM Transfers", - "anchor": "monitor-for-failed-xcm-transfers" + "depth": 2, + "title": "Interact with the Node", + "anchor": "interact-with-the-node" + }, + { + "depth": 2, + "title": "Stop the Node", + "anchor": "stop-the-node" }, { "depth": 2, @@ -5254,24 +6036,24 @@ } ], "stats": { - "chars": 18211, - "words": 2649, - "headings": 21, - "estimated_token_count_total": 3678 + "chars": 10591, + "words": 1510, + "headings": 11, + "estimated_token_count_total": 2377 }, - "hash": "sha256:3d10c04cffc5f737ff75b079d661c2c1904629d23ae1e415e64fd6ae4e98759e", + "hash": "sha256:1277261cb3de71cac194f26e765124ea9f3e09cffdcd94bb717965a11cb7f374", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-bridging", - "title": "Bridge Hub", - "slug": "reference-polkadot-hub-bridging", + "id": "parachains-runtime-maintenance-runtime-upgrades", + "title": "Runtime Upgrades", + "slug": "parachains-runtime-maintenance-runtime-upgrades", "categories": [ - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-bridging.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/bridging/", - "preview": "The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interope", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/", + "preview": "One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.", "outline": [ { "depth": 2, @@ -5280,49 +6062,44 @@ }, { "depth": 2, - "title": "Trustless Bridging", - "anchor": "trustless-bridging" - }, - { - "depth": 2, - "title": "Bridging Components", - "anchor": "bridging-components" + "title": "How Runtime Upgrades Work", + "anchor": "how-runtime-upgrades-work" }, { "depth": 3, - "title": "Ethereum-Specific Support", - "anchor": "ethereum-specific-support" + "title": "Runtime Versioning", + "anchor": "runtime-versioning" }, { - "depth": 2, - "title": "Deployed Bridges", - "anchor": "deployed-bridges" + "depth": 3, + "title": "Accessing the Runtime Version", + "anchor": "accessing-the-runtime-version" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Storage Migrations", + "anchor": "storage-migrations" } ], "stats": { - "chars": 5467, - "words": 776, - "headings": 6, - "estimated_token_count_total": 1220 + "chars": 5837, + "words": 811, + "headings": 5, + "estimated_token_count_total": 1161 }, - "hash": "sha256:86734ba8bcdea7913f488edf666a6104bed0a18649d57abde82c149c41c2b871", + "hash": "sha256:ec31270001a6cd9d0a8ecb7974ad161d5c1ef4d3023d5a6af9fbc5a6ca46cbca", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-collectives-and-daos", - "title": "Collectives Chain", - "slug": "reference-polkadot-hub-collectives-and-daos", + "id": "parachains-runtime-maintenance-storage-migrations", + "title": "Storage Migrations", + "slug": "parachains-runtime-maintenance-storage-migrations", "categories": [ - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-collectives-and-daos.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/collectives-and-daos/", - "preview": "Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/", + "preview": "Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime", "outline": [ { "depth": 2, @@ -5331,29 +6108,69 @@ }, { "depth": 2, - "title": "Key Collectives", - "anchor": "key-collectives" + "title": "Storage Migration Scenarios", + "anchor": "storage-migration-scenarios" + }, + { + "depth": 2, + "title": "Implement Storage Migrations", + "anchor": "implement-storage-migrations" + }, + { + "depth": 3, + "title": "Core Migration Function", + "anchor": "core-migration-function" + }, + { + "depth": 3, + "title": "Migration Testing Hooks", + "anchor": "migration-testing-hooks" + }, + { + "depth": 3, + "title": "Migration Structure", + "anchor": "migration-structure" + }, + { + "depth": 3, + "title": "Migration Organization", + "anchor": "migration-organization" + }, + { + "depth": 3, + "title": "Scheduling Migrations", + "anchor": "scheduling-migrations" + }, + { + "depth": 2, + "title": "Single-Block Migrations", + "anchor": "single-block-migrations" + }, + { + "depth": 2, + "title": "Multi Block Migrations", + "anchor": "multi-block-migrations" } ], "stats": { - "chars": 2288, - "words": 293, - "headings": 2, - "estimated_token_count_total": 424 + "chars": 18500, + "words": 2363, + "headings": 10, + "estimated_token_count_total": 4014 }, - "hash": "sha256:59ec351fbb8d3a392e90f4f5bf6b62f58b21d6d7a900c5e367e5d2e09ecb3aca", + "hash": "sha256:55dc252fdecf1590048ce8d009b822e90231442abe81e9593cf1635944a31336", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-consensus-and-security-agile-coretime", - "title": "Agile Coretime", - "slug": "reference-polkadot-hub-consensus-and-security-agile-coretime", + "id": "parachains-runtime-maintenance-unlock-parachains", + "title": "Unlock a Parachain", + "slug": "parachains-runtime-maintenance-unlock-parachains", "categories": [ - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/agile-coretime/", - "preview": "Agile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-unlock-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/unlock-parachains/", + "preview": "Parachain locks are a critical security mechanism in the Polkadot ecosystem designed to maintain decentralization during the parachain lifecycle. These locks prevent potential centralization risks that could emerge during the early stages of parachain operation.", "outline": [ { "depth": 2, @@ -5362,44 +6179,50 @@ }, { "depth": 2, - "title": "Bulk Coretime", - "anchor": "bulk-coretime" + "title": "Check If the Parachain Is Locked", + "anchor": "check-if-the-parachain-is-locked" + }, + { + "depth": 2, + "title": "How to Unlock a Parachain", + "anchor": "how-to-unlock-a-parachain" }, { "depth": 3, - "title": "Coretime Interlacing", - "anchor": "coretime-interlacing" + "title": "Prepare the Unlock Call", + "anchor": "prepare-the-unlock-call" }, { "depth": 3, - "title": "Coretime Splitting", - "anchor": "coretime-splitting" + "title": "Fund the Sovereign Account", + "anchor": "fund-the-sovereign-account" }, { - "depth": 2, - "title": "On-Demand Coretime", - "anchor": "on-demand-coretime" + "depth": 3, + "title": "Craft and Submit the XCM", + "anchor": "craft-and-submit-the-xcm" } ], "stats": { - "chars": 3028, - "words": 452, - "headings": 5, - "estimated_token_count_total": 619 + "chars": 9232, + "words": 1276, + "headings": 6, + "estimated_token_count_total": 2028 }, - "hash": "sha256:00be43ac8d666bbe15c5c2fa5a5085697d0bb5a6f341ebbb943a209f0be355df", + "hash": "sha256:e408d05199cc184fc6fe8bb212efb3c9aa6cb79258977e07566692176c912def", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-consensus-and-security-pos-consensus", - "title": "Proof of Stake Consensus", - "slug": "reference-polkadot-hub-consensus-and-security-pos-consensus", + "id": "parachains-testing-fork-a-parachain", + "title": "Get Started", + "slug": "parachains-testing-fork-a-parachain", "categories": [ - "Polkadot Protocol" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/pos-consensus/", - "preview": "Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank} model and a com", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md", + "html_url": "https://docs.polkadot.com/parachains/testing/fork-a-parachain/", + "preview": "[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.", "outline": [ { "depth": 2, @@ -5408,86 +6231,70 @@ }, { "depth": 2, - "title": "Nominated Proof of Stake", - "anchor": "nominated-proof-of-stake" - }, - { - "depth": 2, - "title": "Hybrid Consensus", - "anchor": "hybrid-consensus" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Block Production - BABE", - "anchor": "block-production-babe" + "title": "Install Chopsticks", + "anchor": "install-chopsticks" }, { "depth": 3, - "title": "Validator Participation", - "anchor": "validator-participation" + "title": "Global Installation", + "anchor": "global-installation" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Local Installation", + "anchor": "local-installation" }, { "depth": 2, - "title": "Finality Gadget - GRANDPA", - "anchor": "finality-gadget-grandpa" + "title": "Configure Chopsticks", + "anchor": "configure-chopsticks" }, { "depth": 3, - "title": "Probabilistic vs. Provable Finality", - "anchor": "probabilistic-vs-provable-finality" + "title": "Configuration File", + "anchor": "configuration-file" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-2" + "title": "CLI Flags", + "anchor": "cli-flags" }, { "depth": 2, - "title": "Fork Choice", - "anchor": "fork-choice" - }, - { - "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-3" + "title": "WebSocket Commands", + "anchor": "websocket-commands" }, { "depth": 2, - "title": "Bridging - BEEFY", - "anchor": "bridging-beefy" - }, - { - "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-4" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 12753, - "words": 1834, - "headings": 13, - "estimated_token_count_total": 2526 + "chars": 10894, + "words": 1330, + "headings": 10, + "estimated_token_count_total": 2614 }, - "hash": "sha256:231fc555eefe5f910fb36e0c03945147d0fb235272850797391751f4444b0a9c", + "hash": "sha256:4325cdd697814b8043db808da3dee86d3d9c6fc7dd523aae7fe8914d59d1b39c", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-consensus-and-security-relay-chain", - "title": "Overview of the Polkadot Relay Chain", - "slug": "reference-polkadot-hub-consensus-and-security-relay-chain", + "id": "parachains-testing-run-a-parachain-network", + "title": "Get Started", + "slug": "parachains-testing-run-a-parachain-network", "categories": [ - "Basics", - "Polkadot Protocol", - "Parachains" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/", - "preview": "Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank}, and cross-chain int", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md", + "html_url": "https://docs.polkadot.com/parachains/testing/run-a-parachain-network/", + "preview": "Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.", "outline": [ { "depth": 2, @@ -5496,74 +6303,90 @@ }, { "depth": 2, - "title": "Polkadot 1.0", - "anchor": "polkadot-10" + "title": "Install Zombienet", + "anchor": "install-zombienet" }, { - "depth": 3, - "title": "High-Level Architecture", - "anchor": "high-level-architecture" + "depth": 2, + "title": "Providers", + "anchor": "providers" }, { "depth": 3, - "title": "Polkadot's Additional Functionalities", - "anchor": "polkadots-additional-functionalities" + "title": "Kubernetes", + "anchor": "kubernetes" }, { "depth": 3, - "title": "Polkadot's Resilience", - "anchor": "polkadots-resilience" + "title": "Podman", + "anchor": "podman" }, { "depth": 3, - "title": "Polkadot's Blockspace", - "anchor": "polkadots-blockspace" + "title": "Local Provider", + "anchor": "local-provider" }, { "depth": 2, - "title": "DOT Token", - "anchor": "dot-token" + "title": "Configure Zombienet", + "anchor": "configure-zombienet" }, { "depth": 3, - "title": "Redenomination of DOT", - "anchor": "redenomination-of-dot" + "title": "Configuration Files", + "anchor": "configuration-files" }, { "depth": 3, - "title": "The Planck Unit", - "anchor": "the-planck-unit" + "title": "CLI Usage", + "anchor": "cli-usage" }, { "depth": 3, - "title": "Uses for DOT", - "anchor": "uses-for-dot" + "title": "Settings", + "anchor": "settings" + }, + { + "depth": 3, + "title": "Relay Chain Configuration", + "anchor": "relay-chain-configuration" + }, + { + "depth": 3, + "title": "Parachain Configuration", + "anchor": "parachain-configuration" + }, + { + "depth": 3, + "title": "XCM Configuration", + "anchor": "xcm-configuration" }, { "depth": 2, - "title": "JAM and the Road Ahead", - "anchor": "jam-and-the-road-ahead" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 12458, - "words": 1774, - "headings": 11, - "estimated_token_count_total": 2580 + "chars": 41636, + "words": 4599, + "headings": 14, + "estimated_token_count_total": 9871 }, - "hash": "sha256:60f5ac9f67fb9f2188121219830538d334028b3b9e85d42bd1e7279043654e39", + "hash": "sha256:0d7e04fd952cc9d5bd8cdbfd87cc4004c5f95e896a16bc7f89dfc4caeac8f371", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-people-and-identity", - "title": "People Chain", - "slug": "reference-polkadot-hub-people-and-identity", + "id": "polkadot-protocol-architecture-parachains-consensus", + "title": "Parachain Consensus", + "slug": "polkadot-protocol-architecture-parachains-consensus", "categories": [ - "Polkadot Protocol" + "Polkadot Protocol", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-people-and-identity.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/people-and-identity/", - "preview": "People chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains-consensus.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/consensus/", + "preview": "Parachains are independent blockchains built with the Polkadot SDK, designed to leverage Polkadot’s relay chain for shared security and transaction finality. These specialized chains operate as part of Polkadot’s execution sharding model, where each parachain manages its own state and transactions while relying on the relay chain for validation and consensus.", "outline": [ { "depth": 2, @@ -5572,33 +6395,81 @@ }, { "depth": 2, - "title": "Identity Management System", - "anchor": "identity-management-system" + "title": "The Role of Collators", + "anchor": "the-role-of-collators" + }, + { + "depth": 2, + "title": "Consensus and Validation", + "anchor": "consensus-and-validation" }, { "depth": 3, - "title": "Sub-Identities", - "anchor": "sub-identities" + "title": "Path of a Parachain Block", + "anchor": "path-of-a-parachain-block" }, { "depth": 2, - "title": "Verification Process", - "anchor": "verification-process" + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 6150, + "words": 790, + "headings": 5, + "estimated_token_count_total": 1125 + }, + "hash": "sha256:9875239c6071033a37a0f67fabca5a6e840c4a287620309f47b4f29c5a95a1cb", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol-architecture-parachains-overview", + "title": "Overview", + "slug": "polkadot-protocol-architecture-parachains-overview", + "categories": [ + "Basics", + "Polkadot Protocol", + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains-overview.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/overview/", + "preview": "A [_parachain_](/polkadot-protocol/glossary#parachain){target=\\_blank} is a coherent, application-specific blockchain that derives security from its respective relay chain. Parachains on Polkadot are each their own separate, fully functioning blockchain. The primary difference between a parachain and a regular, \"solo\" blockchain is that the relay chain verifies the state of all parachains that are connected to it. In many ways, parachains can be thought of as a [\"cynical\" rollup](#cryptoeconomic", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Judgment Requests", - "anchor": "judgment-requests" + "depth": 2, + "title": "Coherent Systems", + "anchor": "coherent-systems" }, { - "depth": 3, - "title": "Judgment Classifications", - "anchor": "judgment-classifications" + "depth": 2, + "title": "Flexible Ecosystem", + "anchor": "flexible-ecosystem" + }, + { + "depth": 2, + "title": "State Transition Functions (Runtimes)", + "anchor": "state-transition-functions-runtimes" + }, + { + "depth": 2, + "title": "Shared Security: Validated by the Relay Chain", + "anchor": "shared-security-validated-by-the-relay-chain" }, { "depth": 3, - "title": "Registrars", - "anchor": "registrars" + "title": "Cryptoeconomic Security: ELVES Protocol", + "anchor": "cryptoeconomic-security-elves-protocol" + }, + { + "depth": 2, + "title": "Interoperability", + "anchor": "interoperability" }, { "depth": 2, @@ -5607,105 +6478,91 @@ } ], "stats": { - "chars": 4750, - "words": 606, + "chars": 9561, + "words": 1321, "headings": 8, - "estimated_token_count_total": 876 + "estimated_token_count_total": 1861 }, - "hash": "sha256:8239d1e8d8642cb7c10e9e5f971c99b999e9e4a87373b50bf4a691225c1e4702", + "hash": "sha256:932c12e1af939698279ede2eacb2190e1f56119582adf2064d6cf86f7a4f3e3c", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub", - "title": "reference-polkadot-hub", - "slug": "reference-polkadot-hub", + "id": "polkadot-protocol-architecture-parachains", + "title": "Parachains", + "slug": "polkadot-protocol-architecture-parachains", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/", - "preview": "TODO", - "outline": [], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/", + "preview": "Discover how parachains secure their networks and reach consensus by harnessing Polkadot’s relay chain and its robust validator framework. This integrated architecture ensures shared security and seamless coordination across the entire ecosystem.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 725, + "words": 93, + "headings": 1, + "estimated_token_count_total": 12 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:3b9160b166d9b42b124f3b07eb26bdc5499fbbace6f951095009a5eee7fccbb6", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-chopsticks", - "title": "reference-tools-chopsticks", - "slug": "reference-tools-chopsticks", + "id": "polkadot-protocol-architecture-polkadot-chain", + "title": "The Polkadot Relay Chain", + "slug": "polkadot-protocol-architecture-polkadot-chain", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md", - "html_url": "https://docs.polkadot.com/reference/tools/chopsticks/", - "preview": "TODO", - "outline": [], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-polkadot-chain.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/", + "preview": "Discover the central role of the Polkadot relay chain in securing the network and fostering interoperability. As the backbone of Polkadot, the relay chain provides shared security and ensures consensus across the ecosystem. It empowers parachains with flexible coretime allocation, enabling them to purchase blockspace on demand, ensuring efficiency and scalability for diverse blockchain applications.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 481, + "words": 63, + "headings": 1, + "estimated_token_count_total": 12 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:c29356358f095b0d413e4c6525146b3f1b0b900853aada2168e7e55cd8dd6641", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-dedot", - "title": "Dedot", - "slug": "reference-tools-dedot", + "id": "polkadot-protocol-architecture-system-chains-coretime", + "title": "Coretime Chain", + "slug": "polkadot-protocol-architecture-system-chains-coretime", "categories": [ - "Tooling", - "Dapps" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md", - "html_url": "https://docs.polkadot.com/reference/tools/dedot/", - "preview": "[Dedot](https://github.com/dedotdev/dedot){target=\\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\\_blank}.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-system-chains-coretime.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/system-chains/coretime/", + "preview": "The Coretime system chain facilitates the allocation, procurement, sale, and scheduling of bulk [coretime](/reference/glossary/#coretime){target=\\_blank}, enabling tasks (such as [parachains](/reference/glossary/#parachain){target=\\_blank}) to utilize the computation and security provided by Polkadot.", "outline": [ { "depth": 2, "title": "Introduction", "anchor": "introduction" }, - { - "depth": 3, - "title": "Key Features", - "anchor": "key-features" - }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Bulk Coretime Assignment", + "anchor": "bulk-coretime-assignment" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Initialize a Client Instance", - "anchor": "initialize-a-client-instance" - }, - { - "depth": 3, - "title": "Enable Type and API Suggestions", - "anchor": "enable-type-and-api-suggestions" - }, - { - "depth": 3, - "title": "Read On-Chain Data", - "anchor": "read-on-chain-data" - }, - { - "depth": 3, - "title": "Sign and Send Transactions", - "anchor": "sign-and-send-transactions" + "title": "On Demand Coretime", + "anchor": "on-demand-coretime" }, { "depth": 2, @@ -5714,25 +6571,25 @@ } ], "stats": { - "chars": 8855, - "words": 1100, - "headings": 9, - "estimated_token_count_total": 2300 + "chars": 5279, + "words": 772, + "headings": 4, + "estimated_token_count_total": 1230 }, - "hash": "sha256:ba24e31e2ad94fbf1d73f1878da92dd2e1476db00170780bbdf0e65ab18bc961", + "hash": "sha256:8d186fa56ccbbf4b6c85cffc5521b9a99a20e9517f3b4a435730745803cbf2e8", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-light-clients", - "title": "Light Clients", - "slug": "reference-tools-light-clients", + "id": "polkadot-protocol-architecture-system-chains-overview", + "title": "Overview of Polkadot's System Chains", + "slug": "polkadot-protocol-architecture-system-chains-overview", "categories": [ - "Parachains", - "Tooling" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md", - "html_url": "https://docs.polkadot.com/reference/tools/light-clients/", - "preview": "Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-system-chains-overview.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/system-chains/overview/", + "preview": "Polkadot's relay chain is designed to secure parachains and facilitate seamless inter-chain communication. However, resource-intensive—tasks like governance, asset management, and bridging are more efficiently handled by system parachains. These specialized chains offload functionality from the relay chain, leveraging Polkadot's parallel execution model to improve performance and scalability. By distributing key functionalities across system parachains, Polkadot can maximize its relay chain's bl", "outline": [ { "depth": 2, @@ -5741,122 +6598,205 @@ }, { "depth": 2, - "title": "Light Clients Workflow", - "anchor": "light-clients-workflow" + "title": "System Chains", + "anchor": "system-chains" }, { "depth": 2, - "title": "JSON-RPC and Light Client Comparison", - "anchor": "json-rpc-and-light-client-comparison" + "title": "Existing System Chains", + "anchor": "existing-system-chains" }, { - "depth": 2, - "title": "Using Light Clients", - "anchor": "using-light-clients" + "depth": 3, + "title": "Asset Hub", + "anchor": "asset-hub" }, { "depth": 3, - "title": "PAPI Light Client Support", - "anchor": "papi-light-client-support" + "title": "Collectives", + "anchor": "collectives" }, { "depth": 3, - "title": "Substrate Connect - Browser Extension", - "anchor": "substrate-connect-browser-extension" + "title": "Bridge Hub", + "anchor": "bridge-hub" }, { - "depth": 2, - "title": "Resources", - "anchor": "resources" + "depth": 3, + "title": "People Chain", + "anchor": "people-chain" + }, + { + "depth": 3, + "title": "Coretime Chain", + "anchor": "coretime-chain" + }, + { + "depth": 3, + "title": "Encointer", + "anchor": "encointer" } ], "stats": { - "chars": 6490, - "words": 870, - "headings": 7, - "estimated_token_count_total": 1430 + "chars": 7727, + "words": 1105, + "headings": 9, + "estimated_token_count_total": 1643 }, - "hash": "sha256:1284c42be692167e01bcc44e2e134ec20615402675fac26df246c00aa1588d80", + "hash": "sha256:100377787627052a29bd1173270b5ad307639b828c331e71c85d4c00bc5692d8", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-moonwall", - "title": "E2E Testing with Moonwall", - "slug": "reference-tools-moonwall", + "id": "polkadot-protocol-architecture-system-chains", + "title": "System Chains", + "slug": "polkadot-protocol-architecture-system-chains", "categories": [ - "Parachains", - "Tooling" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md", - "html_url": "https://docs.polkadot.com/reference/tools/moonwall/", - "preview": "Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-system-chains.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/system-chains/", + "preview": "Explore the critical roles Polkadot’s system chains play in enhancing the network’s efficiency and scalability. From managing on-chain assets with the Asset Hub to enabling seamless Web3 integration through the Bridge Hub and facilitating coretime operations with the Coretime chain, each system chain is designed to offload specialized tasks from the relay chain, optimizing the entire ecosystem.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 929, + "words": 124, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:6ef13c197dd1865fcc1a405d67486f1d053534d576bb32fe47a442fd2c11b6cd", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol-architecture", + "title": "Architecture", + "slug": "polkadot-protocol-architecture", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/", + "preview": "Explore Polkadot's architecture, including the relay chain, parachains, and system chains, and discover the role each component plays in the broader ecosystem.", + "outline": [ { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "A Brief Look at Polkadot’s Chain Ecosystem", + "anchor": "a-brief-look-at-polkadots-chain-ecosystem" }, { "depth": 2, - "title": "Install Moonwall", - "anchor": "install-moonwall" - }, - { - "depth": 3, - "title": "Global Installation", - "anchor": "global-installation" - }, - { - "depth": 3, - "title": "Local Installation", - "anchor": "local-installation" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 990, + "words": 132, + "headings": 2, + "estimated_token_count_total": 177 + }, + "hash": "sha256:ffda04c93c70ec7204be28b642fa6e51f6bf9436d4792ecd25136696683f0902", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol-onchain-governance", + "title": "On-Chain Governance", + "slug": "polkadot-protocol-onchain-governance", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-onchain-governance.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/onchain-governance/", + "preview": "Polkadot's on-chain governance system, OpenGov, enables decentralized decision-making across the network. It empowers stakeholders to propose, vote on, and enact changes with transparency and efficiency. This system ensures that governance is both flexible and inclusive, allowing developers to integrate custom governance solutions and mechanisms within the network. Understanding how OpenGov functions is crucial for anyone looking to engage with Polkadot’s decentralized ecosystem, whether you’re", + "outline": [ { "depth": 2, - "title": "Initialize Moonwall", - "anchor": "initialize-moonwall" + "title": "Start Building Governance Solutions", + "anchor": "start-building-governance-solutions" }, { "depth": 2, - "title": "Writing Tests", - "anchor": "writing-tests" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 2114, + "words": 285, + "headings": 2, + "estimated_token_count_total": 233 + }, + "hash": "sha256:58fd5c8c092ee748c2979164f985a67071a6ccb88492e79cdad536363364c858", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol-parachain-basics-blocks-transactions-fees", + "title": "Blocks, Transactions, and Fees", + "slug": "polkadot-protocol-parachain-basics-blocks-transactions-fees", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-blocks-transactions-fees.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/blocks-transactions-fees/", + "preview": "Discover the inner workings of Polkadot’s blocks and transactions, including their structure, processing, and lifecycle within the network. Learn how blocks are authored, validated, and finalized, ensuring seamless operation and consensus across the ecosystem. Dive into the various types of transactions—signed, unsigned, and inherent—and understand how they are constructed, submitted, and validated.", + "outline": [ { "depth": 2, - "title": "Running the Tests", - "anchor": "running-the-tests" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 788, + "words": 105, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:235f33cdb64494815dbb3eb58ea98c69935098684e1b34b6d15356bc54b082ea", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol-parachain-basics", + "title": "Parachain Basics", + "slug": "polkadot-protocol-parachain-basics", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/", + "preview": "This section equips developers with the essential knowledge to create, deploy, and enhance applications and blockchains within the Polkadot ecosystem. Gain a comprehensive understanding of Polkadot’s foundational components, including accounts, balances, and transactions, as well as advanced topics like data encoding and cryptographic methods. Mastering these concepts is vital for building robust and secure applications on Polkadot.", + "outline": [ { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 10240, - "words": 1295, - "headings": 9, - "estimated_token_count_total": 2453 + "chars": 998, + "words": 130, + "headings": 1, + "estimated_token_count_total": 12 }, - "hash": "sha256:2c77cfb38bb2e466a8f56dabbb706fcd2e90cf1634fc9beb7f0ee95a75735653", + "hash": "sha256:1514316acba1e9bba82ae1c82b09481e9d03d286e6f5d93b66e5a85fd4be7bca", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-omninode", - "title": "Polkadot Omni Node", - "slug": "reference-tools-omninode", + "id": "polkadot-protocol-smart-contract-basics-evm-vs-polkavm", + "title": "EVM vs PolkaVM", + "slug": "polkadot-protocol-smart-contract-basics-evm-vs-polkavm", "categories": [ - "Parachains", - "Tooling" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md", - "html_url": "https://docs.polkadot.com/reference/tools/omninode/", - "preview": "The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\\_blank} file, allowing it to adapt dynamically to different parachains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-evm-vs-polkavm.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -5865,116 +6805,110 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Core Virtual Machine Architecture", + "anchor": "core-virtual-machine-architecture" }, { - "depth": 2, - "title": "Install Polkadot Omni Node", - "anchor": "install-polkadot-omni-node" + "depth": 3, + "title": "High-Level Architecture Comparison", + "anchor": "high-level-architecture-comparison" }, { "depth": 2, - "title": "Obtain Chain Specifications", - "anchor": "obtain-chain-specifications" + "title": "Gas Model", + "anchor": "gas-model" }, { - "depth": 2, - "title": "Run a Parachain Full Node", - "anchor": "run-a-parachain-full-node" + "depth": 3, + "title": "Dynamic Gas Value Scaling", + "anchor": "dynamic-gas-value-scaling" }, { - "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" + "depth": 3, + "title": "Multi-Dimensional Resource Metering", + "anchor": "multi-dimensional-resource-metering" }, { "depth": 2, - "title": "Parachain Compatibility", - "anchor": "parachain-compatibility" + "title": "Memory Management", + "anchor": "memory-management" }, { "depth": 3, - "title": "Required Runtime APIs", - "anchor": "required-runtime-apis" + "title": "Current Memory Limits", + "anchor": "current-memory-limits" + }, + { + "depth": 2, + "title": "Account Management - Existential Deposit", + "anchor": "account-management-existential-deposit" }, { "depth": 3, - "title": "Required Pallets", - "anchor": "required-pallets" - } - ], - "stats": { - "chars": 8913, - "words": 1164, - "headings": 9, - "estimated_token_count_total": 2017 - }, - "hash": "sha256:7db2d31ba37abad20b026c875f632b89739b45707e58809e2e8b32a09715c6f9", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-papi", - "title": "Polkadot-API", - "slug": "reference-tools-papi", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md", - "html_url": "https://docs.polkadot.com/reference/tools/papi/", - "preview": "[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications.", - "outline": [ + "title": "Account Management Comparison", + "anchor": "account-management-comparison" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Contract Deployment", + "anchor": "contract-deployment" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Solidity and YUL IR Translation Incompatibilities", + "anchor": "solidity-and-yul-ir-translation-incompatibilities" }, { "depth": 3, - "title": "API Instantiation", - "anchor": "api-instantiation" + "title": "Contract Code Structure", + "anchor": "contract-code-structure" }, { "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "title": "Solidity-Specific Differences", + "anchor": "solidity-specific-differences" }, { "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" + "title": "YUL Function Translation Differences", + "anchor": "yul-function-translation-differences" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Unsupported Operations", + "anchor": "unsupported-operations" + }, + { + "depth": 3, + "title": "Compilation Pipeline Considerations", + "anchor": "compilation-pipeline-considerations" + }, + { + "depth": 3, + "title": "Memory Pointer Limitations", + "anchor": "memory-pointer-limitations" } ], "stats": { - "chars": 8957, - "words": 1156, - "headings": 6, - "estimated_token_count_total": 1987 + "chars": 27673, + "words": 3392, + "headings": 18, + "estimated_token_count_total": 5305 }, - "hash": "sha256:2ca93b09d3bb9159bbf53816886a9b242bb3c13b996c51fd52962e049e2d5477", + "hash": "sha256:fe651be49fe0a9ae899b2cbf9c663325f407718dc63f1d2c6a2dc4931be751fa", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-paraspell", - "title": "ParaSpell XCM SDK", - "slug": "reference-tools-paraspell", + "id": "polkadot-protocol-smart-contract-basics-networks", + "title": "Networks for Polkadot Hub Smart Contracts", + "slug": "polkadot-protocol-smart-contract-basics-networks", "categories": [ - "Uncategorized" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md", - "html_url": "https://docs.polkadot.com/reference/tools/paraspell/", - "preview": "[ParaSpell](https://paraspell.github.io/docs/){target=\\_blank} is a comprehensive suite of open-source tools designed to simplify cross-chain interactions within the Polkadot ecosystem. At its core, ParaSpell is dedicated to enhancing the functionality of the [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} protocol by providing developers with a unified and streamlined experience for building interoperable decentralized applications (dApps).", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-networks.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/networks/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -5982,665 +6916,552 @@ "anchor": "introduction" }, { - "depth": 3, - "title": "ParaSpell XCM SDK", - "anchor": "paraspell-xcm-sdk" + "depth": 2, + "title": "Network Overview", + "anchor": "network-overview" }, { "depth": 2, - "title": "Install ParaSpell", - "anchor": "install-paraspell" + "title": "Local Development", + "anchor": "local-development" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Test Networks", + "anchor": "test-networks" + }, + { + "depth": 3, + "title": "Passet Hub", + "anchor": "passet-hub" + }, + { + "depth": 3, + "title": "Westend Hub", + "anchor": "westend-hub" + }, + { + "depth": 2, + "title": "Production Networks", + "anchor": "production-networks" + }, + { + "depth": 3, + "title": "Polkadot Hub", + "anchor": "polkadot-hub" + }, + { + "depth": 3, + "title": "Kusama Hub", + "anchor": "kusama-hub" } ], "stats": { - "chars": 4043, - "words": 562, - "headings": 4, - "estimated_token_count_total": 888 + "chars": 5108, + "words": 696, + "headings": 9, + "estimated_token_count_total": 891 }, - "hash": "sha256:c8741954ea656680aa3322c825e3f6acbaac369baaa42232b06af9e5e482f74f", + "hash": "sha256:b5acdc9acf0e44836b8a4518155eba7d16cc3b103c557a00970ffb1c44c3e9f6", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-polkadart", - "title": "Polkadart", - "slug": "reference-tools-polkadart", + "id": "polkadot-protocol-smart-contract-basics-overview", + "title": "Smart Contracts Basics Overview", + "slug": "polkadot-protocol-smart-contract-basics-overview", "categories": [ - "Tooling", - "Dapps" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md", - "html_url": "https://docs.polkadot.com/reference/tools/polkadart/", - "preview": "Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-overview.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/overview/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Type Generation", - "anchor": "type-generation" - }, - { - "depth": 3, - "title": "Run Generator", - "anchor": "run-generator" - }, - { - "depth": 3, - "title": "Use Generated Types", - "anchor": "use-generated-types" + "title": "Smart Contracts Versus Parachains", + "anchor": "smart-contracts-versus-parachains" }, { - "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" + "depth": 2, + "title": "Building a Smart Contract", + "anchor": "building-a-smart-contract" }, { "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "title": "PolkaVM Contracts", + "anchor": "polkavm-contracts" }, { "depth": 3, - "title": "Subscribe to New Blocks", - "anchor": "subscribe-to-new-blocks" + "title": "EVM Contracts", + "anchor": "evm-contracts" }, { "depth": 3, - "title": "Send a Transaction", - "anchor": "send-a-transaction" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Wasm Contracts", + "anchor": "wasm-contracts" } ], "stats": { - "chars": 5178, - "words": 624, - "headings": 10, - "estimated_token_count_total": 1084 + "chars": 10854, + "words": 1559, + "headings": 6, + "estimated_token_count_total": 2550 }, - "hash": "sha256:7f533abe61586af8438e350c41b741d74a8edb839f9dc4139bc4619ba3748258", + "hash": "sha256:5d293525ce81d27e32c26938a029a6a82b137221a0630d084f528853ffaf798e", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-polkadot-js-api", - "title": "Polkadot.js API", - "slug": "reference-tools-polkadot-js-api", + "id": "polkadot-protocol-smart-contract-basics", + "title": "Smart Contract Basics", + "slug": "polkadot-protocol-smart-contract-basics", "categories": [ - "Tooling", - "Dapps" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md", - "html_url": "https://docs.polkadot.com/reference/tools/polkadot-js-api/", - "preview": "!!! warning \"Maintenance Mode Only\" The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank} (modern, type-safe API) as actively maintained alternatives.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Gain a deep understanding of smart contracts on Polkadot, from execution environments to transaction mechanics.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Key Topics", + "anchor": "key-topics" }, { - "depth": 3, - "title": "Dynamic API Generation", - "anchor": "dynamic-api-generation" + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 1110, + "words": 136, + "headings": 2, + "estimated_token_count_total": 148 + }, + "hash": "sha256:e8dac01e89b7aac4b887e962e91084c253f5ea25c1abc3a56355390d0c3201c8", + "token_estimator": "heuristic-v1" + }, + { + "id": "polkadot-protocol", + "title": "Learn About the Polkadot Protocol", + "slug": "polkadot-protocol", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol.md", + "html_url": "https://docs.polkadot.com/polkadot-protocol/", + "preview": "The Polkadot protocol is designed to enable scalable, secure, and interoperable networks. It introduces a unique multichain architecture that allows independent blockchains, known as parachains, to operate seamlessly while benefiting from the shared security of the relay chain. Polkadot’s decentralized governance ensures that network upgrades and decisions are community-driven, while its cross-chain messaging and interoperability features make it a hub for multichain applications.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 1170, + "words": 150, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:49be4b4b5289572086eaaaf9ccff3bee7879b534188331c9a8052b3fe5aa4933", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-glossary", + "title": "Glossary", + "slug": "reference-glossary", + "categories": [ + "Reference" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md", + "html_url": "https://docs.polkadot.com/reference/glossary/", + "preview": "Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here.", + "outline": [ + { + "depth": 2, + "title": "Authority", + "anchor": "authority" }, { - "depth": 3, - "title": "Available API Categories", - "anchor": "available-api-categories" + "depth": 2, + "title": "Authority Round (Aura)", + "anchor": "authority-round-aura" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Blind Assignment of Blockchain Extension (BABE)", + "anchor": "blind-assignment-of-blockchain-extension-babe" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Block Author", + "anchor": "block-author" + }, + { + "depth": 2, + "title": "Byzantine Fault Tolerance (BFT)", + "anchor": "byzantine-fault-tolerance-bft" }, { "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" + "title": "Byzantine Failure", + "anchor": "byzantine-failure" }, { "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "title": "Practical Byzantine Fault Tolerance (pBFT)", + "anchor": "practical-byzantine-fault-tolerance-pbft" }, { "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" + "title": "Preimage", + "anchor": "preimage" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 5042, - "words": 684, - "headings": 9, - "estimated_token_count_total": 1166 - }, - "hash": "sha256:ed3986f30880fefca5975fcdc847c68b4aca65862c63e3002b25391b0521781d", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-py-substrate-interface", - "title": "Python Substrate Interface", - "slug": "reference-tools-py-substrate-interface", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md", - "html_url": "https://docs.polkadot.com/reference/tools/py-substrate-interface/", - "preview": "The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for:", - "outline": [ + "title": "Call", + "anchor": "call" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Chain Specification", + "anchor": "chain-specification" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Collator", + "anchor": "collator" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Collective", + "anchor": "collective" }, { - "depth": 3, - "title": "Establishing Connection", - "anchor": "establishing-connection" + "depth": 2, + "title": "Consensus", + "anchor": "consensus" }, { - "depth": 3, - "title": "Reading Chain State", - "anchor": "reading-chain-state" + "depth": 2, + "title": "Consensus Algorithm", + "anchor": "consensus-algorithm" }, { - "depth": 3, - "title": "Submitting Transactions", - "anchor": "submitting-transactions" + "depth": 2, + "title": "Consensus Engine", + "anchor": "consensus-engine" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4302, - "words": 541, - "headings": 7, - "estimated_token_count_total": 942 - }, - "hash": "sha256:8987fc35cd28602054ee018031f773e2e3837425107c51d0e2ac68a94b86e9c0", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-sidecar", - "title": "Sidecar REST API", - "slug": "reference-tools-sidecar", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md", - "html_url": "https://docs.polkadot.com/reference/tools/sidecar/", - "preview": "The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more.", - "outline": [ + "title": "Coretime", + "anchor": "coretime" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Development Phrase", + "anchor": "development-phrase" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Digest", + "anchor": "digest" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Dispatchable", + "anchor": "dispatchable" }, { "depth": 2, - "title": "Usage", - "anchor": "usage" + "title": "Events", + "anchor": "events" }, { - "depth": 3, - "title": "Endpoints", - "anchor": "endpoints" + "depth": 2, + "title": "Executor", + "anchor": "executor" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 7309, - "words": 1033, - "headings": 6, - "estimated_token_count_total": 1945 - }, - "hash": "sha256:0795462182cb97256bb5c2acb035855fe0d6557185de8ac99482725ecb4f94c1", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-subxt", - "title": "Subxt Rust API", - "slug": "reference-tools-subxt", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md", - "html_url": "https://docs.polkadot.com/reference/tools/subxt/", - "preview": "Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability.", - "outline": [ + "title": "Existential Deposit", + "anchor": "existential-deposit" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Extrinsic", + "anchor": "extrinsic" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Fork Choice Rule/Strategy", + "anchor": "fork-choice-rulestrategy" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "FRAME (Framework for Runtime Aggregation of Modularized Entities)", + "anchor": "frame-framework-for-runtime-aggregation-of-modularized-entities" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Full Node", + "anchor": "full-node" }, { - "depth": 3, - "title": "Download Chain Metadata", - "anchor": "download-chain-metadata" + "depth": 2, + "title": "Genesis Configuration", + "anchor": "genesis-configuration" }, { - "depth": 3, - "title": "Generate Type-Safe Interfaces", - "anchor": "generate-type-safe-interfaces" + "depth": 2, + "title": "GRANDPA", + "anchor": "grandpa" }, { - "depth": 3, - "title": "Initialize the Subxt Client", - "anchor": "initialize-the-subxt-client" + "depth": 2, + "title": "Header", + "anchor": "header" }, { - "depth": 3, - "title": "Read Chain Data", - "anchor": "read-chain-data" + "depth": 2, + "title": "Hybrid Consensus", + "anchor": "hybrid-consensus" }, { - "depth": 3, - "title": "Submit Transactions", - "anchor": "submit-transactions" + "depth": 2, + "title": "Inherent Transactions", + "anchor": "inherent-transactions" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 9174, - "words": 1175, - "headings": 10, - "estimated_token_count_total": 2187 - }, - "hash": "sha256:56269d9ea47f5b4e92cd7d5a1e65ab06d181a9c380f90bb3ef285529b12299f7", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-xcm-tools", - "title": "XCM Tools", - "slug": "reference-tools-xcm-tools", - "categories": [ - "Basics", - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md", - "html_url": "https://docs.polkadot.com/reference/tools/xcm-tools/", - "preview": "As described in the [Interoperability](/develop/interoperability){target=\\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "JSON-RPC", + "anchor": "json-rpc" }, { "depth": 2, - "title": "Popular XCM Tools", - "anchor": "popular-xcm-tools" - }, - { - "depth": 3, - "title": "Moonsong Labs XCM Tools", - "anchor": "moonsong-labs-xcm-tools" - }, - { - "depth": 3, - "title": "ParaSpell", - "anchor": "paraspell" + "title": "Keystore", + "anchor": "keystore" }, { - "depth": 3, - "title": "Astar XCM Tools", - "anchor": "astar-xcm-tools" + "depth": 2, + "title": "Kusama", + "anchor": "kusama" }, { - "depth": 3, - "title": "Chopsticks", - "anchor": "chopsticks" + "depth": 2, + "title": "libp2p", + "anchor": "libp2p" }, - { - "depth": 3, - "title": "Moonbeam XCM SDK", - "anchor": "moonbeam-xcm-sdk" - } - ], - "stats": { - "chars": 6146, - "words": 852, - "headings": 7, - "estimated_token_count_total": 1377 - }, - "hash": "sha256:674e4f60c82fc7544c7af8e09f1e0f677c9907cdff88b107f6c8489e97a43487", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-zombienet", - "title": "reference-tools-zombienet", - "slug": "reference-tools-zombienet", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md", - "html_url": "https://docs.polkadot.com/reference/tools/zombienet/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference", - "title": "Technical Reference Overview", - "slug": "reference", - "categories": [ - "Basics", - "Polkadot Protocol", - "Reference" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md", - "html_url": "https://docs.polkadot.com/reference/", - "preview": "The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need.", - "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Light Client", + "anchor": "light-client" }, { "depth": 2, - "title": "Polkadot Hub", - "anchor": "polkadot-hub" + "title": "Metadata", + "anchor": "metadata" }, { "depth": 2, - "title": "Parachains", - "anchor": "parachains" + "title": "Nominated Proof of Stake (NPoS)", + "anchor": "nominated-proof-of-stake-npos" }, { "depth": 2, - "title": "On-Chain Governance", - "anchor": "on-chain-governance" + "title": "Oracle", + "anchor": "oracle" }, { "depth": 2, - "title": "Glossary", - "anchor": "glossary" + "title": "Origin", + "anchor": "origin" }, { "depth": 2, - "title": "Tools", - "anchor": "tools" + "title": "Pallet", + "anchor": "pallet" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 7648, - "words": 937, - "headings": 7, - "estimated_token_count_total": 1682 - }, - "hash": "sha256:9f71f3b4018f7a9e127cff51fab7cfe1168adcde2553cd1fc5dc8c25fb97a30d", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-connect", - "title": "Connect to Polkadot", - "slug": "smart-contracts-connect", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-connect.md", - "html_url": "https://docs.polkadot.com/smart-contracts/connect/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", - "outline": [ + "title": "Parachain", + "anchor": "parachain" + }, { "depth": 2, - "title": "Networks Details", - "anchor": "networks-details" + "title": "Paseo", + "anchor": "paseo" }, { "depth": 2, - "title": "Test Tokens", - "anchor": "test-tokens" + "title": "Polkadot", + "anchor": "polkadot" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 3459, - "words": 476, - "headings": 3, - "estimated_token_count_total": 558 - }, - "hash": "sha256:a2490223926957381913ae0ed22e2df3611a6713ec9d77a3015d1cd6a578b3f6", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-dapps-zero-to-hero", - "title": "Zero to Hero Smart Contract DApp", - "slug": "smart-contracts-cookbook-dapps-zero-to-hero", - "categories": [ - "dApp", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/dapps/zero-to-hero/", - "preview": "Decentralized applications (dApps) are a key component of the Web3 ecosystem, enabling developers to build applications that communicate directly with blockchain networks. Polkadot Hub, a blockchain with smart contract support, serves as a robust platform for deploying and interacting with dApps.", - "outline": [ + "title": "Polkadot Cloud", + "anchor": "polkadot-cloud" + }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Polkadot Hub", + "anchor": "polkadot-hub" }, { "depth": 2, - "title": "Project Overview", - "anchor": "project-overview" + "title": "PolkaVM", + "anchor": "polkavm" }, { "depth": 2, - "title": "Create and Deploy the Storage Contract", - "anchor": "create-and-deploy-the-storage-contract" + "title": "Relay Chain", + "anchor": "relay-chain" }, { - "depth": 3, - "title": "Set Up Hardhat Project", - "anchor": "set-up-hardhat-project" + "depth": 2, + "title": "Rococo", + "anchor": "rococo" }, { - "depth": 3, - "title": "Create the Storage Contract", - "anchor": "create-the-storage-contract" + "depth": 2, + "title": "Runtime", + "anchor": "runtime" }, { - "depth": 3, - "title": "Configure Hardhat for Polkadot Hub", - "anchor": "configure-hardhat-for-polkadot-hub" + "depth": 2, + "title": "Slot", + "anchor": "slot" }, { - "depth": 3, - "title": "Compile the Contract", - "anchor": "compile-the-contract" + "depth": 2, + "title": "Sovereign Account", + "anchor": "sovereign-account" }, { - "depth": 3, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" + "depth": 2, + "title": "SS58 Address Format", + "anchor": "ss58-address-format" }, { - "depth": 3, - "title": "Export the Contract ABI", - "anchor": "export-the-contract-abi" + "depth": 2, + "title": "State Transition Function (STF)", + "anchor": "state-transition-function-stf" }, { "depth": 2, - "title": "Set Up the dApp Project", - "anchor": "set-up-the-dapp-project" + "title": "Storage Item", + "anchor": "storage-item" }, { "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" + "title": "Substrate", + "anchor": "substrate" }, { "depth": 2, - "title": "Connect to Polkadot Hub", - "anchor": "connect-to-polkadot-hub" + "title": "Transaction", + "anchor": "transaction" }, { "depth": 2, - "title": "Set Up the Smart Contract Interface", - "anchor": "set-up-the-smart-contract-interface" + "title": "Transaction Era", + "anchor": "transaction-era" }, { "depth": 2, - "title": "Create the Wallet Connection Component", - "anchor": "create-the-wallet-connection-component" + "title": "Trie (Patricia Merkle Tree)", + "anchor": "trie-patricia-merkle-tree" }, { "depth": 2, - "title": "Create the Read Contract Component", - "anchor": "create-the-read-contract-component" + "title": "Validator", + "anchor": "validator" }, { "depth": 2, - "title": "Create the Write Contract Component", - "anchor": "create-the-write-contract-component" + "title": "WebAssembly (Wasm)", + "anchor": "webassembly-wasm" }, { "depth": 2, - "title": "How It Works", - "anchor": "how-it-works" + "title": "Weight", + "anchor": "weight" }, { - "depth": 3, - "title": "Wallet Connection", - "anchor": "wallet-connection" - }, + "depth": 2, + "title": "Westend", + "anchor": "westend" + } + ], + "stats": { + "chars": 24739, + "words": 3626, + "headings": 63, + "estimated_token_count_total": 5273 + }, + "hash": "sha256:40bd67811e7eabc79ca5d105eae388b19380d9f035022da17fc0d6bb173c817c", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-governance-origins-tracks", + "title": "Origins and Tracks", + "slug": "reference-governance-origins-tracks", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance-origins-tracks.md", + "html_url": "https://docs.polkadot.com/reference/governance/origins-tracks/", + "preview": "Polkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency.", + "outline": [ { - "depth": 3, - "title": "Data Reads", - "anchor": "data-reads" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Data Writes", - "anchor": "data-writes" + "depth": 2, + "title": "Origins", + "anchor": "origins" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Tracks", + "anchor": "tracks" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 31207, - "words": 3688, - "headings": 22, - "estimated_token_count_total": 6967 + "chars": 3333, + "words": 469, + "headings": 4, + "estimated_token_count_total": 631 }, - "hash": "sha256:b200f93a9179f0b2588ba722dd4c118536136faf3c39eabccf4abf5c346f78a8", + "hash": "sha256:baba9dd41091b792d09005d55d3df0bf65b35f42b40ebe63caf425a0978a22b0", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-eth-dapps-uniswap-v2", - "title": "Deploying Uniswap V2 on Polkadot", - "slug": "smart-contracts-cookbook-eth-dapps-uniswap-v2", + "id": "reference-governance", + "title": "On-Chain Governance Overview", + "slug": "reference-governance", "categories": [ - "dApps", - "Tooling" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md", + "html_url": "https://docs.polkadot.com/reference/governance/", + "preview": "Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model.", "outline": [ { "depth": 2, @@ -6649,54 +7470,65 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Governance Evolution", + "anchor": "governance-evolution" }, { "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" + "title": "OpenGov Key Features", + "anchor": "opengov-key-features" }, { "depth": 2, - "title": "Understanding Uniswap V2 Architecture", - "anchor": "understanding-uniswap-v2-architecture" + "title": "Origins and Tracks", + "anchor": "origins-and-tracks" }, { "depth": 2, - "title": "Test the Contracts", - "anchor": "test-the-contracts" + "title": "Referendums", + "anchor": "referendums" }, { - "depth": 2, - "title": "Deploy the Contracts", - "anchor": "deploy-the-contracts" + "depth": 3, + "title": "Vote on Referendums", + "anchor": "vote-on-referendums" + }, + { + "depth": 3, + "title": "Delegate Voting Power", + "anchor": "delegate-voting-power" + }, + { + "depth": 3, + "title": "Cancel a Referendum", + "anchor": "cancel-a-referendum" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 11280, - "words": 1560, - "headings": 7, - "estimated_token_count_total": 2671 + "chars": 7493, + "words": 1019, + "headings": 9, + "estimated_token_count_total": 1611 }, - "hash": "sha256:2a42198668c759f63aa602115bf2d290ec7d03bbc3a3df20e30e85027e1b1cc3", + "hash": "sha256:62beec261e72529f70e07a641177d489d2c8872f9c9d618cbadf1ac0fd881986", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", - "title": "Deploy a Basic Contract to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", + "id": "reference-parachains-accounts", + "title": "Polkadot SDK Accounts", + "slug": "reference-parachains-accounts", "categories": [ - "Smart Contracts" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/.deploy-basic-pvm/", - "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md", + "html_url": "https://docs.polkadot.com/reference/parachains/accounts/", + "preview": "Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains.", "outline": [ { "depth": 2, @@ -6705,261 +7537,254 @@ }, { "depth": 2, - "title": "JavaScript with Ethers.js", - "anchor": "javascript-with-ethersjs" + "title": "Account Data Structure", + "anchor": "account-data-structure" }, { "depth": 3, - "title": "Setup", - "anchor": "setup" + "title": "Account", + "anchor": "account" }, { "depth": 3, - "title": "Create and Compile Your Contract", - "anchor": "create-and-compile-your-contract" + "title": "Account Info", + "anchor": "account-info" }, { "depth": 3, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" + "title": "Account Reference Counters", + "anchor": "account-reference-counters" }, { "depth": 2, - "title": "Remix IDE", - "anchor": "remix-ide" + "title": "Account Balance Types", + "anchor": "account-balance-types" }, { "depth": 3, - "title": "Access Remix", - "anchor": "access-remix" + "title": "Balance Types", + "anchor": "balance-types" }, { "depth": 3, - "title": "Compile", - "anchor": "compile" + "title": "Locks", + "anchor": "locks" }, { "depth": 3, - "title": "Deploy", - "anchor": "deploy" + "title": "Balance Types on Polkadot.js", + "anchor": "balance-types-on-polkadotjs" }, { "depth": 2, - "title": "Hardhat", - "anchor": "hardhat" + "title": "Address Formats", + "anchor": "address-formats" }, { "depth": 3, - "title": "Setup", - "anchor": "setup-2" + "title": "Basic Format", + "anchor": "basic-format" }, { "depth": 3, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" + "title": "Address Type", + "anchor": "address-type" }, { "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract" + "title": "Address Length", + "anchor": "address-length" }, { "depth": 3, - "title": "Compile", - "anchor": "compile-2" + "title": "Checksum Types", + "anchor": "checksum-types" }, { "depth": 3, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" - }, + "title": "Validating Addresses", + "anchor": "validating-addresses" + } + ], + "stats": { + "chars": 29604, + "words": 4194, + "headings": 15, + "estimated_token_count_total": 6507 + }, + "hash": "sha256:0104a9132a69345a2faac37fca0e2853a2ded1efb009511a83a98d44509ab887", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-blocks-transactions-fees-blocks", + "title": "Blocks", + "slug": "reference-parachains-blocks-transactions-fees-blocks", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md", + "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/", + "preview": "In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the", + "outline": [ { - "depth": 3, - "title": "Deploy", - "anchor": "deploy-2" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Foundry", - "anchor": "foundry" + "title": "What is a Block?", + "anchor": "what-is-a-block" }, { - "depth": 3, - "title": "Setup", - "anchor": "setup-3" + "depth": 2, + "title": "Block Production", + "anchor": "block-production" }, { "depth": 3, - "title": "Configure Foundry", - "anchor": "configure-foundry" + "title": "Initialize Block", + "anchor": "initialize-block" }, { "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract-2" + "title": "Finalize Block", + "anchor": "finalize-block" }, { - "depth": 3, - "title": "Compile", - "anchor": "compile-3" + "depth": 2, + "title": "Block Authoring and Import", + "anchor": "block-authoring-and-import" }, { "depth": 3, - "title": "Deploy", - "anchor": "deploy-3" + "title": "Block Import Queue", + "anchor": "block-import-queue" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 13872, - "words": 1640, - "headings": 24, - "estimated_token_count_total": 3228 + "chars": 6252, + "words": 910, + "headings": 8, + "estimated_token_count_total": 1395 }, - "hash": "sha256:8f29b0f0b56f8c136206211a858cdc5bc27bcd9119eab179a6cd306182d910cb", + "hash": "sha256:424783c102bea5dae5b8749635858c6c59055563442a98f57521f0027dafa8d3", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry", - "title": "Deploy a Basic Contract with Foundry", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry", + "id": "reference-parachains-blocks-transactions-fees-fees", + "title": "Transactions Weights and Fees", + "slug": "reference-parachains-blocks-transactions-fees-fees", "categories": [ - "Smart Contracts" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/.foundry/", - "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Foundry](https://getfoundry.sh/){target=\\_blank}, which offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md", + "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/", + "preview": "When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop th", "outline": [ { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Introductions", + "anchor": "introductions" }, { "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" + "title": "How Fees are Calculated", + "anchor": "how-fees-are-calculated" }, { "depth": 2, - "title": "Configure Foundry", - "anchor": "configure-foundry" + "title": "Using the Transaction Payment Pallet", + "anchor": "using-the-transaction-payment-pallet" }, { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" + "depth": 3, + "title": "Understanding the Inclusion Fee", + "anchor": "understanding-the-inclusion-fee" }, { - "depth": 2, - "title": "Compile", - "anchor": "compile" + "depth": 3, + "title": "Accounts with an Insufficient Balance", + "anchor": "accounts-with-an-insufficient-balance" }, { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" + "depth": 3, + "title": "Fee Multipliers", + "anchor": "fee-multipliers" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 2731, - "words": 355, - "headings": 7, - "estimated_token_count_total": 598 - }, - "hash": "sha256:63defd84f302f0778c90129abbe69ecd2a5d9d83c622f2b7e5c2ffc9bcb3312f", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", - "title": "Deploy a Basic Contract with Hardhat", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/", - "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Hardhat](https://hardhat.org/){target=\\_blank}, which provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Transactions with Special Requirements", + "anchor": "transactions-with-special-requirements" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Default Weight Annotations", + "anchor": "default-weight-annotations" }, { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" + "depth": 3, + "title": "Weights and Database Read/Write Operations", + "anchor": "weights-and-database-readwrite-operations" }, { - "depth": 2, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" + "depth": 3, + "title": "Dispatch Classes", + "anchor": "dispatch-classes" }, { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" + "depth": 3, + "title": "Dynamic Weights", + "anchor": "dynamic-weights" }, { "depth": 2, - "title": "Compile", - "anchor": "compile" + "title": "Post Dispatch Weight Correction", + "anchor": "post-dispatch-weight-correction" }, { "depth": 2, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" + "title": "Custom Fees", + "anchor": "custom-fees" }, { - "depth": 2, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" + "depth": 3, + "title": "Custom Weights", + "anchor": "custom-weights" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 4051, - "words": 475, - "headings": 9, - "estimated_token_count_total": 981 + "chars": 20800, + "words": 2917, + "headings": 15, + "estimated_token_count_total": 4464 }, - "hash": "sha256:98f5c5c1a26db913e1c4c435062d214ca8c4b5f2dbed5b64d2e54c3435f06452", + "hash": "sha256:7d0c3fa7982b3e1843adb8f27422456397580b3a3eba5047b381da8517742536", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", - "title": "Deploy a Basic Contract with Remix IDE", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", + "id": "reference-parachains-blocks-transactions-fees-transactions", + "title": "Transactions", + "slug": "reference-parachains-blocks-transactions-fees-transactions", "categories": [ - "Smart Contracts" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/", - "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Remix IDE](https://remix.ethereum.org/){target=\\_blank}, which offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md", + "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/", + "preview": "Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions.", "outline": [ { "depth": 2, @@ -6968,169 +7793,130 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "What Is a Transaction?", + "anchor": "what-is-a-transaction" }, { - "depth": 2, - "title": "Access Remix", - "anchor": "access-remix" + "depth": 3, + "title": "Signed Transactions", + "anchor": "signed-transactions" }, { - "depth": 2, - "title": "Compile", - "anchor": "compile" + "depth": 3, + "title": "Unsigned Transactions", + "anchor": "unsigned-transactions" }, { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" + "depth": 3, + "title": "Inherent Transactions", + "anchor": "inherent-transactions" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 2978, - "words": 430, - "headings": 6, - "estimated_token_count_total": 738 - }, - "hash": "sha256:0c00544ba0be9c0a6fa0c54bdb38045d64e95af714785b86e57f885a03b4b17a", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat", - "title": "Deploy an ERC-20 to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/", - "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", - "outline": [ + "title": "Transaction Formats", + "anchor": "transaction-formats" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Types of Transaction Formats", + "anchor": "types-of-transaction-formats" }, { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "depth": 3, + "title": "Signed Transaction Data Structure", + "anchor": "signed-transaction-data-structure" }, { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" + "depth": 3, + "title": "Signed Extensions", + "anchor": "signed-extensions" }, { "depth": 2, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" + "title": "Transaction Construction", + "anchor": "transaction-construction" }, { - "depth": 2, - "title": "Compile your Contract", - "anchor": "compile-your-contract" + "depth": 3, + "title": "Construct a Signed Transaction", + "anchor": "construct-a-signed-transaction" }, { - "depth": 2, - "title": "Test your Contract", - "anchor": "test-your-contract" + "depth": 3, + "title": "Transaction Encoding", + "anchor": "transaction-encoding" }, { - "depth": 2, - "title": "Deploy your Contract", - "anchor": "deploy-your-contract" + "depth": 3, + "title": "Customize Transaction Construction", + "anchor": "customize-transaction-construction" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 8131, - "words": 1205, - "headings": 8, - "estimated_token_count_total": 2156 - }, - "hash": "sha256:4036cb47abaf081ce480654bece336f83bd043f5225d5d8d20f152fb91aa2157", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", - "title": "Deploy an ERC-20 to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/", - "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", - "outline": [ + "title": "Lifecycle of a Transaction", + "anchor": "lifecycle-of-a-transaction" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Define Transaction Properties", + "anchor": "define-transaction-properties" }, { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "depth": 3, + "title": "Process on a Block Authoring Node", + "anchor": "process-on-a-block-authoring-node" }, { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" + "depth": 3, + "title": "Validate and Queue", + "anchor": "validate-and-queue" }, { - "depth": 2, - "title": "Compile", - "anchor": "compile" + "depth": 3, + "title": "Transaction Ordering and Priority", + "anchor": "transaction-ordering-and-priority" + }, + { + "depth": 3, + "title": "Transaction Execution", + "anchor": "transaction-execution" }, { "depth": 2, - "title": "Deploy", - "anchor": "deploy" + "title": "Transaction Mortality", + "anchor": "transaction-mortality" }, { "depth": 2, - "title": "Interact with Your Contract", - "anchor": "interact-with-your-contract" + "title": "Unique Identifiers for Extrinsics", + "anchor": "unique-identifiers-for-extrinsics" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 9121, - "words": 1261, - "headings": 7, - "estimated_token_count_total": 2183 + "chars": 23610, + "words": 3333, + "headings": 22, + "estimated_token_count_total": 4708 }, - "hash": "sha256:992767525da7c1323f28bcaee5b6d1256ee2c0c70dbd16ae521245299858d996", + "hash": "sha256:66726634d3a51cd9c471621054a6e5f09c8061dca6144b64c8bcf45626359617", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry", - "title": "Deploy an NFT to Polkadot Hub with Foundry", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry", + "id": "reference-parachains-chain-data", + "title": "Chain Data", + "slug": "reference-parachains-chain-data", "categories": [ "Basics", - "Smart Contracts" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/.foundry/", - "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md", + "html_url": "https://docs.polkadot.com/reference/parachains/chain-data/", + "preview": "Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you", "outline": [ { "depth": 2, @@ -7139,127 +7925,114 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" + "title": "Application Development", + "anchor": "application-development" }, { "depth": 2, - "title": "Configure Foundry", - "anchor": "configure-foundry" + "title": "Understand Metadata", + "anchor": "understand-metadata" }, { "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" + "title": "Expose Runtime Information as Metadata", + "anchor": "expose-runtime-information-as-metadata" }, { "depth": 2, - "title": "Compile", - "anchor": "compile" + "title": "Generate Metadata", + "anchor": "generate-metadata" }, { "depth": 2, - "title": "Deploy", - "anchor": "deploy" + "title": "Retrieve Runtime Metadata", + "anchor": "retrieve-runtime-metadata" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 3489, - "words": 438, - "headings": 8, - "estimated_token_count_total": 847 - }, - "hash": "sha256:c4b410125946db479b9c262a5132a31bb7730a778501c3a95910ad9d38007cf4", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", - "title": "Deploy an NFT to Polkadot Hub with Hardhat", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/", - "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Use Polkadot.js", + "anchor": "use-polkadotjs" }, { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "depth": 3, + "title": "Use Curl", + "anchor": "use-curl" }, { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" + "depth": 3, + "title": "Use Subxt", + "anchor": "use-subxt" }, { "depth": 2, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" + "title": "Client Applications and Metadata", + "anchor": "client-applications-and-metadata" }, { "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" + "title": "Metadata Format", + "anchor": "metadata-format" }, { - "depth": 2, - "title": "Compile", - "anchor": "compile" + "depth": 3, + "title": "Pallets", + "anchor": "pallets" }, { - "depth": 2, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" + "depth": 3, + "title": "Extrinsic", + "anchor": "extrinsic" }, { "depth": 2, - "title": "Deploy", - "anchor": "deploy" + "title": "Included RPC APIs", + "anchor": "included-rpc-apis" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 4837, - "words": 565, - "headings": 9, - "estimated_token_count_total": 1152 + "chars": 18650, + "words": 2216, + "headings": 15, + "estimated_token_count_total": 3774 }, - "hash": "sha256:1e44c9df24715affa822f0df9680413cd995909f2c086d3a70499ee69901985e", + "hash": "sha256:49238d1e9e2c33e0fcd3a84b5e30f0d3840d7d23a783b538875e0a23f38efc1d", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", - "title": "Deploy an NFT to Polkadot Hub with Remix", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", + "id": "reference-parachains-consensus-async-backing", + "title": "reference-parachains-consensus-async-backing", + "slug": "reference-parachains-consensus-async-backing", "categories": [ - "Basics", - "Smart Contracts" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/", - "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-async-backing.md", + "html_url": "https://docs.polkadot.com/reference/parachains/consensus/async-backing/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-consensus-elastic-scaling", + "title": "Elastic Scaling", + "slug": "reference-parachains-consensus-elastic-scaling", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-elastic-scaling.md", + "html_url": "https://docs.polkadot.com/reference/parachains/consensus/elastic-scaling/", + "preview": "Polkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains.", "outline": [ { "depth": 2, @@ -7268,138 +8041,5178 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "How Elastic Scaling Works", + "anchor": "how-elastic-scaling-works" }, { "depth": 2, - "title": "Access Remix", - "anchor": "access-remix" + "title": "Benefits of Elastic Scaling", + "anchor": "benefits-of-elastic-scaling" }, { "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" + "title": "Use Cases", + "anchor": "use-cases" }, { - "depth": 2, - "title": "Compile", - "anchor": "compile" + "depth": 3, + "title": "Handling Sudden Traffic Spikes", + "anchor": "handling-sudden-traffic-spikes" }, { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" + "depth": 3, + "title": "Supporting Early-Stage Growth", + "anchor": "supporting-early-stage-growth" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Scaling Massive IoT Networks", + "anchor": "scaling-massive-iot-networks" + }, + { + "depth": 3, + "title": "Powering Real-Time, Low-Latency Systems", + "anchor": "powering-real-time-low-latency-systems" } ], "stats": { - "chars": 3754, - "words": 505, - "headings": 7, - "estimated_token_count_total": 928 + "chars": 7871, + "words": 1047, + "headings": 8, + "estimated_token_count_total": 1440 }, - "hash": "sha256:12a8debfbc05c5ac0e2c94daa40167adab837dc4e1b2731f5b48ae8bc9bc2c93", + "hash": "sha256:2d228c52844df8952520fafdd3e6f0e26bfd2f32b5ee60c6241cf7d38603643c", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-cookbook", - "title": "Smart Contracts Cookbook Index", - "slug": "smart-contracts-cookbook", + "id": "reference-parachains-consensus", + "title": "reference-parachains-consensus", + "slug": "reference-parachains-consensus", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus.md", + "html_url": "https://docs.polkadot.com/reference/parachains/consensus/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-cryptography", + "title": "Cryptography", + "slug": "reference-parachains-cryptography", "categories": [ "Basics", - "dApps", - "Smart Contracts" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/", - "preview": "Welcome to the Polkadot smart contracts cookbook index.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md", + "html_url": "https://docs.polkadot.com/reference/parachains/cryptography/", + "preview": "Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem.", "outline": [ { "depth": 2, - "title": "Get Tokens from the Faucet", - "anchor": "get-tokens-from-the-faucet" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "EVM/PVM Smart Contracts", - "anchor": "evmpvm-smart-contracts" + "title": "Hash Functions", + "anchor": "hash-functions" + }, + { + "depth": 3, + "title": "Key Properties of Hash Functions", + "anchor": "key-properties-of-hash-functions" + }, + { + "depth": 3, + "title": "Blake2", + "anchor": "blake2" }, { "depth": 2, - "title": "Port Ethereum DApps", - "anchor": "port-ethereum-dapps" + "title": "Types of Cryptography", + "anchor": "types-of-cryptography" + }, + { + "depth": 3, + "title": "Symmetric Cryptography", + "anchor": "symmetric-cryptography" + }, + { + "depth": 3, + "title": "Asymmetric Cryptography", + "anchor": "asymmetric-cryptography" + }, + { + "depth": 3, + "title": "Trade-offs and Compromises", + "anchor": "trade-offs-and-compromises" + }, + { + "depth": 2, + "title": "Digital Signatures", + "anchor": "digital-signatures" + }, + { + "depth": 3, + "title": "Example of Creating a Digital Signature", + "anchor": "example-of-creating-a-digital-signature" + }, + { + "depth": 2, + "title": "Elliptic Curve", + "anchor": "elliptic-curve" + }, + { + "depth": 3, + "title": "Various Implementations", + "anchor": "various-implementations" } ], "stats": { - "chars": 2815, - "words": 206, - "headings": 3, - "estimated_token_count_total": 1014 + "chars": 8860, + "words": 1293, + "headings": 12, + "estimated_token_count_total": 1797 }, - "hash": "sha256:cea0745bf1f1ac5680690a78494977b5e111c33638f5ceaa2c19ce0804cc74ad", + "hash": "sha256:259dcef86aadc513675258b665cc3940db65af6eb32a5db85da6ac339966fa60", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-hardhat-compile-and-test", - "title": "smart-contracts-dev-environments-hardhat-compile-and-test", - "slug": "smart-contracts-dev-environments-hardhat-compile-and-test", + "id": "reference-parachains-data-encoding", + "title": "Data Encoding", + "slug": "reference-parachains-data-encoding", "categories": [ - "Uncategorized" + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md", + "html_url": "https://docs.polkadot.com/reference/parachains/data-encoding/", + "preview": "The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "SCALE Codec", + "anchor": "scale-codec" + }, + { + "depth": 3, + "title": "Encode", + "anchor": "encode" + }, + { + "depth": 3, + "title": "Decode", + "anchor": "decode" + }, + { + "depth": 3, + "title": "CompactAs", + "anchor": "compactas" + }, + { + "depth": 3, + "title": "HasCompact", + "anchor": "hascompact" + }, + { + "depth": 3, + "title": "EncodeLike", + "anchor": "encodelike" + }, + { + "depth": 3, + "title": "Data Types", + "anchor": "data-types" + }, + { + "depth": 2, + "title": "Encode and Decode Rust Trait Implementations", + "anchor": "encode-and-decode-rust-trait-implementations" + }, + { + "depth": 2, + "title": "SCALE Codec Libraries", + "anchor": "scale-codec-libraries" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-compile-and-test.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/compile-and-test/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 13629, + "words": 1314, + "headings": 10, + "estimated_token_count_total": 3213 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:e448294b6e52291ac0add5fa6533572814e6cd27af42bdaccc2000b86f52d775", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-hardhat-deploy-a-contract", - "title": "smart-contracts-dev-environments-hardhat-deploy-a-contract", - "slug": "smart-contracts-dev-environments-hardhat-deploy-a-contract", + "id": "reference-parachains-interoperability", + "title": "Interoperability", + "slug": "reference-parachains-interoperability", "categories": [ - "Uncategorized" + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md", + "html_url": "https://docs.polkadot.com/reference/parachains/interoperability/", + "preview": "Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Why Interoperability Matters", + "anchor": "why-interoperability-matters" + }, + { + "depth": 2, + "title": "Key Mechanisms for Interoperability", + "anchor": "key-mechanisms-for-interoperability" + }, + { + "depth": 3, + "title": "Cross-Consensus Messaging (XCM): The Backbone of Communication", + "anchor": "cross-consensus-messaging-xcm-the-backbone-of-communication" + }, + { + "depth": 3, + "title": "Bridges: Connecting External Networks", + "anchor": "bridges-connecting-external-networks" + }, + { + "depth": 2, + "title": "The Polkadot Advantage", + "anchor": "the-polkadot-advantage" + }, + { + "depth": 2, + "title": "Looking Ahead", + "anchor": "looking-ahead" + } + ], + "stats": { + "chars": 4635, + "words": 584, + "headings": 7, + "estimated_token_count_total": 772 + }, + "hash": "sha256:11bb4f113bdda5852a3115e64d5ba47f8eccd4e3619a05ad960ab3a541f31346", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-networks", + "title": "Networks", + "slug": "reference-parachains-networks", + "categories": [ + "Basics", + "Polkadot Protocol", + "Networks" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md", + "html_url": "https://docs.polkadot.com/reference/parachains/networks/", + "preview": "The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's va", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Network Overview", + "anchor": "network-overview" + }, + { + "depth": 2, + "title": "Polkadot Development Networks", + "anchor": "polkadot-development-networks" + }, + { + "depth": 2, + "title": "Kusama Network", + "anchor": "kusama-network" + }, + { + "depth": 2, + "title": "Test Networks", + "anchor": "test-networks" + }, + { + "depth": 3, + "title": "Westend", + "anchor": "westend" + }, + { + "depth": 3, + "title": "Paseo", + "anchor": "paseo" + }, + { + "depth": 2, + "title": "Local Test Networks", + "anchor": "local-test-networks" + }, + { + "depth": 3, + "title": "Zombienet", + "anchor": "zombienet" + }, + { + "depth": 3, + "title": "Chopsticks", + "anchor": "chopsticks" + } + ], + "stats": { + "chars": 7834, + "words": 1111, + "headings": 10, + "estimated_token_count_total": 1473 + }, + "hash": "sha256:e49e063a2cc0fb5a48c6cdc3de266bb6e025a006940fea8e90cc4d5f9884900f", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-node-and-runtime", + "title": "Node and Runtime", + "slug": "reference-parachains-node-and-runtime", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md", + "html_url": "https://docs.polkadot.com/reference/parachains/node-and-runtime/", + "preview": "Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Architectural Principles", + "anchor": "architectural-principles" + }, + { + "depth": 3, + "title": "Advantages of this Architecture", + "anchor": "advantages-of-this-architecture" + }, + { + "depth": 2, + "title": "Node (Client)", + "anchor": "node-client" + }, + { + "depth": 2, + "title": "Runtime", + "anchor": "runtime" + }, + { + "depth": 3, + "title": "Characteristics", + "anchor": "characteristics" + }, + { + "depth": 3, + "title": "Key Functions", + "anchor": "key-functions" + }, + { + "depth": 2, + "title": "Communication Between Node and Runtime", + "anchor": "communication-between-node-and-runtime" + }, + { + "depth": 3, + "title": "Runtime APIs", + "anchor": "runtime-apis" + }, + { + "depth": 3, + "title": "Host Functions", + "anchor": "host-functions" + } + ], + "stats": { + "chars": 4937, + "words": 628, + "headings": 10, + "estimated_token_count_total": 914 + }, + "hash": "sha256:8122e21c149d0863cfe3b37fc5606bcdb91668e9d265f0f05451a61ff70e4e93", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-randomness", + "title": "Randomness", + "slug": "reference-parachains-randomness", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md", + "html_url": "https://docs.polkadot.com/reference/parachains/randomness/", + "preview": "Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as \"random\" numbers on a computer are actually pseudo-random. These numbers rely on an initial \"seed,\" which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\\_blank}, [heart rates](https://m", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "VRF", + "anchor": "vrf" + }, + { + "depth": 3, + "title": "How VRF Works", + "anchor": "how-vrf-works" + }, + { + "depth": 2, + "title": "RANDAO", + "anchor": "randao" + }, + { + "depth": 2, + "title": "VDFs", + "anchor": "vdfs" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 6503, + "words": 1005, + "headings": 6, + "estimated_token_count_total": 1388 + }, + "hash": "sha256:c7d8a5a4263fd21af458ab0bd102377104affdf2431b4fe74eeff4ebe62a4a81", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains", + "title": "Parachains Overview", + "slug": "reference-parachains", + "categories": [ + "Basics", + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md", + "html_url": "https://docs.polkadot.com/reference/parachains/", + "preview": "A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Polkadot SDK: Parachain Architecture", + "anchor": "polkadot-sdk-parachain-architecture" + }, + { + "depth": 3, + "title": "Substrate: The Foundation", + "anchor": "substrate-the-foundation" + }, + { + "depth": 3, + "title": "FRAME: Building Blocks for Your Runtime", + "anchor": "frame-building-blocks-for-your-runtime" + }, + { + "depth": 3, + "title": "Cumulus: Parachain-Specific Functionality", + "anchor": "cumulus-parachain-specific-functionality" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 8495, + "words": 1029, + "headings": 6, + "estimated_token_count_total": 1759 + }, + "hash": "sha256:ecb0d9459e08920db7d2d59dc7c01aba7a91ce8c9e39256bd0c3efa473dbaa17", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-assets-and-smart-contracts", + "title": "Asset Hub", + "slug": "reference-polkadot-hub-assets-and-smart-contracts", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/assets-and-smart-contracts/", + "preview": "The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integra", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Assets Basics", + "anchor": "assets-basics" + }, + { + "depth": 2, + "title": "Assets Pallet", + "anchor": "assets-pallet" + }, + { + "depth": 3, + "title": "Key Features", + "anchor": "key-features" + }, + { + "depth": 3, + "title": "Main Functions", + "anchor": "main-functions" + }, + { + "depth": 3, + "title": "Querying Functions", + "anchor": "querying-functions" + }, + { + "depth": 3, + "title": "Permission Models and Roles", + "anchor": "permission-models-and-roles" + }, + { + "depth": 3, + "title": "Asset Freezing", + "anchor": "asset-freezing" + }, + { + "depth": 3, + "title": "Non-Custodial Transfers (Approval API)", + "anchor": "non-custodial-transfers-approval-api" + }, + { + "depth": 2, + "title": "Foreign Assets", + "anchor": "foreign-assets" + }, + { + "depth": 3, + "title": "Handling Foreign Assets", + "anchor": "handling-foreign-assets" + }, + { + "depth": 2, + "title": "Integration", + "anchor": "integration" + }, + { + "depth": 3, + "title": "API Sidecar", + "anchor": "api-sidecar" + }, + { + "depth": 3, + "title": "TxWrapper", + "anchor": "txwrapper" + }, + { + "depth": 3, + "title": "Parachain Node", + "anchor": "parachain-node" + }, + { + "depth": 2, + "title": "XCM Transfer Monitoring", + "anchor": "xcm-transfer-monitoring" + }, + { + "depth": 3, + "title": "Monitor XCM Deposits", + "anchor": "monitor-xcm-deposits" + }, + { + "depth": 3, + "title": "Track XCM Information Back to the Source", + "anchor": "track-xcm-information-back-to-the-source" + }, + { + "depth": 3, + "title": "Practical Monitoring Examples", + "anchor": "practical-monitoring-examples" + }, + { + "depth": 3, + "title": "Monitor for Failed XCM Transfers", + "anchor": "monitor-for-failed-xcm-transfers" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 18211, + "words": 2649, + "headings": 21, + "estimated_token_count_total": 3678 + }, + "hash": "sha256:3d10c04cffc5f737ff75b079d661c2c1904629d23ae1e415e64fd6ae4e98759e", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-bridging", + "title": "Bridge Hub", + "slug": "reference-polkadot-hub-bridging", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-bridging.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/bridging/", + "preview": "The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interope", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Trustless Bridging", + "anchor": "trustless-bridging" + }, + { + "depth": 2, + "title": "Bridging Components", + "anchor": "bridging-components" + }, + { + "depth": 3, + "title": "Ethereum-Specific Support", + "anchor": "ethereum-specific-support" + }, + { + "depth": 2, + "title": "Deployed Bridges", + "anchor": "deployed-bridges" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 5467, + "words": 776, + "headings": 6, + "estimated_token_count_total": 1220 + }, + "hash": "sha256:86734ba8bcdea7913f488edf666a6104bed0a18649d57abde82c149c41c2b871", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-collectives-and-daos", + "title": "Collectives Chain", + "slug": "reference-polkadot-hub-collectives-and-daos", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-collectives-and-daos.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/collectives-and-daos/", + "preview": "Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Key Collectives", + "anchor": "key-collectives" + } + ], + "stats": { + "chars": 2288, + "words": 293, + "headings": 2, + "estimated_token_count_total": 424 + }, + "hash": "sha256:59ec351fbb8d3a392e90f4f5bf6b62f58b21d6d7a900c5e367e5d2e09ecb3aca", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-consensus-and-security-agile-coretime", + "title": "Agile Coretime", + "slug": "reference-polkadot-hub-consensus-and-security-agile-coretime", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/agile-coretime/", + "preview": "Agile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Bulk Coretime", + "anchor": "bulk-coretime" + }, + { + "depth": 3, + "title": "Coretime Interlacing", + "anchor": "coretime-interlacing" + }, + { + "depth": 3, + "title": "Coretime Splitting", + "anchor": "coretime-splitting" + }, + { + "depth": 2, + "title": "On-Demand Coretime", + "anchor": "on-demand-coretime" + } + ], + "stats": { + "chars": 3028, + "words": 452, + "headings": 5, + "estimated_token_count_total": 619 + }, + "hash": "sha256:00be43ac8d666bbe15c5c2fa5a5085697d0bb5a6f341ebbb943a209f0be355df", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-consensus-and-security-pos-consensus", + "title": "Proof of Stake Consensus", + "slug": "reference-polkadot-hub-consensus-and-security-pos-consensus", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/pos-consensus/", + "preview": "Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank} model and a com", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Nominated Proof of Stake", + "anchor": "nominated-proof-of-stake" + }, + { + "depth": 2, + "title": "Hybrid Consensus", + "anchor": "hybrid-consensus" + }, + { + "depth": 2, + "title": "Block Production - BABE", + "anchor": "block-production-babe" + }, + { + "depth": 3, + "title": "Validator Participation", + "anchor": "validator-participation" + }, + { + "depth": 3, + "title": "Additional Resources", + "anchor": "additional-resources" + }, + { + "depth": 2, + "title": "Finality Gadget - GRANDPA", + "anchor": "finality-gadget-grandpa" + }, + { + "depth": 3, + "title": "Probabilistic vs. Provable Finality", + "anchor": "probabilistic-vs-provable-finality" + }, + { + "depth": 3, + "title": "Additional Resources", + "anchor": "additional-resources-2" + }, + { + "depth": 2, + "title": "Fork Choice", + "anchor": "fork-choice" + }, + { + "depth": 3, + "title": "Additional Resources", + "anchor": "additional-resources-3" + }, + { + "depth": 2, + "title": "Bridging - BEEFY", + "anchor": "bridging-beefy" + }, + { + "depth": 3, + "title": "Additional Resources", + "anchor": "additional-resources-4" + } + ], + "stats": { + "chars": 12753, + "words": 1834, + "headings": 13, + "estimated_token_count_total": 2526 + }, + "hash": "sha256:231fc555eefe5f910fb36e0c03945147d0fb235272850797391751f4444b0a9c", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-consensus-and-security-relay-chain", + "title": "Overview of the Polkadot Relay Chain", + "slug": "reference-polkadot-hub-consensus-and-security-relay-chain", + "categories": [ + "Basics", + "Polkadot Protocol", + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/", + "preview": "Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank}, and cross-chain int", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Polkadot 1.0", + "anchor": "polkadot-10" + }, + { + "depth": 3, + "title": "High-Level Architecture", + "anchor": "high-level-architecture" + }, + { + "depth": 3, + "title": "Polkadot's Additional Functionalities", + "anchor": "polkadots-additional-functionalities" + }, + { + "depth": 3, + "title": "Polkadot's Resilience", + "anchor": "polkadots-resilience" + }, + { + "depth": 3, + "title": "Polkadot's Blockspace", + "anchor": "polkadots-blockspace" + }, + { + "depth": 2, + "title": "DOT Token", + "anchor": "dot-token" + }, + { + "depth": 3, + "title": "Redenomination of DOT", + "anchor": "redenomination-of-dot" + }, + { + "depth": 3, + "title": "The Planck Unit", + "anchor": "the-planck-unit" + }, + { + "depth": 3, + "title": "Uses for DOT", + "anchor": "uses-for-dot" + }, + { + "depth": 2, + "title": "JAM and the Road Ahead", + "anchor": "jam-and-the-road-ahead" + } + ], + "stats": { + "chars": 12458, + "words": 1774, + "headings": 11, + "estimated_token_count_total": 2580 + }, + "hash": "sha256:8a914e4309d4fe7070e62d7abe4665b6c76c8dc5ec3219332eccb16b77b0dd95", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-people-and-identity", + "title": "People Chain", + "slug": "reference-polkadot-hub-people-and-identity", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-people-and-identity.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/people-and-identity/", + "preview": "People chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Identity Management System", + "anchor": "identity-management-system" + }, + { + "depth": 3, + "title": "Sub-Identities", + "anchor": "sub-identities" + }, + { + "depth": 2, + "title": "Verification Process", + "anchor": "verification-process" + }, + { + "depth": 3, + "title": "Judgment Requests", + "anchor": "judgment-requests" + }, + { + "depth": 3, + "title": "Judgment Classifications", + "anchor": "judgment-classifications" + }, + { + "depth": 3, + "title": "Registrars", + "anchor": "registrars" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 4750, + "words": 606, + "headings": 8, + "estimated_token_count_total": 876 + }, + "hash": "sha256:8239d1e8d8642cb7c10e9e5f971c99b999e9e4a87373b50bf4a691225c1e4702", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub", + "title": "reference-polkadot-hub", + "slug": "reference-polkadot-hub", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-chopsticks", + "title": "reference-tools-chopsticks", + "slug": "reference-tools-chopsticks", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md", + "html_url": "https://docs.polkadot.com/reference/tools/chopsticks/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-dedot", + "title": "Dedot", + "slug": "reference-tools-dedot", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md", + "html_url": "https://docs.polkadot.com/reference/tools/dedot/", + "preview": "[Dedot](https://github.com/dedotdev/dedot){target=\\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\\_blank}.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 3, + "title": "Key Features", + "anchor": "key-features" + }, + { + "depth": 2, + "title": "Installation", + "anchor": "installation" + }, + { + "depth": 2, + "title": "Get Started", + "anchor": "get-started" + }, + { + "depth": 3, + "title": "Initialize a Client Instance", + "anchor": "initialize-a-client-instance" + }, + { + "depth": 3, + "title": "Enable Type and API Suggestions", + "anchor": "enable-type-and-api-suggestions" + }, + { + "depth": 3, + "title": "Read On-Chain Data", + "anchor": "read-on-chain-data" + }, + { + "depth": 3, + "title": "Sign and Send Transactions", + "anchor": "sign-and-send-transactions" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 8855, + "words": 1100, + "headings": 9, + "estimated_token_count_total": 2300 + }, + "hash": "sha256:ba24e31e2ad94fbf1d73f1878da92dd2e1476db00170780bbdf0e65ab18bc961", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-light-clients", + "title": "Light Clients", + "slug": "reference-tools-light-clients", + "categories": [ + "Parachains", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md", + "html_url": "https://docs.polkadot.com/reference/tools/light-clients/", + "preview": "Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Light Clients Workflow", + "anchor": "light-clients-workflow" + }, + { + "depth": 2, + "title": "JSON-RPC and Light Client Comparison", + "anchor": "json-rpc-and-light-client-comparison" + }, + { + "depth": 2, + "title": "Using Light Clients", + "anchor": "using-light-clients" + }, + { + "depth": 3, + "title": "PAPI Light Client Support", + "anchor": "papi-light-client-support" + }, + { + "depth": 3, + "title": "Substrate Connect - Browser Extension", + "anchor": "substrate-connect-browser-extension" + }, + { + "depth": 2, + "title": "Resources", + "anchor": "resources" + } + ], + "stats": { + "chars": 6490, + "words": 870, + "headings": 7, + "estimated_token_count_total": 1430 + }, + "hash": "sha256:1284c42be692167e01bcc44e2e134ec20615402675fac26df246c00aa1588d80", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-moonwall", + "title": "E2E Testing with Moonwall", + "slug": "reference-tools-moonwall", + "categories": [ + "Parachains", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md", + "html_url": "https://docs.polkadot.com/reference/tools/moonwall/", + "preview": "Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Install Moonwall", + "anchor": "install-moonwall" + }, + { + "depth": 3, + "title": "Global Installation", + "anchor": "global-installation" + }, + { + "depth": 3, + "title": "Local Installation", + "anchor": "local-installation" + }, + { + "depth": 2, + "title": "Initialize Moonwall", + "anchor": "initialize-moonwall" + }, + { + "depth": 2, + "title": "Writing Tests", + "anchor": "writing-tests" + }, + { + "depth": 2, + "title": "Running the Tests", + "anchor": "running-the-tests" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 10240, + "words": 1295, + "headings": 9, + "estimated_token_count_total": 2453 + }, + "hash": "sha256:2c77cfb38bb2e466a8f56dabbb706fcd2e90cf1634fc9beb7f0ee95a75735653", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-omninode", + "title": "Polkadot Omni Node", + "slug": "reference-tools-omninode", + "categories": [ + "Parachains", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md", + "html_url": "https://docs.polkadot.com/reference/tools/omninode/", + "preview": "The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\\_blank} file, allowing it to adapt dynamically to different parachains.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Install Polkadot Omni Node", + "anchor": "install-polkadot-omni-node" + }, + { + "depth": 2, + "title": "Obtain Chain Specifications", + "anchor": "obtain-chain-specifications" + }, + { + "depth": 2, + "title": "Run a Parachain Full Node", + "anchor": "run-a-parachain-full-node" + }, + { + "depth": 2, + "title": "Interact with the Node", + "anchor": "interact-with-the-node" + }, + { + "depth": 2, + "title": "Parachain Compatibility", + "anchor": "parachain-compatibility" + }, + { + "depth": 3, + "title": "Required Runtime APIs", + "anchor": "required-runtime-apis" + }, + { + "depth": 3, + "title": "Required Pallets", + "anchor": "required-pallets" + } + ], + "stats": { + "chars": 8913, + "words": 1164, + "headings": 9, + "estimated_token_count_total": 2017 + }, + "hash": "sha256:a87815deff81936d7f50842f8600004990076c1a33e7e6b408ab954b6ce47259", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-papi", + "title": "Polkadot-API", + "slug": "reference-tools-papi", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md", + "html_url": "https://docs.polkadot.com/reference/tools/papi/", + "preview": "[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Get Started", + "anchor": "get-started" + }, + { + "depth": 3, + "title": "API Instantiation", + "anchor": "api-instantiation" + }, + { + "depth": 3, + "title": "Reading Chain Data", + "anchor": "reading-chain-data" + }, + { + "depth": 3, + "title": "Sending Transactions", + "anchor": "sending-transactions" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 8957, + "words": 1156, + "headings": 6, + "estimated_token_count_total": 1987 + }, + "hash": "sha256:2ca93b09d3bb9159bbf53816886a9b242bb3c13b996c51fd52962e049e2d5477", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-paraspell", + "title": "ParaSpell XCM SDK", + "slug": "reference-tools-paraspell", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md", + "html_url": "https://docs.polkadot.com/reference/tools/paraspell/", + "preview": "[ParaSpell](https://paraspell.github.io/docs/){target=\\_blank} is a comprehensive suite of open-source tools designed to simplify cross-chain interactions within the Polkadot ecosystem. At its core, ParaSpell is dedicated to enhancing the functionality of the [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} protocol by providing developers with a unified and streamlined experience for building interoperable decentralized applications (dApps).", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 3, + "title": "ParaSpell XCM SDK", + "anchor": "paraspell-xcm-sdk" + }, + { + "depth": 2, + "title": "Install ParaSpell", + "anchor": "install-paraspell" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 4043, + "words": 562, + "headings": 4, + "estimated_token_count_total": 888 + }, + "hash": "sha256:c8741954ea656680aa3322c825e3f6acbaac369baaa42232b06af9e5e482f74f", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-polkadart", + "title": "Polkadart", + "slug": "reference-tools-polkadart", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md", + "html_url": "https://docs.polkadot.com/reference/tools/polkadart/", + "preview": "Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications.", + "outline": [ + { + "depth": 2, + "title": "Installation", + "anchor": "installation" + }, + { + "depth": 2, + "title": "Get Started", + "anchor": "get-started" + }, + { + "depth": 3, + "title": "Type Generation", + "anchor": "type-generation" + }, + { + "depth": 3, + "title": "Run Generator", + "anchor": "run-generator" + }, + { + "depth": 3, + "title": "Use Generated Types", + "anchor": "use-generated-types" + }, + { + "depth": 3, + "title": "Creating an API Instance", + "anchor": "creating-an-api-instance" + }, + { + "depth": 3, + "title": "Reading Chain Data", + "anchor": "reading-chain-data" + }, + { + "depth": 3, + "title": "Subscribe to New Blocks", + "anchor": "subscribe-to-new-blocks" + }, + { + "depth": 3, + "title": "Send a Transaction", + "anchor": "send-a-transaction" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 5178, + "words": 624, + "headings": 10, + "estimated_token_count_total": 1084 + }, + "hash": "sha256:7f533abe61586af8438e350c41b741d74a8edb839f9dc4139bc4619ba3748258", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-polkadot-js-api", + "title": "Polkadot.js API", + "slug": "reference-tools-polkadot-js-api", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md", + "html_url": "https://docs.polkadot.com/reference/tools/polkadot-js-api/", + "preview": "!!! warning \"Maintenance Mode Only\" The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank} (modern, type-safe API) as actively maintained alternatives.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 3, + "title": "Dynamic API Generation", + "anchor": "dynamic-api-generation" + }, + { + "depth": 3, + "title": "Available API Categories", + "anchor": "available-api-categories" + }, + { + "depth": 2, + "title": "Installation", + "anchor": "installation" + }, + { + "depth": 2, + "title": "Get Started", + "anchor": "get-started" + }, + { + "depth": 3, + "title": "Creating an API Instance", + "anchor": "creating-an-api-instance" + }, + { + "depth": 3, + "title": "Reading Chain Data", + "anchor": "reading-chain-data" + }, + { + "depth": 3, + "title": "Sending Transactions", + "anchor": "sending-transactions" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 5042, + "words": 684, + "headings": 9, + "estimated_token_count_total": 1166 + }, + "hash": "sha256:ed3986f30880fefca5975fcdc847c68b4aca65862c63e3002b25391b0521781d", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-py-substrate-interface", + "title": "Python Substrate Interface", + "slug": "reference-tools-py-substrate-interface", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md", + "html_url": "https://docs.polkadot.com/reference/tools/py-substrate-interface/", + "preview": "The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for:", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Installation", + "anchor": "installation" + }, + { + "depth": 2, + "title": "Get Started", + "anchor": "get-started" + }, + { + "depth": 3, + "title": "Establishing Connection", + "anchor": "establishing-connection" + }, + { + "depth": 3, + "title": "Reading Chain State", + "anchor": "reading-chain-state" + }, + { + "depth": 3, + "title": "Submitting Transactions", + "anchor": "submitting-transactions" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 4302, + "words": 541, + "headings": 7, + "estimated_token_count_total": 942 + }, + "hash": "sha256:8987fc35cd28602054ee018031f773e2e3837425107c51d0e2ac68a94b86e9c0", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-sidecar", + "title": "Sidecar REST API", + "slug": "reference-tools-sidecar", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md", + "html_url": "https://docs.polkadot.com/reference/tools/sidecar/", + "preview": "The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Installation", + "anchor": "installation" + }, + { + "depth": 2, + "title": "Usage", + "anchor": "usage" + }, + { + "depth": 3, + "title": "Endpoints", + "anchor": "endpoints" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 7309, + "words": 1033, + "headings": 6, + "estimated_token_count_total": 1945 + }, + "hash": "sha256:0795462182cb97256bb5c2acb035855fe0d6557185de8ac99482725ecb4f94c1", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-subxt", + "title": "Subxt Rust API", + "slug": "reference-tools-subxt", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md", + "html_url": "https://docs.polkadot.com/reference/tools/subxt/", + "preview": "Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Installation", + "anchor": "installation" + }, + { + "depth": 2, + "title": "Get Started", + "anchor": "get-started" + }, + { + "depth": 3, + "title": "Download Chain Metadata", + "anchor": "download-chain-metadata" + }, + { + "depth": 3, + "title": "Generate Type-Safe Interfaces", + "anchor": "generate-type-safe-interfaces" + }, + { + "depth": 3, + "title": "Initialize the Subxt Client", + "anchor": "initialize-the-subxt-client" + }, + { + "depth": 3, + "title": "Read Chain Data", + "anchor": "read-chain-data" + }, + { + "depth": 3, + "title": "Submit Transactions", + "anchor": "submit-transactions" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 9174, + "words": 1175, + "headings": 10, + "estimated_token_count_total": 2187 + }, + "hash": "sha256:56269d9ea47f5b4e92cd7d5a1e65ab06d181a9c380f90bb3ef285529b12299f7", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-xcm-tools", + "title": "XCM Tools", + "slug": "reference-tools-xcm-tools", + "categories": [ + "Basics", + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md", + "html_url": "https://docs.polkadot.com/reference/tools/xcm-tools/", + "preview": "As described in the [Interoperability](/develop/interoperability){target=\\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Popular XCM Tools", + "anchor": "popular-xcm-tools" + }, + { + "depth": 3, + "title": "Moonsong Labs XCM Tools", + "anchor": "moonsong-labs-xcm-tools" + }, + { + "depth": 3, + "title": "ParaSpell", + "anchor": "paraspell" + }, + { + "depth": 3, + "title": "Astar XCM Tools", + "anchor": "astar-xcm-tools" + }, + { + "depth": 3, + "title": "Chopsticks", + "anchor": "chopsticks" + }, + { + "depth": 3, + "title": "Moonbeam XCM SDK", + "anchor": "moonbeam-xcm-sdk" + } + ], + "stats": { + "chars": 6146, + "words": 852, + "headings": 7, + "estimated_token_count_total": 1377 + }, + "hash": "sha256:674e4f60c82fc7544c7af8e09f1e0f677c9907cdff88b107f6c8489e97a43487", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-zombienet", + "title": "reference-tools-zombienet", + "slug": "reference-tools-zombienet", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md", + "html_url": "https://docs.polkadot.com/reference/tools/zombienet/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference", + "title": "reference", + "slug": "reference", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md", + "html_url": "https://docs.polkadot.com/reference/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-connect", + "title": "Connect to Polkadot", + "slug": "smart-contracts-connect", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-connect.md", + "html_url": "https://docs.polkadot.com/smart-contracts/connect/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", + "outline": [ + { + "depth": 2, + "title": "Networks Details", + "anchor": "networks-details" + }, + { + "depth": 2, + "title": "Test Tokens", + "anchor": "test-tokens" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 3459, + "words": 476, + "headings": 3, + "estimated_token_count_total": 558 + }, + "hash": "sha256:a2490223926957381913ae0ed22e2df3611a6713ec9d77a3015d1cd6a578b3f6", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-dapps-zero-to-hero", + "title": "Zero to Hero Smart Contract DApp", + "slug": "smart-contracts-cookbook-dapps-zero-to-hero", + "categories": [ + "dApp", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/dapps/zero-to-hero/", + "preview": "Decentralized applications (dApps) are a key component of the Web3 ecosystem, enabling developers to build applications that communicate directly with blockchain networks. Polkadot Hub, a blockchain with smart contract support, serves as a robust platform for deploying and interacting with dApps.", + "outline": [ + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Project Overview", + "anchor": "project-overview" + }, + { + "depth": 2, + "title": "Create and Deploy the Storage Contract", + "anchor": "create-and-deploy-the-storage-contract" + }, + { + "depth": 3, + "title": "Set Up Hardhat Project", + "anchor": "set-up-hardhat-project" + }, + { + "depth": 3, + "title": "Create the Storage Contract", + "anchor": "create-the-storage-contract" + }, + { + "depth": 3, + "title": "Configure Hardhat for Polkadot Hub", + "anchor": "configure-hardhat-for-polkadot-hub" + }, + { + "depth": 3, + "title": "Compile the Contract", + "anchor": "compile-the-contract" + }, + { + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 3, + "title": "Export the Contract ABI", + "anchor": "export-the-contract-abi" + }, + { + "depth": 2, + "title": "Set Up the dApp Project", + "anchor": "set-up-the-dapp-project" + }, + { + "depth": 2, + "title": "Install Dependencies", + "anchor": "install-dependencies" + }, + { + "depth": 2, + "title": "Connect to Polkadot Hub", + "anchor": "connect-to-polkadot-hub" + }, + { + "depth": 2, + "title": "Set Up the Smart Contract Interface", + "anchor": "set-up-the-smart-contract-interface" + }, + { + "depth": 2, + "title": "Create the Wallet Connection Component", + "anchor": "create-the-wallet-connection-component" + }, + { + "depth": 2, + "title": "Create the Read Contract Component", + "anchor": "create-the-read-contract-component" + }, + { + "depth": 2, + "title": "Create the Write Contract Component", + "anchor": "create-the-write-contract-component" + }, + { + "depth": 2, + "title": "How It Works", + "anchor": "how-it-works" + }, + { + "depth": 3, + "title": "Wallet Connection", + "anchor": "wallet-connection" + }, + { + "depth": 3, + "title": "Data Reads", + "anchor": "data-reads" + }, + { + "depth": 3, + "title": "Data Writes", + "anchor": "data-writes" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 31207, + "words": 3688, + "headings": 22, + "estimated_token_count_total": 6967 + }, + "hash": "sha256:b200f93a9179f0b2588ba722dd4c118536136faf3c39eabccf4abf5c346f78a8", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-eth-dapps-uniswap-v2", + "title": "Deploying Uniswap V2 on Polkadot", + "slug": "smart-contracts-cookbook-eth-dapps-uniswap-v2", + "categories": [ + "dApps", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Set Up the Project", + "anchor": "set-up-the-project" + }, + { + "depth": 2, + "title": "Understanding Uniswap V2 Architecture", + "anchor": "understanding-uniswap-v2-architecture" + }, + { + "depth": 2, + "title": "Test the Contracts", + "anchor": "test-the-contracts" + }, + { + "depth": 2, + "title": "Deploy the Contracts", + "anchor": "deploy-the-contracts" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } + ], + "stats": { + "chars": 11280, + "words": 1560, + "headings": 7, + "estimated_token_count_total": 2671 + }, + "hash": "sha256:2a42198668c759f63aa602115bf2d290ec7d03bbc3a3df20e30e85027e1b1cc3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", + "title": "Deploy a Basic Contract to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/.deploy-basic-pvm/", + "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "JavaScript with Ethers.js", + "anchor": "javascript-with-ethersjs" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" + }, + { + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 2, + "title": "Remix IDE", + "anchor": "remix-ide" + }, + { + "depth": 3, + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Hardhat", + "anchor": "hardhat" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup-2" + }, + { + "depth": 3, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile-2" + }, + { + "depth": 3, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy-2" + }, + { + "depth": 2, + "title": "Foundry", + "anchor": "foundry" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup-3" + }, + { + "depth": 3, + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract-2" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile-3" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy-3" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 13872, + "words": 1640, + "headings": 24, + "estimated_token_count_total": 3228 + }, + "hash": "sha256:8f29b0f0b56f8c136206211a858cdc5bc27bcd9119eab179a6cd306182d910cb", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-ethers-js", + "title": "JavaScript with Ethers.js", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-ethers-js", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-ethers-js.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-ethers-js/", + "preview": "[Ethers.js](https://docs.ethers.org/v6/){target=\\_blank} provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications.", + "outline": [ + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" + }, + { + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 6935, + "words": 767, + "headings": 4, + "estimated_token_count_total": 1490 + }, + "hash": "sha256:b0af34b460192f665ca70e7d7985e87b9f59a1a359888f6d14d651daedbcd711", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-foundry", + "title": "Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-foundry", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-foundry/", + "preview": "[Foundry](https://getfoundry.sh/){target=\\_blank} offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", + "outline": [ + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 2125, + "words": 276, + "headings": 6, + "estimated_token_count_total": 429 + }, + "hash": "sha256:f7687b9a1e80ab381cf4fb24f37cccfb98ddf139bf687e8832af99364ef0a8a9", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat", + "title": "hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-hardhat/", + "preview": "[Hardhat](https://hardhat.org/){target=\\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", + "outline": [ + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 3336, + "words": 375, + "headings": 7, + "estimated_token_count_total": 672 + }, + "hash": "sha256:93ca24da15095dd0bb03657f53d27771934aee055c11af529445a50e161f79a3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-remix", + "title": "Remix IDE", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-remix", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-remix/", + "preview": "[Remix IDE](https://remix.live/){target=\\_blank} offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", + "outline": [ + { + "depth": 3, + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 2473, + "words": 363, + "headings": 4, + "estimated_token_count_total": 527 + }, + "hash": "sha256:56d730c8a6d2ccf0324caf1c3f30929a93904f80e482cfcb457541e04482dbad", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-ethers-js", + "title": "JavaScript with Ethers.js", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-ethers-js", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-ethers-js.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-ethers-js/", + "preview": "[Ethers.js](https://docs.ethers.org/v6/){target=\\_blank} provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications.", + "outline": [ + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" + }, + { + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 6935, + "words": 767, + "headings": 4, + "estimated_token_count_total": 1490 + }, + "hash": "sha256:b0af34b460192f665ca70e7d7985e87b9f59a1a359888f6d14d651daedbcd711", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-foundry", + "title": "Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-foundry", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-foundry/", + "preview": "[Foundry](https://getfoundry.sh/){target=\\_blank} offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", + "outline": [ + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 2125, + "words": 276, + "headings": 6, + "estimated_token_count_total": 429 + }, + "hash": "sha256:f7687b9a1e80ab381cf4fb24f37cccfb98ddf139bf687e8832af99364ef0a8a9", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat", + "title": "hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-hardhat/", + "preview": "[Hardhat](https://hardhat.org/){target=\\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", + "outline": [ + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 3336, + "words": 375, + "headings": 7, + "estimated_token_count_total": 672 + }, + "hash": "sha256:93ca24da15095dd0bb03657f53d27771934aee055c11af529445a50e161f79a3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-remix", + "title": "Remix IDE", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-remix", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-remix/", + "preview": "[Remix IDE](https://remix.live/){target=\\_blank} offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", + "outline": [ + { + "depth": 3, + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 2473, + "words": 363, + "headings": 4, + "estimated_token_count_total": 527 + }, + "hash": "sha256:56d730c8a6d2ccf0324caf1c3f30929a93904f80e482cfcb457541e04482dbad", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-ethers", + "title": "Deploy a Basic Contract with Ethers.js", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-ethers", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-ethers.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/ethers/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, which provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 7370, + "words": 823, + "headings": 7, + "estimated_token_count_total": 1729 + }, + "hash": "sha256:ff8975b44870613c3aef0907df365f1ac981de74ec83019df232fe4bda6d9dbe", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-evm", + "title": "Deploy a Basic Contract to EVM", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-evm", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-evm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-evm/", + "preview": "Deploying smart contracts to the [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished using standard EVM development tools and workflows. This guide demonstrates how to deploy a basic smart contract using four popular EVM approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}, and [Foundry](https://getfoundry.sh/){ta", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Deployment options", + "anchor": "deployment-options" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 15629, + "words": 1659, + "headings": 4, + "estimated_token_count_total": 3341 + }, + "hash": "sha256:a4fd853afb897985602e0356551edacbce77db60bbc6556de3b6ae5af3fbc9e5", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-foundry", + "title": "Deploy a Basic Contract with Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-foundry", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Foundry](https://getfoundry.sh/){target=\\_blank}, which offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", + "outline": [ + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" + }, + { + "depth": 2, + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 2731, + "words": 355, + "headings": 7, + "estimated_token_count_total": 598 + }, + "hash": "sha256:63defd84f302f0778c90129abbe69ecd2a5d9d83c622f2b7e5c2ffc9bcb3312f", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", + "title": "Deploy a Basic Contract with Hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Hardhat](https://hardhat.org/){target=\\_blank}, which provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" + }, + { + "depth": 2, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 2, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 4051, + "words": 475, + "headings": 9, + "estimated_token_count_total": 981 + }, + "hash": "sha256:98f5c5c1a26db913e1c4c435062d214ca8c4b5f2dbed5b64d2e54c3435f06452", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-pvm", + "title": "Deploy a Basic Contract to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-pvm", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-pvm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-pvm/", + "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "JavaScript with Ethers.js", + "anchor": "javascript-with-ethersjs" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" + }, + { + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 2, + "title": "Remix IDE", + "anchor": "remix-ide" + }, + { + "depth": 3, + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Hardhat", + "anchor": "hardhat" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup-2" + }, + { + "depth": 3, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile-2" + }, + { + "depth": 3, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy-2" + }, + { + "depth": 2, + "title": "Foundry", + "anchor": "foundry" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup-3" + }, + { + "depth": 3, + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract-2" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile-3" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy-3" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 13872, + "words": 1640, + "headings": 24, + "estimated_token_count_total": 3228 + }, + "hash": "sha256:8f29b0f0b56f8c136206211a858cdc5bc27bcd9119eab179a6cd306182d910cb", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", + "title": "Deploy a Basic Contract with Remix IDE", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Remix IDE](https://remix.ethereum.org/){target=\\_blank}, which offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 2978, + "words": 430, + "headings": 6, + "estimated_token_count_total": 738 + }, + "hash": "sha256:0c00544ba0be9c0a6fa0c54bdb38045d64e95af714785b86e57f885a03b4b17a", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", + "title": "Deploy a Basic Contract to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", + "title": "Deploy an ERC-20 to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", + "categories": [ + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/", + "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Interact with Your Contract", + "anchor": "interact-with-your-contract" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 9109, + "words": 1260, + "headings": 7, + "estimated_token_count_total": 2182 + }, + "hash": "sha256:0cb418d465a51230ece5d3a56d64754f979bc6c4ad78f2cc3df537b99739e627", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20", + "title": "Deploy an ERC-20 to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20", + "categories": [ + "Basics", + "dApps", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/.deploy-basic-pvm/", + "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "JavaScript with Ethers.js", + "anchor": "javascript-with-ethersjs" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup" + }, + { + "depth": 3, + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" + }, + { + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 2, + "title": "Remix IDE", + "anchor": "remix-ide" + }, + { + "depth": 3, + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Hardhat", + "anchor": "hardhat" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup-2" + }, + { + "depth": 3, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile-2" + }, + { + "depth": 3, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy-2" + }, + { + "depth": 2, + "title": "Foundry", + "anchor": "foundry" + }, + { + "depth": 3, + "title": "Setup", + "anchor": "setup-3" + }, + { + "depth": 3, + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract-2" + }, + { + "depth": 3, + "title": "Compile", + "anchor": "compile-3" + }, + { + "depth": 3, + "title": "Deploy", + "anchor": "deploy-3" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + }, + { + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 13872, + "words": 1640, + "headings": 24, + "estimated_token_count_total": 3228 + }, + "hash": "sha256:296cba75b1d49aefa1b8636ba95ca20c3431b7eb0e93b0658add671ef5801732", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry", + "title": "Deploy a Basic Contract with Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/.foundry/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Foundry](https://getfoundry.sh/){target=\\_blank}, which offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", + "outline": [ + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" + }, + { + "depth": 2, + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 2731, + "words": 355, + "headings": 7, + "estimated_token_count_total": 598 + }, + "hash": "sha256:fdd65f6fe6d109043f11a26f1477e2bbbce1a440dbcb2b191eacfa79a28766e9", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-foundry", + "title": "Deploy an NFT to Polkadot Hub with Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-foundry", + "categories": [ + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/foundry/", + "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" + }, + { + "depth": 2, + "title": "Configure Foundry", + "anchor": "configure-foundry" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 3489, + "words": 438, + "headings": 8, + "estimated_token_count_total": 847 + }, + "hash": "sha256:c4b410125946db479b9c262a5132a31bb7730a778501c3a95910ad9d38007cf4", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", + "title": "Deploy an NFT to Polkadot Hub with Hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", + "categories": [ + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/", + "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" + }, + { + "depth": 2, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 4745, + "words": 550, + "headings": 9, + "estimated_token_count_total": 1137 + }, + "hash": "sha256:f787f9c66787c53aa5c6fccf30d622b2b617794d1292641ea256e0896d418b28", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", + "title": "Deploy an NFT to Polkadot Hub with Remix", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", + "categories": [ + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/", + "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 3754, + "words": 505, + "headings": 7, + "estimated_token_count_total": 928 + }, + "hash": "sha256:12a8debfbc05c5ac0e2c94daa40167adab837dc4e1b2731f5b48ae8bc9bc2c93", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook", + "title": "Smart Contracts Cookbook Index", + "slug": "smart-contracts-cookbook", + "categories": [ + "Basics", + "dApps", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/", + "preview": "Welcome to the Polkadot smart contracts cookbook index.", + "outline": [ + { + "depth": 2, + "title": "Get Tokens from the Faucet", + "anchor": "get-tokens-from-the-faucet" + }, + { + "depth": 2, + "title": "EVM/PVM Smart Contracts", + "anchor": "evmpvm-smart-contracts" + }, + { + "depth": 2, + "title": "Port Ethereum DApps", + "anchor": "port-ethereum-dapps" + } + ], + "stats": { + "chars": 1586, + "words": 204, + "headings": 3, + "estimated_token_count_total": 406 + }, + "hash": "sha256:ea0d085c376117436a9cf68e786da942cf88993651d4e06550f9ee03d2e810f4", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", + "title": "Deploy a Basic Contract with Hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-compile-and-test.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/foundry/compile-and-test/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-foundry-deploy-a-contract", + "title": "smart-contracts-dev-environments-foundry-deploy-a-contract", + "slug": "smart-contracts-dev-environments-foundry-deploy-a-contract", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-deploy-a-contract.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/foundry/deploy-a-contract/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-foundry-get-started", + "title": "Use Foundry with Polkadot Hub", + "slug": "smart-contracts-dev-environments-foundry-get-started", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-get-started.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/foundry/get-started/", + "preview": "!!! warning Consider that features like Anvil (Foundry's local blockchain) and `forge test` (for running Solidity tests) are not yet supported in `foundry-polkadot`.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" + }, + { + "depth": 2, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 2, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 4051, + "words": 475, + "headings": 9, + "estimated_token_count_total": 981 + }, + "hash": "sha256:72e41f816f07026d96c803f399c71852aa1151c464e79cec3e1746b282d5eaae", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", + "title": "Deploy a Basic Contract with Remix IDE", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Remix IDE](https://remix.ethereum.org/){target=\\_blank}, which offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Access Remix", + "anchor": "access-remix" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 2978, + "words": 430, + "headings": 6, + "estimated_token_count_total": 738 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat", + "title": "Deploy an ERC-20 to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat", + "categories": [ + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/", + "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" + }, + { + "depth": 2, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 2, + "title": "Compile your Contract", + "anchor": "compile-your-contract" + }, + { + "depth": 2, + "title": "Test your Contract", + "anchor": "test-your-contract" + }, + { + "depth": 2, + "title": "Deploy your Contract", + "anchor": "deploy-your-contract" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 8131, + "words": 1205, + "headings": 8, + "estimated_token_count_total": 2156 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", + "title": "Deploy an ERC-20 to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", + "categories": [ + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/", + "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Interact with Your Contract", + "anchor": "interact-with-your-contract" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 9121, + "words": 1261, + "headings": 7, + "estimated_token_count_total": 2183 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-hardhat-compile-and-test", + "title": "smart-contracts-dev-environments-hardhat-compile-and-test", + "slug": "smart-contracts-dev-environments-hardhat-compile-and-test", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-compile-and-test.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/compile-and-test/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-hardhat-deploy-a-contract", + "title": "smart-contracts-dev-environments-hardhat-deploy-a-contract", + "slug": "smart-contracts-dev-environments-hardhat-deploy-a-contract", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-deploy-a-contract.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/deploy-a-contract/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-hardhat-get-started", + "title": "Use Hardhat with Polkadot Hub", + "slug": "smart-contracts-dev-environments-hardhat-get-started", + "categories": [ + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/get-started/", + "preview": "Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer.", + "outline": [ + { + "depth": 2, + "title": "Overview", + "anchor": "overview" + }, + { + "depth": 2, + "title": "Hardhat Workflow", + "anchor": "hardhat-workflow" + }, + { + "depth": 2, + "title": "Project Anatomy", + "anchor": "project-anatomy" + }, + { + "depth": 2, + "title": "Core Functionalities", + "anchor": "core-functionalities" + }, + { + "depth": 3, + "title": "Project Setup", + "anchor": "project-setup" + }, + { + "depth": 3, + "title": "Contract Compilation", + "anchor": "contract-compilation" + }, + { + "depth": 3, + "title": "Testing Environment", + "anchor": "testing-environment" + }, + { + "depth": 3, + "title": "Deployment", + "anchor": "deployment" + }, + { + "depth": 3, + "title": "Contract Interaction", + "anchor": "contract-interaction" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 5817, + "words": 730, + "headings": 10, + "estimated_token_count_total": 1282 + }, + "hash": "sha256:95352e48926dd24d6363218dfd703840871be8822bc522f45bf343436612eff4", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-hardhat-install-and-config", + "title": "smart-contracts-dev-environments-hardhat-install-and-config", + "slug": "smart-contracts-dev-environments-hardhat-install-and-config", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-install-and-config.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/install-and-config/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-hardhat-troubleshooting", + "title": "smart-contracts-dev-environments-hardhat-troubleshooting", + "slug": "smart-contracts-dev-environments-hardhat-troubleshooting", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-troubleshooting.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/troubleshooting/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-hardhat-verify-a-contract", + "title": "smart-contracts-dev-environments-hardhat-verify-a-contract", + "slug": "smart-contracts-dev-environments-hardhat-verify-a-contract", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-verify-a-contract.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/verify-a-contract/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-local-dev-node", + "title": "Local Development Node", + "slug": "smart-contracts-dev-environments-local-dev-node", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-local-dev-node.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/local-dev-node/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Install the Revive Dev Node and ETH-RPC Adapter", + "anchor": "install-the-revive-dev-node-and-eth-rpc-adapter" + }, + { + "depth": 2, + "title": "Run the Local Node", + "anchor": "run-the-local-node" + } + ], + "stats": { + "chars": 9052, + "words": 1431, + "headings": 4, + "estimated_token_count_total": 2428 + }, + "hash": "sha256:e3d8b84cb2cee7010978582998b2269296a042aec53fb016388690ab6adf355e", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-remix-deploy-a-contract", + "title": "smart-contracts-dev-environments-remix-deploy-a-contract", + "slug": "smart-contracts-dev-environments-remix-deploy-a-contract", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-remix-get-started", + "title": "Use the Polkadot Remix IDE", + "slug": "smart-contracts-dev-environments-remix-get-started", + "categories": [ + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/get-started/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
- :octicons-code-16:{ .lg .middle } __Deploy NFTs Using Remix IDE__", + "outline": [ + { + "depth": 2, + "title": "Overview", + "anchor": "overview" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Accessing Remix IDE", + "anchor": "accessing-remix-ide" + }, + { + "depth": 2, + "title": "Creating a New Contract", + "anchor": "creating-a-new-contract" + }, + { + "depth": 2, + "title": "Compiling Your Contract", + "anchor": "compiling-your-contract" + }, + { + "depth": 2, + "title": "Deploying Contracts", + "anchor": "deploying-contracts" + }, + { + "depth": 2, + "title": "Interacting with Contracts", + "anchor": "interacting-with-contracts" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 6664, + "words": 905, + "headings": 8, + "estimated_token_count_total": 1347 + }, + "hash": "sha256:7589fa1dbdbf5748892ab6d42fc784d833f33e254bd3f95ee58424effcd38323", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-remix-troubleshooting", + "title": "smart-contracts-dev-environments-remix-troubleshooting", + "slug": "smart-contracts-dev-environments-remix-troubleshooting", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-remix-verify-a-contract", + "title": "smart-contracts-dev-environments-remix-verify-a-contract", + "slug": "smart-contracts-dev-environments-remix-verify-a-contract", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/verify-a-contract/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-explorers", + "title": "Block Explorers", + "slug": "smart-contracts-explorers", + "categories": [ + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-explorers.md", + "html_url": "https://docs.polkadot.com/smart-contracts/explorers/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Core Functionality", + "anchor": "core-functionality" + }, + { + "depth": 2, + "title": "Available Block Explorers", + "anchor": "available-block-explorers" + }, + { + "depth": 3, + "title": "BlockScout", + "anchor": "blockscout" + } + ], + "stats": { + "chars": 1793, + "words": 223, + "headings": 4, + "estimated_token_count_total": 309 + }, + "hash": "sha256:93e8a3043d65583e3d66f8f5f0ed6f4ef89a908ef85da2b6ca906a1100b7dded", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-faucet", + "title": "Faucet", + "slug": "smart-contracts-faucet", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-faucet.md", + "html_url": "https://docs.polkadot.com/smart-contracts/faucet/", + "preview": "Test tokens allow you to experiment with smart contracts, test transactions, and validate your dApp functionality without using real cryptocurrency.", + "outline": [ + { + "depth": 2, + "title": "Get Test Tokens", + "anchor": "get-test-tokens" + }, + { + "depth": 2, + "title": "Things to Consider", + "anchor": "things-to-consider" + }, + { + "depth": 2, + "title": "Using Your Test Tokens", + "anchor": "using-your-test-tokens" + } + ], + "stats": { + "chars": 1890, + "words": 279, + "headings": 3, + "estimated_token_count_total": 313 + }, + "hash": "sha256:c609bc98cba5efa2d2a808548cf93ad9d0a06455b35a8fd9f534daf52824f506", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-for-eth-devs-accounts", + "title": "Accounts in Asset Hub Smart Contracts", + "slug": "smart-contracts-for-eth-devs-accounts", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-accounts.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/accounts/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Address Types and Mappings", + "anchor": "address-types-and-mappings" + }, + { + "depth": 3, + "title": "Ethereum to Polkadot Mapping", + "anchor": "ethereum-to-polkadot-mapping" + }, + { + "depth": 3, + "title": "Polkadot to Ethereum Mapping", + "anchor": "polkadot-to-ethereum-mapping" + }, + { + "depth": 3, + "title": "Account Mapping for Native Polkadot Accounts", + "anchor": "account-mapping-for-native-polkadot-accounts" + }, + { + "depth": 2, + "title": "Account Registration", + "anchor": "account-registration" + }, + { + "depth": 2, + "title": "Fallback Accounts", + "anchor": "fallback-accounts" + }, + { + "depth": 2, + "title": "Contract Address Generation", + "anchor": "contract-address-generation" + }, + { + "depth": 2, + "title": "Security Considerations", + "anchor": "security-considerations" + } + ], + "stats": { + "chars": 8521, + "words": 1138, + "headings": 9, + "estimated_token_count_total": 1816 + }, + "hash": "sha256:f50cd1177dd4aff8eb031d6f21cb640f8187a7f2dd0edcaef5c73354a378e44d", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-for-eth-devs-blocks-transactions-fees", + "title": "Transactions and Fees on Asset Hub", + "slug": "smart-contracts-for-eth-devs-blocks-transactions-fees", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-blocks-transactions-fees.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/blocks-transactions-fees/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Smart Contract Blocks", + "anchor": "smart-contract-blocks" + }, + { + "depth": 2, + "title": "Smart Contract Transactions", + "anchor": "smart-contract-transactions" + }, + { + "depth": 3, + "title": "EVM Transaction Types", + "anchor": "evm-transaction-types" + }, + { + "depth": 2, + "title": "Fees and Gas", + "anchor": "fees-and-gas" + }, + { + "depth": 3, + "title": "Gas Model Overview", + "anchor": "gas-model-overview" + }, + { + "depth": 3, + "title": "Fee Components", + "anchor": "fee-components" + }, + { + "depth": 3, + "title": "Gas Calculation and Conversion", + "anchor": "gas-calculation-and-conversion" + } + ], + "stats": { + "chars": 6366, + "words": 791, + "headings": 8, + "estimated_token_count_total": 1182 + }, + "hash": "sha256:9542f40acae725e628f4c3155ad1e7e0e18b2eb518484856ad439a1d9f86d1f3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-for-eth-devs-contract-deployment", + "title": "Contract Deployment", + "slug": "smart-contracts-for-eth-devs-contract-deployment", + "categories": [ + "Smart Contracts", + "Basics" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-contract-deployment.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/contract-deployment/", + "preview": "Polkadot's smart contract platform supports two distinct virtual machine backends: Rust Ethereum Virtual Machine (REVM) and PolkaVM. Each backend has its own deployment characteristics and optimization strategies. REVM provides full Ethereum compatibility with familiar single-step deployment, while the RISC-V-based PolkaVM uses a more structured two-step approach optimized for its architecture. Understanding these differences ensures smooth deployment regardless of which backend you choose for y", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "REVM Deployment", + "anchor": "revm-deployment" + }, + { + "depth": 2, + "title": "PolkaVM Deployment", + "anchor": "polkavm-deployment" + }, + { + "depth": 3, + "title": "Standard Contract Deployment", + "anchor": "standard-contract-deployment" + }, + { + "depth": 3, + "title": "Two-Step Deployment Model", + "anchor": "two-step-deployment-model" + }, + { + "depth": 3, + "title": "Factory Pattern Considerations", + "anchor": "factory-pattern-considerations" + }, + { + "depth": 3, + "title": "Migration Strategy for Factory Contracts", + "anchor": "migration-strategy-for-factory-contracts" + }, + { + "depth": 3, + "title": "Architecture-Specific Limitations", + "anchor": "architecture-specific-limitations" + }, + { + "depth": 3, + "title": "On-Chain Constructors", + "anchor": "on-chain-constructors" + }, + { + "depth": 2, + "title": "Gas Estimation vs Actual Consumption", + "anchor": "gas-estimation-vs-actual-consumption" + }, + { + "depth": 2, + "title": "Deployment Comparison", + "anchor": "deployment-comparison" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } + ], + "stats": { + "chars": 5999, + "words": 766, + "headings": 12, + "estimated_token_count_total": 1133 + }, + "hash": "sha256:0792e3956242eb8e08ab82e2d73964c381074cc8b1ea46f396d136856fa6cc07", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-for-eth-devs-dual-vm-stack", + "title": "Dual Virtual Machine Stack", + "slug": "smart-contracts-for-eth-devs-dual-vm-stack", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Migrate from EVM", + "anchor": "migrate-from-evm" + }, + { + "depth": 2, + "title": "Upgrade to PolkaVM", + "anchor": "upgrade-to-polkavm" + }, + { + "depth": 2, + "title": "Architecture", + "anchor": "architecture" + }, + { + "depth": 3, + "title": "Revive Pallet", + "anchor": "revive-pallet" + }, + { + "depth": 3, + "title": "PolkaVM Design Fundamentals", + "anchor": "polkavm-design-fundamentals" + }, + { + "depth": 2, + "title": "Where To Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 5383, + "words": 702, + "headings": 7, + "estimated_token_count_total": 986 + }, + "hash": "sha256:2d918017faecf489ec786f34de6cd4366a86e9f1cecfbb7722cc03079e6b64ea", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-for-eth-devs-gas-model", + "title": "Gas Model on the Polkadot Hub", + "slug": "smart-contracts-for-eth-devs-gas-model", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-gas-model.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/gas-model/", + "preview": "The Polkadot Hub implements a gas model that bridges Ethereum's familiar gas concept with Polkadot's more sophisticated resource metering system. This page explains how gas works in the Polkadot Hub and what developers need to know when building smart contracts.", + "outline": [ + { + "depth": 2, + "title": "Overview", + "anchor": "overview" + }, + { + "depth": 2, + "title": "Understanding Resources in the Polkadot Hub", + "anchor": "understanding-resources-in-the-polkadot-hub" + }, + { + "depth": 2, + "title": "Gas vs Weight", + "anchor": "gas-vs-weight" + }, + { + "depth": 2, + "title": "How Gas Estimation Works", + "anchor": "how-gas-estimation-works" + }, + { + "depth": 2, + "title": "Dynamic Gas Pricing", + "anchor": "dynamic-gas-pricing" + }, + { + "depth": 2, + "title": "Transaction Execution Flow", + "anchor": "transaction-execution-flow" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } + ], + "stats": { + "chars": 5234, + "words": 751, + "headings": 7, + "estimated_token_count_total": 1046 + }, + "hash": "sha256:dd29fab6e3c00d720b10effa4e50373a6fe9ab4b7bfd3aea892c7fa9c84318a2", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-for-eth-devs-json-rpc-apis", + "title": "JSON-RPC APIs", + "slug": "smart-contracts-for-eth-devs-json-rpc-apis", + "categories": [ + "Reference" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Available Methods", + "anchor": "available-methods" + }, + { + "depth": 3, + "title": "eth_accounts", + "anchor": "eth_accounts" + }, + { + "depth": 3, + "title": "eth_blockNumber", + "anchor": "eth_blocknumber" + }, + { + "depth": 3, + "title": "eth_call", + "anchor": "eth_call" + }, + { + "depth": 3, + "title": "eth_chainId", + "anchor": "eth_chainid" + }, + { + "depth": 3, + "title": "eth_estimateGas", + "anchor": "eth_estimategas" + }, + { + "depth": 3, + "title": "eth_gasPrice", + "anchor": "eth_gasprice" + }, + { + "depth": 3, + "title": "eth_getBalance", + "anchor": "eth_getbalance" + }, + { + "depth": 3, + "title": "eth_getBlockByHash", + "anchor": "eth_getblockbyhash" + }, + { + "depth": 3, + "title": "eth_getBlockByNumber", + "anchor": "eth_getblockbynumber" + }, + { + "depth": 3, + "title": "eth_getBlockTransactionCountByNumber", + "anchor": "eth_getblocktransactioncountbynumber" + }, + { + "depth": 3, + "title": "eth_getBlockTransactionCountByHash", + "anchor": "eth_getblocktransactioncountbyhash" + }, + { + "depth": 3, + "title": "eth_getCode", + "anchor": "eth_getcode" + }, + { + "depth": 3, + "title": "eth_getLogs", + "anchor": "eth_getlogs" + }, + { + "depth": 3, + "title": "eth_getStorageAt", + "anchor": "eth_getstorageat" + }, + { + "depth": 3, + "title": "eth_getTransactionCount", + "anchor": "eth_gettransactioncount" + }, + { + "depth": 3, + "title": "eth_getTransactionByHash", + "anchor": "eth_gettransactionbyhash" + }, + { + "depth": 3, + "title": "eth_getTransactionByBlockNumberAndIndex", + "anchor": "eth_gettransactionbyblocknumberandindex" + }, + { + "depth": 3, + "title": "eth_getTransactionByBlockHashAndIndex", + "anchor": "eth_gettransactionbyblockhashandindex" + }, + { + "depth": 3, + "title": "eth_getTransactionReceipt", + "anchor": "eth_gettransactionreceipt" + }, + { + "depth": 3, + "title": "eth_maxPriorityFeePerGas", + "anchor": "eth_maxpriorityfeepergas" + }, + { + "depth": 3, + "title": "eth_sendRawTransaction", + "anchor": "eth_sendrawtransaction" + }, + { + "depth": 3, + "title": "eth_sendTransaction", + "anchor": "eth_sendtransaction" + }, + { + "depth": 3, + "title": "eth_syncing", + "anchor": "eth_syncing" + }, + { + "depth": 3, + "title": "net_listening", + "anchor": "net_listening" + }, + { + "depth": 3, + "title": "net_peerCount", + "anchor": "net_peercount" + }, + { + "depth": 3, + "title": "net_version", + "anchor": "net_version" + }, + { + "depth": 3, + "title": "system_health", + "anchor": "system_health" + }, + { + "depth": 3, + "title": "web3_clientVersion", + "anchor": "web3_clientversion" + }, + { + "depth": 3, + "title": "debug_traceBlockByNumber", + "anchor": "debug_traceblockbynumber" + }, + { + "depth": 3, + "title": "debug_traceTransaction", + "anchor": "debug_tracetransaction" + }, + { + "depth": 3, + "title": "debug_traceCall", + "anchor": "debug_tracecall" + }, + { + "depth": 2, + "title": "Response Format", + "anchor": "response-format" + }, + { + "depth": 2, + "title": "Error Handling", + "anchor": "error-handling" + } + ], + "stats": { + "chars": 31444, + "words": 3848, + "headings": 35, + "estimated_token_count_total": 9562 + }, + "hash": "sha256:1fb7a20bc4a799a771954720428029419ec73afa640e589590c43dd041a7e307", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-for-eth-devs-migration", + "title": "Migration FAQs and Considerations", + "slug": "smart-contracts-for-eth-devs-migration", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/", + "preview": "This guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Migration Considerations", + "anchor": "migration-considerations" + }, + { + "depth": 2, + "title": "Migration Checklist", + "anchor": "migration-checklist" + }, + { + "depth": 2, + "title": "Migration FAQs", + "anchor": "migration-faqs" + }, + { + "depth": 3, + "title": "Which backend should I choose?", + "anchor": "which-backend-should-i-choose" + }, + { + "depth": 3, + "title": "Do I need to rewrite my Solidity code?", + "anchor": "do-i-need-to-rewrite-my-solidity-code" + }, + { + "depth": 3, + "title": "What about factory contracts?", + "anchor": "what-about-factory-contracts" + }, + { + "depth": 3, + "title": "How do gas costs compare?", + "anchor": "how-do-gas-costs-compare" + }, + { + "depth": 3, + "title": "Which Solidity features are not supported?", + "anchor": "which-solidity-features-are-not-supported" + }, + { + "depth": 3, + "title": "How do I handle the existential deposit?", + "anchor": "how-do-i-handle-the-existential-deposit" + }, + { + "depth": 3, + "title": "Can I use my existing development tools?", + "anchor": "can-i-use-my-existing-development-tools" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } + ], + "stats": { + "chars": 6247, + "words": 803, + "headings": 12, + "estimated_token_count_total": 1322 + }, + "hash": "sha256:bf9b21750158389c387b92f2165947e5f5cff752f5d163680ee37493710e81d7", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-get-started", + "title": "Get Started with Smart Contracts", + "slug": "smart-contracts-get-started", + "categories": [ + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md", + "html_url": "https://docs.polkadot.com/smart-contracts/get-started/", + "preview": "This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need.", + "outline": [ + { + "depth": 2, + "title": "Quick Starts", + "anchor": "quick-starts" + }, + { + "depth": 2, + "title": "Build and Test Locally", + "anchor": "build-and-test-locally" + }, + { + "depth": 2, + "title": "Ethereum Developer Resources", + "anchor": "ethereum-developer-resources" + }, + { + "depth": 2, + "title": "Cookbook: Hands‑on Tutorials", + "anchor": "cookbook-handson-tutorials" + }, + { + "depth": 2, + "title": "Libraries", + "anchor": "libraries" + }, + { + "depth": 2, + "title": "Integrations", + "anchor": "integrations" + }, + { + "depth": 2, + "title": "Precompiles", + "anchor": "precompiles" + } + ], + "stats": { + "chars": 10103, + "words": 937, + "headings": 7, + "estimated_token_count_total": 2888 + }, + "hash": "sha256:224a9f69d4613a5f1afdbc1f05379add8321fe159e32c71db003bbe08ff8e976", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-integrations-indexers", + "title": "smart-contracts-integrations-indexers", + "slug": "smart-contracts-integrations-indexers", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-indexers.md", + "html_url": "https://docs.polkadot.com/smart-contracts/integrations/indexers/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-integrations-oracles", + "title": "smart-contracts-integrations-oracles", + "slug": "smart-contracts-integrations-oracles", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-oracles.md", + "html_url": "https://docs.polkadot.com/smart-contracts/integrations/oracles/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-integrations-wallets", + "title": "Wallets for Polkadot Hub", + "slug": "smart-contracts-integrations-wallets", + "categories": [ + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md", + "html_url": "https://docs.polkadot.com/smart-contracts/integrations/wallets/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Connect Your Wallet", + "anchor": "connect-your-wallet" + }, + { + "depth": 3, + "title": "MetaMask", + "anchor": "metamask" + }, + { + "depth": 3, + "title": "SubWallet", + "anchor": "subwallet" + }, + { + "depth": 3, + "title": "Talisman", + "anchor": "talisman" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } + ], + "stats": { + "chars": 7340, + "words": 1041, + "headings": 6, + "estimated_token_count_total": 1627 + }, + "hash": "sha256:65809486f62f60c6a6ac8109f9f027361683c23f639991a045ec5c057b665026", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-libraries-ethers-js", + "title": "Deploy Contracts to Polkadot Hub with Ethers.js", + "slug": "smart-contracts-libraries-ethers-js", + "categories": [ + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-ethers-js.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/ethers-js/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Project Structure", + "anchor": "project-structure" + }, + { + "depth": 2, + "title": "Set Up the Project", + "anchor": "set-up-the-project" + }, + { + "depth": 2, + "title": "Install Dependencies", + "anchor": "install-dependencies" + }, + { + "depth": 2, + "title": "Set Up the Ethers.js Provider", + "anchor": "set-up-the-ethersjs-provider" + }, + { + "depth": 2, + "title": "Compile Contracts", + "anchor": "compile-contracts" + }, + { + "depth": 3, + "title": "Install the Revive Library", + "anchor": "install-the-revive-library" + }, + { + "depth": 3, + "title": "Sample Storage Smart Contract", + "anchor": "sample-storage-smart-contract" + }, + { + "depth": 3, + "title": "Compile the Smart Contract", + "anchor": "compile-the-smart-contract" + }, + { + "depth": 2, + "title": "Deploy the Compiled Contract", + "anchor": "deploy-the-compiled-contract" + }, + { + "depth": 2, + "title": "Interact with the Contract", + "anchor": "interact-with-the-contract" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 20457, + "words": 2333, + "headings": 13, + "estimated_token_count_total": 4474 + }, + "hash": "sha256:c74a28d8d62369591c5734535136508db3d1f7380e486fd214f98d433cafd6e7", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-libraries-viem", + "title": "viem for Polkadot Hub Smart Contracts", + "slug": "smart-contracts-libraries-viem", + "categories": [ + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-viem.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/viem/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Project Structure", + "anchor": "project-structure" + }, + { + "depth": 2, + "title": "Set Up the Project", + "anchor": "set-up-the-project" + }, + { + "depth": 2, + "title": "Install Dependencies", + "anchor": "install-dependencies" + }, + { + "depth": 2, + "title": "Initialize Project", + "anchor": "initialize-project" + }, + { + "depth": 2, + "title": "Set Up the Chain Configuration", + "anchor": "set-up-the-chain-configuration" + }, + { + "depth": 2, + "title": "Set Up the viem Client", + "anchor": "set-up-the-viem-client" + }, + { + "depth": 2, + "title": "Set Up a Wallet", + "anchor": "set-up-a-wallet" + }, + { + "depth": 2, + "title": "Sample Smart Contract", + "anchor": "sample-smart-contract" + }, + { + "depth": 2, + "title": "Compile the Contract", + "anchor": "compile-the-contract" + }, + { + "depth": 2, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 2, + "title": "Interact with the Contract", + "anchor": "interact-with-the-contract" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 16600, + "words": 1940, + "headings": 14, + "estimated_token_count_total": 3891 + }, + "hash": "sha256:e27657e4e4a14fe86f424b96631946ec36fb90d277e6010b6cbd64c4769aba8a", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-libraries-wagmi", + "title": "Wagmi for Polkadot Hub Smart Contracts", + "slug": "smart-contracts-libraries-wagmi", + "categories": [ + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-wagmi.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/wagmi/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Set Up the Project", + "anchor": "set-up-the-project" + }, + { + "depth": 2, + "title": "Install Dependencies", + "anchor": "install-dependencies" + }, + { + "depth": 2, + "title": "Configure Wagmi for Polkadot Hub", + "anchor": "configure-wagmi-for-polkadot-hub" + }, + { + "depth": 2, + "title": "Set Up the Wagmi Provider", + "anchor": "set-up-the-wagmi-provider" + }, + { + "depth": 2, + "title": "Connect a Wallet", + "anchor": "connect-a-wallet" + }, + { + "depth": 2, + "title": "Fetch Blockchain Data", + "anchor": "fetch-blockchain-data" + }, + { + "depth": 2, + "title": "Interact with Deployed Contract", + "anchor": "interact-with-deployed-contract" + }, + { + "depth": 2, + "title": "Integrate Components", + "anchor": "integrate-components" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-deploy-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/deploy-a-contract/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 13604, + "words": 1515, + "headings": 10, + "estimated_token_count_total": 3250 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:bc771f912627fa09cad64adab1bc81c052f650d6c5a3b4f0c91883a98f6628da", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-hardhat-get-started", - "title": "Use Hardhat with Polkadot Hub", - "slug": "smart-contracts-dev-environments-hardhat-get-started", + "id": "smart-contracts-libraries-web3-js", + "title": "Web3.js", + "slug": "smart-contracts-libraries-web3-js", "categories": [ "Smart Contracts", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/get-started/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
- :octicons-code-16:{ .lg .middle } __Test and Deploy with Hardhat__", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/web3-js/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. !!! warning Web3.js has been [sunset](https://blog.chainsafe.io/web3-js-sunset/){target=\\_blank}. You can find guides on using [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank} and [viem](/smart-contracts/libraries/viem/){target=\\_blank} in the Libraries section.", "outline": [ { "depth": 2, - "title": "Overview", - "anchor": "overview" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, @@ -7408,43 +13221,38 @@ }, { "depth": 2, - "title": "Set Up Hardhat", - "anchor": "set-up-hardhat" - }, - { - "depth": 2, - "title": "Compile Your Contract", - "anchor": "compile-your-contract" + "title": "Project Structure", + "anchor": "project-structure" }, { "depth": 2, - "title": "Set Up a Testing Environment", - "anchor": "set-up-a-testing-environment" + "title": "Set Up the Project", + "anchor": "set-up-the-project" }, { "depth": 2, - "title": "Test Your Contract", - "anchor": "test-your-contract" + "title": "Install Dependencies", + "anchor": "install-dependencies" }, { "depth": 2, - "title": "Deploy to a Local Node", - "anchor": "deploy-to-a-local-node" + "title": "Set Up the Web3 Provider", + "anchor": "set-up-the-web3-provider" }, { "depth": 2, - "title": "Deploying to a Live Network", - "anchor": "deploying-to-a-live-network" + "title": "Compile Contracts", + "anchor": "compile-contracts" }, { "depth": 2, - "title": "Interacting with Your Contract", - "anchor": "interacting-with-your-contract" + "title": "Contract Deployment", + "anchor": "contract-deployment" }, { "depth": 2, - "title": "Upgrading the Plugin", - "anchor": "upgrading-the-plugin" + "title": "Interact with the Contract", + "anchor": "interact-with-the-contract" }, { "depth": 2, @@ -7453,84 +13261,189 @@ } ], "stats": { - "chars": 18514, - "words": 2477, - "headings": 11, - "estimated_token_count_total": 4190 + "chars": 13266, + "words": 1579, + "headings": 10, + "estimated_token_count_total": 3035 }, - "hash": "sha256:1729ad83ad381a90752540644d400c60add3555e5da296ab455442be81d32f8c", + "hash": "sha256:f0d36333d0d3afff7f6374a61d0f6d1fb878c9ef4c4e4c24447745661dbe59d0", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-hardhat-install-and-config", - "title": "smart-contracts-dev-environments-hardhat-install-and-config", - "slug": "smart-contracts-dev-environments-hardhat-install-and-config", + "id": "smart-contracts-libraries-web3-py", + "title": "Web3.py", + "slug": "smart-contracts-libraries-web3-py", "categories": [ - "Uncategorized" + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-py.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/web3-py/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Set Up the Project", + "anchor": "set-up-the-project" + }, + { + "depth": 2, + "title": "Set Up the Web3 Provider", + "anchor": "set-up-the-web3-provider" + }, + { + "depth": 2, + "title": "Contract Deployment", + "anchor": "contract-deployment" + }, + { + "depth": 2, + "title": "Interact with the Contract", + "anchor": "interact-with-the-contract" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-install-and-config.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/install-and-config/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 11627, + "words": 1333, + "headings": 6, + "estimated_token_count_total": 2509 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:205892e350168b3d0da7ccc280c67c3217ad1e45e87a53d124fa1dd69661aa5e", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-hardhat-troubleshooting", - "title": "smart-contracts-dev-environments-hardhat-troubleshooting", - "slug": "smart-contracts-dev-environments-hardhat-troubleshooting", + "id": "smart-contracts-overview", + "title": "Smart Contracts Overview", + "slug": "smart-contracts-overview", "categories": [ - "Uncategorized" + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md", + "html_url": "https://docs.polkadot.com/smart-contracts/overview/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Native Smart Contracts", + "anchor": "native-smart-contracts" + }, + { + "depth": 3, + "title": "Introduction", + "anchor": "introduction-2" + }, + { + "depth": 3, + "title": "Smart Contract Development", + "anchor": "smart-contract-development" + }, + { + "depth": 3, + "title": "Technical Architecture", + "anchor": "technical-architecture" + }, + { + "depth": 3, + "title": "Development Tools and Resources", + "anchor": "development-tools-and-resources" + }, + { + "depth": 3, + "title": "Cross-Chain Capabilities", + "anchor": "cross-chain-capabilities" + }, + { + "depth": 3, + "title": "Use Cases", + "anchor": "use-cases" + }, + { + "depth": 2, + "title": "Other Smart Contract Environments", + "anchor": "other-smart-contract-environments" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-troubleshooting.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/troubleshooting/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 6305, + "words": 804, + "headings": 10, + "estimated_token_count_total": 1122 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:ee87115c828928c82937de26f5f938cecd4c3bb1225fdb61627e8092e6ea5951", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-hardhat-verify-a-contract", - "title": "smart-contracts-dev-environments-hardhat-verify-a-contract", - "slug": "smart-contracts-dev-environments-hardhat-verify-a-contract", + "id": "smart-contracts-precompiles-eth-native", + "title": "Ethereum-Native Precompiles", + "slug": "smart-contracts-precompiles-eth-native", "categories": [ - "Uncategorized" + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-eth-native.md", + "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/eth-native/", + "preview": "Ethereum-native precompiles are special contract implementations that provide essential cryptographic and utility functions at the runtime level. These precompiles are available at predefined addresses and offer optimized, native implementations of commonly used operations that would be computationally expensive or impractical to implement in pure contract code.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "How to Use Precompiles", + "anchor": "how-to-use-precompiles" + }, + { + "depth": 2, + "title": "Standard Precompiles in Polkadot Hub", + "anchor": "standard-precompiles-in-polkadot-hub" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-verify-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/verify-a-contract/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 5232, + "words": 532, + "headings": 4, + "estimated_token_count_total": 1192 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:f17db5daca8feae70ce428e03a5a4870ef87dfc8571b07376327cd80d057b759", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-local-dev-node", - "title": "Local Development Node", - "slug": "smart-contracts-dev-environments-local-dev-node", + "id": "smart-contracts-precompiles-xcm", + "title": "Interact with the XCM Precompile", + "slug": "smart-contracts-precompiles-xcm", "categories": [ "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-local-dev-node.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/local-dev-node/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-xcm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/xcm/", + "preview": "The [XCM (Cross-Consensus Message)](/parachains/interoperability/get-started/){target=\\_blank} precompile enables Polkadot Hub developers to access XCM functionality directly from their smart contracts using a Solidity interface.", "outline": [ { "depth": 2, @@ -7539,65 +13452,105 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Precompile Interface", + "anchor": "precompile-interface" }, { "depth": 2, - "title": "Install the Revive Dev Node and ETH-RPC Adapter", - "anchor": "install-the-revive-dev-node-and-eth-rpc-adapter" + "title": "Interact with the XCM Precompile", + "anchor": "interact-with-the-xcm-precompile" + }, + { + "depth": 3, + "title": "Weigh a Message", + "anchor": "weigh-a-message" + }, + { + "depth": 3, + "title": "Execute a Message", + "anchor": "execute-a-message" + }, + { + "depth": 3, + "title": "Send a Message", + "anchor": "send-a-message" }, { "depth": 2, - "title": "Run the Local Node", - "anchor": "run-the-local-node" + "title": "Cross Contract Calls", + "anchor": "cross-contract-calls" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + }, + { + "depth": 2, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 9052, - "words": 1431, - "headings": 4, - "estimated_token_count_total": 2428 + "chars": 10705, + "words": 1436, + "headings": 9, + "estimated_token_count_total": 2325 }, - "hash": "sha256:8ea9865b49c4d7cea7eed22c66c1c9616d3da837ba7c9047abfc7c0396441aab", + "hash": "sha256:c084190ea7d676128e7e399e8fe88598ca150f88d684db279a687ee1c3956120", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-remix-deploy-a-contract", - "title": "smart-contracts-dev-environments-remix-deploy-a-contract", - "slug": "smart-contracts-dev-environments-remix-deploy-a-contract", + "id": "smart-contracts-precompiles", + "title": "Advanced Functionalities via Precompiles", + "slug": "smart-contracts-precompiles", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/", - "preview": "TODO", - "outline": [], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles.md", + "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "What are Precompiles?", + "anchor": "what-are-precompiles" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" + } + ], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 2525, + "words": 328, + "headings": 3, + "estimated_token_count_total": 412 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:a40e3f34f70db22bfe39e40d68dc5a53a726ce47cb73b602d8605355c61ffd22", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-remix-get-started", - "title": "Use the Polkadot Remix IDE", - "slug": "smart-contracts-dev-environments-remix-get-started", + "id": "tutorials-dapps-remark-tutorial", + "title": "PAPI Account Watcher Tutorial", + "slug": "tutorials-dapps-remark-tutorial", "categories": [ - "Smart Contracts", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/get-started/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
- :octicons-code-16:{ .lg .middle } __Deploy NFTs Using Remix IDE__", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-dapps-remark-tutorial.md", + "html_url": "https://docs.polkadot.com/tutorials/dapps/remark-tutorial/", + "preview": "This tutorial demonstrates how to build a simple command-line interface (CLI) application that monitors a user's account on the relay chain for the [`system.remarkWithEvent`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.remark_with_event){target=\\_blank} extrinsic, using the [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank}.", "outline": [ { "depth": 2, - "title": "Overview", - "anchor": "overview" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, @@ -7606,173 +13559,126 @@ }, { "depth": 2, - "title": "Accessing Remix IDE", - "anchor": "accessing-remix-ide" + "title": "Clone the Repository", + "anchor": "clone-the-repository" }, { "depth": 2, - "title": "Creating a New Contract", - "anchor": "creating-a-new-contract" + "title": "Explore the Template (Light Clients)", + "anchor": "explore-the-template-light-clients" }, { "depth": 2, - "title": "Compiling Your Contract", - "anchor": "compiling-your-contract" + "title": "Create the CLI", + "anchor": "create-the-cli" }, { "depth": 2, - "title": "Deploying Contracts", - "anchor": "deploying-contracts" + "title": "Watch for Remarks", + "anchor": "watch-for-remarks" }, { "depth": 2, - "title": "Interacting with Contracts", - "anchor": "interacting-with-contracts" + "title": "Compile and Run", + "anchor": "compile-and-run" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Test the CLI", + "anchor": "test-the-cli" + }, + { + "depth": 2, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 6664, - "words": 905, - "headings": 8, - "estimated_token_count_total": 1347 - }, - "hash": "sha256:ceef35da1647c5f10217ad5058a5a932f0931e1c83e624539f0b67fd075eacb4", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-remix-troubleshooting", - "title": "smart-contracts-dev-environments-remix-troubleshooting", - "slug": "smart-contracts-dev-environments-remix-troubleshooting", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 8044, + "words": 1111, + "headings": 9, + "estimated_token_count_total": 2249 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:1368f6d49bccb7ba0e642cc58ea2c97ca95ae45e390cb9fa2ab11b0b41de52f4", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-remix-verify-a-contract", - "title": "smart-contracts-dev-environments-remix-verify-a-contract", - "slug": "smart-contracts-dev-environments-remix-verify-a-contract", + "id": "tutorials-dapps", + "title": "Decentralized Application Tutorials", + "slug": "tutorials-dapps", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/verify-a-contract/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-explorers", - "title": "Block Explorers", - "slug": "smart-contracts-explorers", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-explorers.md", - "html_url": "https://docs.polkadot.com/smart-contracts/explorers/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-dapps.md", + "html_url": "https://docs.polkadot.com/tutorials/dapps/", + "preview": "This section provides hands-on tutorials for building decentralized applications (dApps) using the Polkadot SDK and its developer toolkits. These guides help you leverage Polkadot's infrastructure to build scalable, secure, and interoperable dApps without relying solely on smart contracts.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Core Functionality", - "anchor": "core-functionality" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Available Block Explorers", - "anchor": "available-block-explorers" - }, - { - "depth": 3, - "title": "BlockScout", - "anchor": "blockscout" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 1793, - "words": 223, - "headings": 4, - "estimated_token_count_total": 309 + "chars": 1206, + "words": 169, + "headings": 2, + "estimated_token_count_total": 198 }, - "hash": "sha256:93e8a3043d65583e3d66f8f5f0ed6f4ef89a908ef85da2b6ca906a1100b7dded", + "hash": "sha256:467765777cace42ab4e3f1bb36c94f97e655c5d2cd570e00dd747c6a3db043f7", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-faucet", - "title": "Faucet", - "slug": "smart-contracts-faucet", + "id": "tutorials-interoperability-xcm-channels", + "title": "Tutorials for Managing XCM Channels", + "slug": "tutorials-interoperability-xcm-channels", "categories": [ - "Smart Contracts" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-faucet.md", - "html_url": "https://docs.polkadot.com/smart-contracts/faucet/", - "preview": "Test tokens allow you to experiment with smart contracts, test transactions, and validate your dApp functionality without using real cryptocurrency.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-interoperability-xcm-channels.md", + "html_url": "https://docs.polkadot.com/tutorials/interoperability/xcm-channels/", + "preview": "Establishing [XCM channels](/develop/interoperability/xcm-channels/) is essential to unlocking Polkadot's native interoperability. Before bridging assets or sending cross-chain contract calls, the necessary XCM channels must be established.", "outline": [ { "depth": 2, - "title": "Get Test Tokens", - "anchor": "get-test-tokens" + "title": "Understand the Process of Opening Channels", + "anchor": "understand-the-process-of-opening-channels" }, { "depth": 2, - "title": "Things to Consider", - "anchor": "things-to-consider" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Using Your Test Tokens", - "anchor": "using-your-test-tokens" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 1890, - "words": 279, + "chars": 1816, + "words": 236, "headings": 3, - "estimated_token_count_total": 313 + "estimated_token_count_total": 208 }, - "hash": "sha256:c609bc98cba5efa2d2a808548cf93ad9d0a06455b35a8fd9f534daf52824f506", + "hash": "sha256:3a6704a6330c6e35aa98fe8d615e2e27beb870a48c68bda02c217e6ae77274d2", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-for-eth-devs-accounts", - "title": "Accounts in Asset Hub Smart Contracts", - "slug": "smart-contracts-for-eth-devs-accounts", + "id": "tutorials-interoperability-xcm-transfers-from-relaychain-to-parachain", + "title": "XCM Transfers from Relay Chain to Parachain", + "slug": "tutorials-interoperability-xcm-transfers-from-relaychain-to-parachain", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-accounts.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/accounts/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-interoperability-xcm-transfers-from-relaychain-to-parachain.md", + "html_url": "https://docs.polkadot.com/tutorials/interoperability/xcm-transfers/from-relaychain-to-parachain/", + "preview": "[Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\\_blank} facilitates asset transfers both within the same consensus system and between different ones, such as between a relay chain and its parachains. For cross-system transfers, two main methods are available:", "outline": [ { "depth": 2, @@ -7781,127 +13687,126 @@ }, { "depth": 2, - "title": "Address Types and Mappings", - "anchor": "address-types-and-mappings" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Ethereum to Polkadot Mapping", - "anchor": "ethereum-to-polkadot-mapping" + "depth": 2, + "title": "Setup", + "anchor": "setup" }, { - "depth": 3, - "title": "Polkadot to Ethereum Mapping", - "anchor": "polkadot-to-ethereum-mapping" + "depth": 2, + "title": "Use Polkadot.js Apps", + "anchor": "use-polkadotjs-apps" }, { "depth": 3, - "title": "Account Mapping for Native Polkadot Accounts", - "anchor": "account-mapping-for-native-polkadot-accounts" - }, - { - "depth": 2, - "title": "Account Registration", - "anchor": "account-registration" + "title": "From the Relay Chain Perspective", + "anchor": "from-the-relay-chain-perspective" }, { - "depth": 2, - "title": "Fallback Accounts", - "anchor": "fallback-accounts" + "depth": 3, + "title": "From the Parachain Perspective", + "anchor": "from-the-parachain-perspective" }, { "depth": 2, - "title": "Contract Address Generation", - "anchor": "contract-address-generation" + "title": "Use PAPI", + "anchor": "use-papi" }, { "depth": 2, - "title": "Security Considerations", - "anchor": "security-considerations" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 8521, - "words": 1138, - "headings": 9, - "estimated_token_count_total": 1816 + "chars": 12680, + "words": 1562, + "headings": 8, + "estimated_token_count_total": 2764 }, - "hash": "sha256:dc95833b74404d8630a13e8746df3962e2d9d4777e5f18ca9a25d8d9302ebd53", + "hash": "sha256:a2bba0ba575bd7e3f7199282ea5994087acf2c62e828f316e6eb62c9a43449e1", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-for-eth-devs-blocks-transactions-fees", - "title": "Transactions and Fees on Asset Hub", - "slug": "smart-contracts-for-eth-devs-blocks-transactions-fees", + "id": "tutorials-interoperability-xcm-transfers", + "title": "XCM Transfers", + "slug": "tutorials-interoperability-xcm-transfers", "categories": [ - "Basics", - "Polkadot Protocol" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-blocks-transactions-fees.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/blocks-transactions-fees/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-interoperability-xcm-transfers.md", + "html_url": "https://docs.polkadot.com/tutorials/interoperability/xcm-transfers/", + "preview": "Discover comprehensive tutorials that guide you through performing asset transfers between distinct consensus systems. These tutorials leverage [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} technology, that enables cross-chain communication and asset exchanges across different blockchain networks. Whether you're working within the same ecosystem or bridging multiple systems, XCM ensures secure, efficient, and interoperable solutions.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Smart Contract Blocks", - "anchor": "smart-contract-blocks" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 826, + "words": 102, + "headings": 1, + "estimated_token_count_total": 12 + }, + "hash": "sha256:917ce0777f8ac5a4288e54ce4086432d320b127a7fc753ade5392d766a1f3c33", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-interoperability", + "title": "Interoperability Tutorials", + "slug": "tutorials-interoperability", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-interoperability.md", + "html_url": "https://docs.polkadot.com/tutorials/interoperability/", + "preview": "This section introduces you to the core interoperability solutions within the Polkadot ecosystem through practical, hands-on tutorials. These resources are designed to help you master cross-chain communication techniques, from setting up messaging channels between parachains to leveraging Polkadot's advanced features of the [XCM protocol](/parachains/interoperability/get-started/){target=\\_blank}.", + "outline": [ { "depth": 2, - "title": "Smart Contract Transactions", - "anchor": "smart-contract-transactions" + "title": "XCM (Cross-Consensus Messaging)", + "anchor": "xcm-cross-consensus-messaging" }, { "depth": 3, - "title": "EVM Transaction Types", - "anchor": "evm-transaction-types" + "title": "For Parachain Integrators", + "anchor": "for-parachain-integrators" }, { "depth": 2, - "title": "Fees and Gas", - "anchor": "fees-and-gas" - }, - { - "depth": 3, - "title": "Gas Model Overview", - "anchor": "gas-model-overview" - }, - { - "depth": 3, - "title": "Fee Components", - "anchor": "fee-components" + "title": "In This Section", + "anchor": "in-this-section" }, { - "depth": 3, - "title": "Gas Calculation and Conversion", - "anchor": "gas-calculation-and-conversion" + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 6366, - "words": 791, - "headings": 8, - "estimated_token_count_total": 1182 + "chars": 2193, + "words": 266, + "headings": 4, + "estimated_token_count_total": 339 }, - "hash": "sha256:9542f40acae725e628f4c3155ad1e7e0e18b2eb518484856ad439a1d9f86d1f3", + "hash": "sha256:9559f240b9433b496bfea92b57394a75c28bc743bb756c231f0137dfdf077e4a", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-for-eth-devs-contract-deployment", - "title": "Contract Deployment", - "slug": "smart-contracts-for-eth-devs-contract-deployment", + "id": "tutorials-onchain-governance-fast-track-gov-proposal", + "title": "Fast Track a Governance Proposal", + "slug": "tutorials-onchain-governance-fast-track-gov-proposal", "categories": [ - "Smart Contracts", - "Basics" + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-contract-deployment.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/contract-deployment/", - "preview": "Polkadot's smart contract platform supports two distinct virtual machine backends: Rust Ethereum Virtual Machine (REVM) and PolkaVM. Each backend has its own deployment characteristics and optimization strategies. REVM provides full Ethereum compatibility with familiar single-step deployment, while the RISC-V-based PolkaVM uses a more structured two-step approach optimized for its architecture. Understanding these differences ensures smooth deployment regardless of which backend you choose for y", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-onchain-governance-fast-track-gov-proposal.md", + "html_url": "https://docs.polkadot.com/tutorials/onchain-governance/fast-track-gov-proposal/", + "preview": "Polkadot's [OpenGov](/polkadot-protocol/onchain-governance/overview){target=\\_blank} is a sophisticated governance mechanism designed to allow the network to evolve gracefully over time, guided by its stakeholders. This system features multiple [tracks](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#origins-and-tracks-info){target=\\_blank} for different types of proposals, each with parameters for approval, support, and confirmation period. While this flexibility is powerful, it", "outline": [ { "depth": 2, @@ -7910,80 +13815,111 @@ }, { "depth": 2, - "title": "REVM Deployment", - "anchor": "revm-deployment" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "PolkaVM Deployment", - "anchor": "polkavm-deployment" + "title": "Set Up the Project", + "anchor": "set-up-the-project" }, { - "depth": 3, - "title": "Standard Contract Deployment", - "anchor": "standard-contract-deployment" + "depth": 2, + "title": "Submit and Execute a Proposal Using Chopsticks", + "anchor": "submit-and-execute-a-proposal-using-chopsticks" }, { "depth": 3, - "title": "Two-Step Deployment Model", - "anchor": "two-step-deployment-model" + "title": "Spin Up the Polkadot Fork", + "anchor": "spin-up-the-polkadot-fork" }, { "depth": 3, - "title": "Factory Pattern Considerations", - "anchor": "factory-pattern-considerations" + "title": "Set Up Dependencies and Structure", + "anchor": "set-up-dependencies-and-structure" }, { "depth": 3, - "title": "Migration Strategy for Factory Contracts", - "anchor": "migration-strategy-for-factory-contracts" + "title": "Connect to the Forked Chain", + "anchor": "connect-to-the-forked-chain" }, { "depth": 3, - "title": "Architecture-Specific Limitations", - "anchor": "architecture-specific-limitations" + "title": "Create and Submit the Proposal", + "anchor": "create-and-submit-the-proposal" }, { "depth": 3, - "title": "On-Chain Constructors", - "anchor": "on-chain-constructors" + "title": "Force Proposal Execution", + "anchor": "force-proposal-execution" }, { "depth": 2, - "title": "Gas Estimation vs Actual Consumption", - "anchor": "gas-estimation-vs-actual-consumption" + "title": "Execute the Proposal Script", + "anchor": "execute-the-proposal-script" }, { "depth": 2, - "title": "Deployment Comparison", - "anchor": "deployment-comparison" + "title": "Summary", + "anchor": "summary" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Full Code", + "anchor": "full-code" } ], "stats": { - "chars": 5999, - "words": 766, + "chars": 169845, + "words": 17558, "headings": 12, - "estimated_token_count_total": 1133 + "estimated_token_count_total": 34492 }, - "hash": "sha256:0792e3956242eb8e08ab82e2d73964c381074cc8b1ea46f396d136856fa6cc07", + "hash": "sha256:bef820acfe429d4a847a8de82de6c70155ac6b3ad5ebdd574a2157923b45f688", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-for-eth-devs-dual-vm-stack", - "title": "Dual Virtual Machine Stack", - "slug": "smart-contracts-for-eth-devs-dual-vm-stack", + "id": "tutorials-onchain-governance", + "title": "On-Chain Governance Tutorials", + "slug": "tutorials-onchain-governance", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-onchain-governance.md", + "html_url": "https://docs.polkadot.com/tutorials/onchain-governance/", + "preview": "On-chain governance enables decentralized networks to grow and adapt through collective decision-making. For developers, understanding and implementing governance features is crucial for contributing to network improvements and supporting user interactions.", + "outline": [ + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 867, + "words": 112, + "headings": 2, + "estimated_token_count_total": 125 + }, + "hash": "sha256:c675e4231537732f24d1dd93f2b248398248a77c9877860fe53926e255ed0710", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-build-custom-pallet", + "title": "Build a Custom Pallet", + "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-build-custom-pallet", "categories": [ "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-build-custom-pallet.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/", + "preview": "In Polkadot SDK-based blockchains, runtime functionality is built through modular components called [pallets](/polkadot-protocol/glossary#pallet){target=\\_blank}. These pallets are Rust-based runtime modules created using [FRAME (Framework for Runtime Aggregation of Modular Entities)](/develop/parachains/customize-parachain/overview/){target=\\_blank}, a powerful library that simplifies blockchain development by providing specialized macros and standardized patterns for building blockchain logic.", "outline": [ { "depth": 2, @@ -7992,110 +13928,89 @@ }, { "depth": 2, - "title": "Migrate from EVM", - "anchor": "migrate-from-evm" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Upgrade to PolkaVM", - "anchor": "upgrade-to-polkavm" + "title": "Create a New Project", + "anchor": "create-a-new-project" }, { "depth": 2, - "title": "Architecture", - "anchor": "architecture" + "title": "Add Dependencies", + "anchor": "add-dependencies" }, { - "depth": 3, - "title": "Revive Pallet", - "anchor": "revive-pallet" + "depth": 2, + "title": "Implement the Pallet Logic", + "anchor": "implement-the-pallet-logic" }, { "depth": 3, - "title": "PolkaVM Design Fundamentals", - "anchor": "polkavm-design-fundamentals" + "title": "Add Scaffold Pallet Structure", + "anchor": "add-scaffold-pallet-structure" }, { - "depth": 2, - "title": "Where To Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 5383, - "words": 702, - "headings": 7, - "estimated_token_count_total": 986 - }, - "hash": "sha256:2d918017faecf489ec786f34de6cd4366a86e9f1cecfbb7722cc03079e6b64ea", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-for-eth-devs-gas-model", - "title": "Gas Model on the Polkadot Hub", - "slug": "smart-contracts-for-eth-devs-gas-model", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-gas-model.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/gas-model/", - "preview": "The Polkadot Hub implements a gas model that bridges Ethereum's familiar gas concept with Polkadot's more sophisticated resource metering system. This page explains how gas works in the Polkadot Hub and what developers need to know when building smart contracts.", - "outline": [ + "depth": 3, + "title": "Pallet Configuration", + "anchor": "pallet-configuration" + }, { - "depth": 2, - "title": "Overview", - "anchor": "overview" + "depth": 3, + "title": "Add Events", + "anchor": "add-events" }, { - "depth": 2, - "title": "Understanding Resources in the Polkadot Hub", - "anchor": "understanding-resources-in-the-polkadot-hub" + "depth": 3, + "title": "Add Storage Items", + "anchor": "add-storage-items" }, { - "depth": 2, - "title": "Gas vs Weight", - "anchor": "gas-vs-weight" + "depth": 3, + "title": "Implement Custom Errors", + "anchor": "implement-custom-errors" }, { - "depth": 2, - "title": "How Gas Estimation Works", - "anchor": "how-gas-estimation-works" + "depth": 3, + "title": "Implement Calls", + "anchor": "implement-calls" }, { "depth": 2, - "title": "Dynamic Gas Pricing", - "anchor": "dynamic-gas-pricing" + "title": "Verify Compilation", + "anchor": "verify-compilation" }, { "depth": 2, - "title": "Transaction Execution Flow", - "anchor": "transaction-execution-flow" + "title": "Key Takeaways", + "anchor": "key-takeaways" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 5234, - "words": 751, - "headings": 7, - "estimated_token_count_total": 1046 + "chars": 26829, + "words": 2787, + "headings": 14, + "estimated_token_count_total": 5338 }, - "hash": "sha256:dd29fab6e3c00d720b10effa4e50373a6fe9ab4b7bfd3aea892c7fa9c84318a2", + "hash": "sha256:b3530f5fc5c9e916181dbc259a7fbae9c60100cb0450fc6d47bbb0d140afa075", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-for-eth-devs-json-rpc-apis", - "title": "JSON-RPC APIs", - "slug": "smart-contracts-for-eth-devs-json-rpc-apis", + "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-deploy-to-testnet", + "title": "Deploy on Paseo TestNet", + "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-deploy-to-testnet", "categories": [ - "Reference" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-deploy-to-testnet.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/deploy-to-testnet/", + "preview": "Previously, you learned how to [build and run a blockchain locally](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to a public test network.", "outline": [ { "depth": 2, @@ -8104,194 +14019,267 @@ }, { "depth": 2, - "title": "Available Methods", - "anchor": "available-methods" + "title": "Get Started with an Account and Tokens", + "anchor": "get-started-with-an-account-and-tokens" }, { - "depth": 3, - "title": "eth_accounts", - "anchor": "eth_accounts" + "depth": 2, + "title": "Reserve a Parachain Identifier", + "anchor": "reserve-a-parachain-identifier" }, { - "depth": 3, - "title": "eth_blockNumber", - "anchor": "eth_blocknumber" + "depth": 2, + "title": "Generate Customs Keys for Your Collator", + "anchor": "generate-customs-keys-for-your-collator" }, { - "depth": 3, - "title": "eth_call", - "anchor": "eth_call" + "depth": 2, + "title": "Generate the Chain Specification", + "anchor": "generate-the-chain-specification" }, { - "depth": 3, - "title": "eth_chainId", - "anchor": "eth_chainid" + "depth": 2, + "title": "Export Required Files", + "anchor": "export-required-files" }, { - "depth": 3, - "title": "eth_estimateGas", - "anchor": "eth_estimategas" + "depth": 2, + "title": "Register a Parathread", + "anchor": "register-a-parathread" }, { - "depth": 3, - "title": "eth_gasPrice", - "anchor": "eth_gasprice" + "depth": 2, + "title": "Start the Collator Node", + "anchor": "start-the-collator-node" }, { - "depth": 3, - "title": "eth_getBalance", - "anchor": "eth_getbalance" + "depth": 2, + "title": "Producing Blocks", + "anchor": "producing-blocks" }, { - "depth": 3, - "title": "eth_getBlockByHash", - "anchor": "eth_getblockbyhash" - }, + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 21251, + "words": 2506, + "headings": 10, + "estimated_token_count_total": 4358 + }, + "hash": "sha256:87b19f6e881611329b7015e8d8187d7d85b2b2ef14b01e832c8b8e20897e3b40", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-obtain-coretime", + "title": "Obtain Coretime", + "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-obtain-coretime", + "categories": [ + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-obtain-coretime.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/obtain-coretime/", + "preview": "After deploying a parachain to the Paseo TestNet in the [Deploy to TestNet](/tutorials/polkadot-sdk/parachains/zero-to-hero/deploy-to-testnet/){target=\\_blank} tutorial, the focus shifts to understanding Coretime, which is the mechanism in which validation resources are allocated from the relay chain to the respective task, such as a parachain. A parachain could only produce blocks and finalize them on the relay chain by obtaining coretime.", + "outline": [ { - "depth": 3, - "title": "eth_getBlockByNumber", - "anchor": "eth_getblockbynumber" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "eth_getBlockTransactionCountByNumber", - "anchor": "eth_getblocktransactioncountbynumber" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "eth_getBlockTransactionCountByHash", - "anchor": "eth_getblocktransactioncountbyhash" + "depth": 2, + "title": "Order On Demand Coretime", + "anchor": "order-on-demand-coretime" }, { - "depth": 3, - "title": "eth_getCode", - "anchor": "eth_getcode" + "depth": 2, + "title": "Purchase Bulk Coretime", + "anchor": "purchase-bulk-coretime" }, { "depth": 3, - "title": "eth_getLogs", - "anchor": "eth_getlogs" + "title": "Get Coretime Funds", + "anchor": "get-coretime-funds" }, { "depth": 3, - "title": "eth_getStorageAt", - "anchor": "eth_getstorageat" + "title": "Purchase a Core", + "anchor": "purchase-a-core" }, { "depth": 3, - "title": "eth_getTransactionCount", - "anchor": "eth_gettransactioncount" + "title": "Assign a Core", + "anchor": "assign-a-core" + } + ], + "stats": { + "chars": 8625, + "words": 1309, + "headings": 7, + "estimated_token_count_total": 2138 + }, + "hash": "sha256:ff2c267284959711782c0d6ecb4b439c3a6cc31f763d5e1ff2cc3b1f6efb62b2", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-benchmarking", + "title": "Pallet Benchmarking", + "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-benchmarking", + "categories": [ + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-benchmarking.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-benchmarking/", + "preview": "After validating your pallet through testing and integrating it into your runtime, the next crucial step is benchmarking. Testing procedures were detailed in the [Pallet Unit Testing](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/){target=\\_blank} tutorial, while runtime integration was covered in the [Add Pallets to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/){target=\\_blank} guide.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "eth_getTransactionByHash", - "anchor": "eth_gettransactionbyhash" + "depth": 2, + "title": "Environment Setup", + "anchor": "environment-setup" }, { - "depth": 3, - "title": "eth_getTransactionByBlockNumberAndIndex", - "anchor": "eth_gettransactionbyblocknumberandindex" + "depth": 2, + "title": "Implement Benchmark Tests", + "anchor": "implement-benchmark-tests" }, { - "depth": 3, - "title": "eth_getTransactionByBlockHashAndIndex", - "anchor": "eth_gettransactionbyblockhashandindex" + "depth": 2, + "title": "Execute the Benchmarking", + "anchor": "execute-the-benchmarking" }, { - "depth": 3, - "title": "eth_getTransactionReceipt", - "anchor": "eth_gettransactionreceipt" + "depth": 2, + "title": "Add Benchmarking Weights to the Pallet", + "anchor": "add-benchmarking-weights-to-the-pallet" }, { - "depth": 3, - "title": "eth_maxPriorityFeePerGas", - "anchor": "eth_maxpriorityfeepergas" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 12857, + "words": 1539, + "headings": 6, + "estimated_token_count_total": 2929 + }, + "hash": "sha256:df60044893f48dd7f37a11de275a16bf32adb31317ed70a789fd7fac64150e1a", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-unit-testing", + "title": "Pallet Unit Testing", + "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-unit-testing", + "categories": [ + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-unit-testing.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/", + "preview": "You have learned how to create a new pallet in the [Build a Custom Pallet](/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/){target=\\_blank} tutorial; now you will see how to test the pallet to ensure that it works as expected. As stated in the [Pallet Testing](/parachains/customize-runtime/pallet-development/pallet-testing/){target=\\_blank} article, unit testing is crucial for ensuring the reliability and correctness of pallets in Polkadot SDK-based blockchains. Comprehensiv", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "eth_sendRawTransaction", - "anchor": "eth_sendrawtransaction" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "eth_sendTransaction", - "anchor": "eth_sendtransaction" + "depth": 2, + "title": "Set Up the Testing Environment", + "anchor": "set-up-the-testing-environment" }, { - "depth": 3, - "title": "eth_syncing", - "anchor": "eth_syncing" + "depth": 2, + "title": "Implement Mocked Runtime", + "anchor": "implement-mocked-runtime" }, { "depth": 3, - "title": "net_listening", - "anchor": "net_listening" + "title": "Full Mocked Runtime", + "anchor": "full-mocked-runtime" }, { - "depth": 3, - "title": "net_peerCount", - "anchor": "net_peercount" + "depth": 2, + "title": "Implement Test Cases", + "anchor": "implement-test-cases" }, { "depth": 3, - "title": "net_version", - "anchor": "net_version" + "title": "Successful Operations", + "anchor": "successful-operations" }, { "depth": 3, - "title": "system_health", - "anchor": "system_health" + "title": "Preventing Value Overflow", + "anchor": "preventing-value-overflow" }, { "depth": 3, - "title": "web3_clientVersion", - "anchor": "web3_clientversion" + "title": "Origin and Access Control", + "anchor": "origin-and-access-control" }, { "depth": 3, - "title": "debug_traceBlockByNumber", - "anchor": "debug_traceblockbynumber" + "title": "Edge Case Handling", + "anchor": "edge-case-handling" }, { "depth": 3, - "title": "debug_traceTransaction", - "anchor": "debug_tracetransaction" + "title": "Verify State Changes", + "anchor": "verify-state-changes" }, { "depth": 3, - "title": "debug_traceCall", - "anchor": "debug_tracecall" + "title": "Full Test Suite", + "anchor": "full-test-suite" }, { "depth": 2, - "title": "Response Format", - "anchor": "response-format" + "title": "Run the Tests", + "anchor": "run-the-tests" }, { "depth": 2, - "title": "Error Handling", - "anchor": "error-handling" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 31444, - "words": 3848, - "headings": 35, - "estimated_token_count_total": 9562 + "chars": 23736, + "words": 2324, + "headings": 14, + "estimated_token_count_total": 4789 }, - "hash": "sha256:da1669344010a793a5296c9397b2d5a85240ff6fbe37b885bce0139298364423", + "hash": "sha256:81750202081ff24447f4e129c49230eedb315d1b44c740b677c3495a8f7adb9a", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-for-eth-devs-migration", - "title": "Migration FAQs and Considerations", - "slug": "smart-contracts-for-eth-devs-migration", + "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-runtime-upgrade", + "title": "Runtime Upgrades", + "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-runtime-upgrade", "categories": [ - "Smart Contracts" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/", - "preview": "This guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-runtime-upgrade.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/runtime-upgrade/", + "preview": "Upgrading the runtime of your Polkadot SDK-based blockchain is a fundamental feature that allows you to add new functionality, fix bugs, or improve performance without requiring a hard fork. Runtime upgrades are performed by submitting a special extrinsic that replaces the existing on-chain WASM runtime code. This process is trustless, transparent, and can be executed either through governance or using sudo, depending on your chain's configuration.", "outline": [ { "depth": 2, @@ -8300,229 +14288,282 @@ }, { "depth": 2, - "title": "Migration Considerations", - "anchor": "migration-considerations" + "title": "Update the Runtime", + "anchor": "update-the-runtime" }, { - "depth": 2, - "title": "Migration Checklist", - "anchor": "migration-checklist" + "depth": 3, + "title": "Start Your Chain", + "anchor": "start-your-chain" }, { - "depth": 2, - "title": "Migration FAQs", - "anchor": "migration-faqs" + "depth": 3, + "title": "Add a New Feature", + "anchor": "add-a-new-feature" }, { "depth": 3, - "title": "Which backend should I choose?", - "anchor": "which-backend-should-i-choose" + "title": "Update Runtime Configuration", + "anchor": "update-runtime-configuration" }, { "depth": 3, - "title": "Do I need to rewrite my Solidity code?", - "anchor": "do-i-need-to-rewrite-my-solidity-code" + "title": "Bump the Runtime Version", + "anchor": "bump-the-runtime-version" }, { "depth": 3, - "title": "What about factory contracts?", - "anchor": "what-about-factory-contracts" + "title": "Build the New Runtime", + "anchor": "build-the-new-runtime" }, { - "depth": 3, - "title": "How do gas costs compare?", - "anchor": "how-do-gas-costs-compare" + "depth": 2, + "title": "Submit the Runtime Upgrade", + "anchor": "submit-the-runtime-upgrade" }, { - "depth": 3, - "title": "Which Solidity features are not supported?", - "anchor": "which-solidity-features-are-not-supported" + "depth": 2, + "title": "Verify the Upgrade", + "anchor": "verify-the-upgrade" }, { "depth": 3, - "title": "How do I handle the existential deposit?", - "anchor": "how-do-i-handle-the-existential-deposit" + "title": "Check Runtime Version", + "anchor": "check-runtime-version" }, { "depth": 3, - "title": "Can I use my existing development tools?", - "anchor": "can-i-use-my-existing-development-tools" + "title": "Test New Functionality", + "anchor": "test-new-functionality" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 6067, - "words": 777, + "chars": 10233, + "words": 1378, "headings": 12, - "estimated_token_count_total": 1275 + "estimated_token_count_total": 2452 }, - "hash": "sha256:d6cbd026bd22d3362fffe6bdab0ce3d1688482b6d1eec26368b46fd03eb82a5f", + "hash": "sha256:1eb463c6b2732ebed0d16165425cde438688d21cc302f759b40250850c2a5e83", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-get-started", - "title": "Get Started with Smart Contracts", - "slug": "smart-contracts-get-started", + "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-set-up-a-template", + "title": "Set Up a Template", + "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-set-up-a-template", "categories": [ "Basics", - "Smart Contracts" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md", - "html_url": "https://docs.polkadot.com/smart-contracts/get-started/", - "preview": "This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-set-up-a-template.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/set-up-a-template/", + "preview": "[Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} offers a versatile and extensible blockchain development framework, enabling you to create custom blockchains tailored to your specific application or business requirements.", "outline": [ { "depth": 2, - "title": "Quick Starts", - "anchor": "quick-starts" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Build and Test Locally", - "anchor": "build-and-test-locally" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Ethereum Developer Resources", - "anchor": "ethereum-developer-resources" + "title": "Utility Tools", + "anchor": "utility-tools" }, { "depth": 2, - "title": "Cookbook: Hands‑on Tutorials", - "anchor": "cookbook-handson-tutorials" + "title": "Compile the Runtime", + "anchor": "compile-the-runtime" }, { "depth": 2, - "title": "Libraries", - "anchor": "libraries" + "title": "Start the Local Chain", + "anchor": "start-the-local-chain" }, { "depth": 2, - "title": "Integrations", - "anchor": "integrations" + "title": "Interact with the Node", + "anchor": "interact-with-the-node" }, { "depth": 2, - "title": "Precompiles", - "anchor": "precompiles" + "title": "Stop the Node", + "anchor": "stop-the-node" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 10103, - "words": 937, - "headings": 7, - "estimated_token_count_total": 2888 + "chars": 12524, + "words": 1873, + "headings": 8, + "estimated_token_count_total": 3255 }, - "hash": "sha256:8ec1a9444ba7ec4a35361f14bb0268be87d1ebee8079bb9740f47f69c90f877a", + "hash": "sha256:fe94de6f97fb588552f6cbc6b1a4c7399e91f5f31585f61a0dee66f5f50ff8a0", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-integrations-indexers", - "title": "smart-contracts-integrations-indexers", - "slug": "smart-contracts-integrations-indexers", + "id": "tutorials-polkadot-sdk-parachains-zero-to-hero", + "title": "Zero To Hero Parachain Tutorial Series", + "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-indexers.md", - "html_url": "https://docs.polkadot.com/smart-contracts/integrations/indexers/", - "preview": "TODO", - "outline": [], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/", + "preview": "The **Parachain Zero To Hero Tutorials** provide developers with a series of step-by-step guides to building, testing, and deploying custom pallets and runtimes using the Polkadot SDK. These tutorials are designed to help you gain hands-on experience and understand the core concepts necessary to create efficient and scalable blockchains.", + "outline": [ + { + "depth": 2, + "title": "Parachain Development Cycle", + "anchor": "parachain-development-cycle" + } + ], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 828, + "words": 132, + "headings": 1, + "estimated_token_count_total": 42 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:06acc146698c1d3224544987d7ee52da498e3179228f98a494e385c5786a3a2c", "token_estimator": "heuristic-v1" }, - { - "id": "smart-contracts-integrations-oracles", - "title": "smart-contracts-integrations-oracles", - "slug": "smart-contracts-integrations-oracles", + { + "id": "tutorials-polkadot-sdk-parachains", + "title": "Parachain Tutorials", + "slug": "tutorials-polkadot-sdk-parachains", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-oracles.md", - "html_url": "https://docs.polkadot.com/smart-contracts/integrations/oracles/", - "preview": "TODO", - "outline": [], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/", + "preview": "The Polkadot SDK enables you to build custom blockchains that can operate as part of the Polkadot network. These tutorials guide you through the essential steps of developing, testing, and deploying your own parachain.", + "outline": [ + { + "depth": 2, + "title": "Parachain Zero To Hero Tutorials", + "anchor": "parachain-zero-to-hero-tutorials" + }, + { + "depth": 2, + "title": "Key Takeaways", + "anchor": "key-takeaways" + }, + { + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" + } + ], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 924, + "words": 122, + "headings": 3, + "estimated_token_count_total": 107 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:fdd391227992c966de25b9240f5492135a9993859ec42b77952c1aa3d2e39ed9", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-integrations-wallets", - "title": "Wallets for Polkadot Hub", - "slug": "smart-contracts-integrations-wallets", + "id": "tutorials-polkadot-sdk-system-chains-asset-hub", + "title": "Asset Hub Tutorials", + "slug": "tutorials-polkadot-sdk-system-chains-asset-hub", "categories": [ - "Smart Contracts", - "Tooling" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md", - "html_url": "https://docs.polkadot.com/smart-contracts/integrations/wallets/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-system-chains-asset-hub.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/system-chains/asset-hub/", + "preview": "Polkadot SDK-based relay chains focus on security and consensus, leaving asset management to an external component, such as a [system chain](/polkadot-protocol/architecture/system-chains/){target=\\_blank}. The [Asset Hub](/reference/polkadot-hub/assets-and-smart-contracts/){target=\\_blank} is one example of a system chain and is vital to managing tokens which aren't native to the Polkadot ecosystem. Developers opting to integrate with Asset Hub can expect the following benefits:", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Benefits of Asset Hub", + "anchor": "benefits-of-asset-hub" }, { "depth": 2, - "title": "Connect Your Wallet", - "anchor": "connect-your-wallet" + "title": "Get Started", + "anchor": "get-started" }, { - "depth": 3, - "title": "MetaMask", - "anchor": "metamask" + "depth": 2, + "title": "In This Section", + "anchor": "in-this-section" }, { - "depth": 3, - "title": "SubWallet", - "anchor": "subwallet" + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1768, + "words": 250, + "headings": 4, + "estimated_token_count_total": 400 + }, + "hash": "sha256:2fc6f513fd8b269e586b754b2bdbd2af9df5178624a028fab940a385f3fee577", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-polkadot-sdk-system-chains", + "title": "System Chains Tutorials", + "slug": "tutorials-polkadot-sdk-system-chains", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-system-chains.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/system-chains/", + "preview": "In this section, you'll gain hands-on experience building solutions that integrate with [system chains](/polkadot-protocol/architecture/system-chains/){target=\\_blank} on Polkadot using the Polkadot SDK. System chains like the [Asset Hub](/reference/polkadot-hub/assets-and-smart-contracts/){target=\\_blank} provide essential infrastructure for enabling cross-chain interoperability and asset management across the Polkadot ecosystem.", + "outline": [ + { + "depth": 2, + "title": "For Parachain Integrators", + "anchor": "for-parachain-integrators" }, { - "depth": 3, - "title": "Talisman", - "anchor": "talisman" + "depth": 2, + "title": "For Developers Leveraging System Chains", + "anchor": "for-developers-leveraging-system-chains" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 7340, - "words": 1041, - "headings": 6, - "estimated_token_count_total": 1627 + "chars": 1560, + "words": 211, + "headings": 3, + "estimated_token_count_total": 211 }, - "hash": "sha256:65809486f62f60c6a6ac8109f9f027361683c23f639991a045ec5c057b665026", + "hash": "sha256:5d45ec9f8efda8c4bc2d0c21399a036d017a03540e7efab60d4710cb7eb33eb3", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-libraries-ethers-js", - "title": "Deploy Contracts to Polkadot Hub with Ethers.js", - "slug": "smart-contracts-libraries-ethers-js", + "id": "tutorials-polkadot-sdk-testing-fork-live-chains", + "title": "Fork a Chain with Chopsticks", + "slug": "tutorials-polkadot-sdk-testing-fork-live-chains", "categories": [ - "Smart Contracts", + "Basics", + "dApps", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-ethers-js.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/ethers-js/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-testing-fork-live-chains.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/testing/fork-live-chains/", + "preview": "Chopsticks is an innovative tool that simplifies the process of forking live Polkadot SDK chains. This guide provides step-by-step instructions to configure and fork chains, enabling developers to:", "outline": [ { "depth": 2, @@ -8536,80 +14577,61 @@ }, { "depth": 2, - "title": "Project Structure", - "anchor": "project-structure" - }, - { - "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" - }, - { - "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" + "title": "Configuration File", + "anchor": "configuration-file" }, { "depth": 2, - "title": "Set Up the Ethers.js Provider", - "anchor": "set-up-the-ethersjs-provider" + "title": "Create a Fork", + "anchor": "create-a-fork" }, { "depth": 2, - "title": "Compile Contracts", - "anchor": "compile-contracts" - }, - { - "depth": 3, - "title": "Install the Revive Library", - "anchor": "install-the-revive-library" + "title": "Interact with a Fork", + "anchor": "interact-with-a-fork" }, { "depth": 3, - "title": "Sample Storage Smart Contract", - "anchor": "sample-storage-smart-contract" + "title": "Use Polkadot.js Apps", + "anchor": "use-polkadotjs-apps" }, { "depth": 3, - "title": "Compile the Smart Contract", - "anchor": "compile-the-smart-contract" - }, - { - "depth": 2, - "title": "Deploy the Compiled Contract", - "anchor": "deploy-the-compiled-contract" + "title": "Use Polkadot.js Library", + "anchor": "use-polkadotjs-library" }, { "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" + "title": "Replay Blocks", + "anchor": "replay-blocks" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "XCM Testing", + "anchor": "xcm-testing" } ], "stats": { - "chars": 20457, - "words": 2333, - "headings": 13, - "estimated_token_count_total": 4474 + "chars": 22265, + "words": 1326, + "headings": 9, + "estimated_token_count_total": 2702 }, - "hash": "sha256:c74a28d8d62369591c5734535136508db3d1f7380e486fd214f98d433cafd6e7", + "hash": "sha256:1f8ab387f721d865a7ca75eaa2528f1f2ebd4528a7d65ffeb27c68953100a3cb", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-libraries-viem", - "title": "viem for Polkadot Hub Smart Contracts", - "slug": "smart-contracts-libraries-viem", + "id": "tutorials-polkadot-sdk-testing-spawn-basic-chain", + "title": "Spawn a Basic Chain with Zombienet", + "slug": "tutorials-polkadot-sdk-testing-spawn-basic-chain", "categories": [ - "Smart Contracts", + "Basics", + "dApps", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-viem.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/viem/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-testing-spawn-basic-chain.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/testing/spawn-basic-chain/", + "preview": "Zombienet simplifies blockchain development by enabling developers to create temporary, customizable networks for testing and validation. These ephemeral chains are ideal for experimenting with configurations, debugging applications, and validating functionality in a controlled environment.", "outline": [ { "depth": 2, @@ -8623,84 +14645,152 @@ }, { "depth": 2, - "title": "Project Structure", - "anchor": "project-structure" + "title": "Set Up Local Provider", + "anchor": "set-up-local-provider" }, { "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" + "title": "Define the Network", + "anchor": "define-the-network" }, { "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" + "title": "Spawn the Network", + "anchor": "spawn-the-network" }, { "depth": 2, - "title": "Initialize Project", - "anchor": "initialize-project" + "title": "Interact with the Spawned Network", + "anchor": "interact-with-the-spawned-network" }, { - "depth": 2, - "title": "Set Up the Chain Configuration", - "anchor": "set-up-the-chain-configuration" + "depth": 3, + "title": "Connect to the Nodes", + "anchor": "connect-to-the-nodes" }, { - "depth": 2, - "title": "Set Up the viem Client", - "anchor": "set-up-the-viem-client" + "depth": 3, + "title": "Check Metrics", + "anchor": "check-metrics" }, + { + "depth": 3, + "title": "Check Logs", + "anchor": "check-logs" + } + ], + "stats": { + "chars": 9496, + "words": 1395, + "headings": 9, + "estimated_token_count_total": 2564 + }, + "hash": "sha256:97dadddf4c27f469f552875461fc54d331fa151e4656401e15d6d4173115eecf", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-polkadot-sdk-testing", + "title": "Blockchain Testing Tutorials", + "slug": "tutorials-polkadot-sdk-testing", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-testing.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/testing/", + "preview": "Polkadot offers specialized tools that make it simple to create realistic testing environments, particularly for cross-chain interactions. These purpose-built tools enable developers to quickly spin up test networks that accurately simulate real-world scenarios. Learn to create controlled testing environments using powerful tools designed for Polkadot SDK development.", + "outline": [ { "depth": 2, - "title": "Set Up a Wallet", - "anchor": "set-up-a-wallet" + "title": "Get Started", + "anchor": "get-started" }, { "depth": 2, - "title": "Sample Smart Contract", - "anchor": "sample-smart-contract" - }, + "title": "In This Section", + "anchor": "in-this-section" + } + ], + "stats": { + "chars": 843, + "words": 106, + "headings": 2, + "estimated_token_count_total": 80 + }, + "hash": "sha256:1dfbb8c3cfa27f92e982b4ce705415e117c50eb38f641691129863b474741da7", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-polkadot-sdk", + "title": "Polkadot SDK Tutorials", + "slug": "tutorials-polkadot-sdk", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk.md", + "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/", + "preview": "The Polkadot SDK is a versatile framework for building custom blockchains, whether as standalone networks or as part of the Polkadot ecosystem. With its modular design and extensible tools, libraries, and runtime components, the SDK simplifies the process of creating parachains, system chains, and solochains.", + "outline": [ { "depth": 2, - "title": "Compile the Contract", - "anchor": "compile-the-contract" + "title": "Build and Deploy a Parachain", + "anchor": "build-and-deploy-a-parachain" }, { "depth": 2, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" + "title": "In This Section", + "anchor": "in-this-section" }, { "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 1481, + "words": 214, + "headings": 3, + "estimated_token_count_total": 256 + }, + "hash": "sha256:d63121126e51c785f0dfd4ae4ecd49cb71640515d39df69a0689f30a7ab8122f", + "token_estimator": "heuristic-v1" + }, + { + "id": "tutorials-smart-contracts-demo-aplications", + "title": "Demo Applications", + "slug": "tutorials-smart-contracts-demo-aplications", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-demo-aplications.md", + "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/demo-aplications/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. This section highlights demo applications that can be deployed to Polkadot Hub. These examples illustrate practical use cases and provide guidance for developers looking to launch and test applications within the Polkadot ecosystem.", + "outline": [ { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 16600, - "words": 1940, - "headings": 14, - "estimated_token_count_total": 3891 + "chars": 474, + "words": 60, + "headings": 1, + "estimated_token_count_total": 12 }, - "hash": "sha256:e27657e4e4a14fe86f424b96631946ec36fb90d277e6010b6cbd64c4769aba8a", + "hash": "sha256:94dbafb2d78b87d5f0f0c75de002501b8210ac8d66072bc07989f685837cbac5", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-libraries-wagmi", - "title": "Wagmi for Polkadot Hub Smart Contracts", - "slug": "smart-contracts-libraries-wagmi", + "id": "tutorials-smart-contracts-launch-your-first-project-create-contracts", + "title": "Create a Smart Contract", + "slug": "tutorials-smart-contracts-launch-your-first-project-create-contracts", "categories": [ - "Smart Contracts", - "Tooling" + "Basics", + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-wagmi.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/wagmi/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project-create-contracts.md", + "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/create-contracts/", "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { @@ -8710,43 +14800,23 @@ }, { "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" - }, - { - "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" - }, - { - "depth": 2, - "title": "Configure Wagmi for Polkadot Hub", - "anchor": "configure-wagmi-for-polkadot-hub" - }, - { - "depth": 2, - "title": "Set Up the Wagmi Provider", - "anchor": "set-up-the-wagmi-provider" - }, - { - "depth": 2, - "title": "Connect a Wallet", - "anchor": "connect-a-wallet" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Fetch Blockchain Data", - "anchor": "fetch-blockchain-data" + "title": "Understanding Smart Contract Structure", + "anchor": "understanding-smart-contract-structure" }, { "depth": 2, - "title": "Interact with Deployed Contract", - "anchor": "interact-with-deployed-contract" + "title": "Create the Smart Contract", + "anchor": "create-the-smart-contract" }, { "depth": 2, - "title": "Integrate Components", - "anchor": "integrate-components" + "title": "Understanding the Code", + "anchor": "understanding-the-code" }, { "depth": 2, @@ -8755,25 +14825,25 @@ } ], "stats": { - "chars": 13604, - "words": 1515, - "headings": 10, - "estimated_token_count_total": 3250 + "chars": 8665, + "words": 1178, + "headings": 6, + "estimated_token_count_total": 1760 }, - "hash": "sha256:bc771f912627fa09cad64adab1bc81c052f650d6c5a3b4f0c91883a98f6628da", + "hash": "sha256:9cf70459e921b8b231a3f2e7a7c1d47a4917e45f0c4d0fe873ad4062fd540a9a", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-libraries-web3-js", - "title": "Web3.js", - "slug": "smart-contracts-libraries-web3-js", + "id": "tutorials-smart-contracts-launch-your-first-project-create-dapp-ethers-js", + "title": "Create a dApp With Ethers.js", + "slug": "tutorials-smart-contracts-launch-your-first-project-create-dapp-ethers-js", "categories": [ - "Smart Contracts", + "dApp", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/web3-js/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. !!! warning Web3.js has been [sunset](https://blog.chainsafe.io/web3-js-sunset/){target=\\_blank}. You can find guides on using [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank} and [viem](/smart-contracts/libraries/viem/){target=\\_blank} in the Libraries section.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project-create-dapp-ethers-js.md", + "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/create-dapp-ethers-js/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -8787,8 +14857,8 @@ }, { "depth": 2, - "title": "Project Structure", - "anchor": "project-structure" + "title": "Project Overview", + "anchor": "project-overview" }, { "depth": 2, @@ -8797,60 +14867,65 @@ }, { "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" + "title": "Connect to Polkadot Hub", + "anchor": "connect-to-polkadot-hub" }, { "depth": 2, - "title": "Set Up the Web3 Provider", - "anchor": "set-up-the-web3-provider" + "title": "Set Up the Smart Contract Interface", + "anchor": "set-up-the-smart-contract-interface" }, { "depth": 2, - "title": "Compile Contracts", - "anchor": "compile-contracts" + "title": "Create the Wallet Connection Component", + "anchor": "create-the-wallet-connection-component" }, { "depth": 2, - "title": "Contract Deployment", - "anchor": "contract-deployment" + "title": "Read Data from the Blockchain", + "anchor": "read-data-from-the-blockchain" }, { "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" + "title": "Write Data to the Blockchain", + "anchor": "write-data-to-the-blockchain" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 13266, - "words": 1579, - "headings": 10, - "estimated_token_count_total": 3035 + "chars": 2525, + "words": 328, + "headings": 3, + "estimated_token_count_total": 412 }, - "hash": "sha256:f0d36333d0d3afff7f6374a61d0f6d1fb878c9ef4c4e4c24447745661dbe59d0", + "hash": "sha256:de7fde61d4cac9c28634ee496dcabe116fe44b1b87408f202103290d78247c05", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-libraries-web3-py", - "title": "Web3.py", - "slug": "smart-contracts-libraries-web3-py", + "id": "tutorials-smart-contracts-launch-your-first-project-create-dapp-viem", + "title": "Create a dApp With Viem", + "slug": "tutorials-smart-contracts-launch-your-first-project-create-dapp-viem", "categories": [ - "Smart Contracts", + "dApp", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-py.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/web3-py/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project-create-dapp-viem.md", + "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/create-dapp-viem/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Decentralized applications (dApps) are a key component of the Web3 ecosystem, enabling developers to build applications that communicate directly with blockchain networks. Polkadot Hub, a blockchain with smart contract support, serves as a robust platform for deploying and interacting with dApps.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Project Overview", + "anchor": "project-overview" }, { "depth": 2, @@ -8859,18 +14934,43 @@ }, { "depth": 2, - "title": "Set Up the Web3 Provider", - "anchor": "set-up-the-web3-provider" + "title": "Install Dependencies", + "anchor": "install-dependencies" }, { "depth": 2, - "title": "Contract Deployment", - "anchor": "contract-deployment" + "title": "Connect to Polkadot Hub", + "anchor": "connect-to-polkadot-hub" }, { "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" + "title": "Set Up the Smart Contract Interface", + "anchor": "set-up-the-smart-contract-interface" + }, + { + "depth": 2, + "title": "Create the Wallet Connection Component", + "anchor": "create-the-wallet-connection-component" + }, + { + "depth": 2, + "title": "Create the Read Contract Component", + "anchor": "create-the-read-contract-component" + }, + { + "depth": 2, + "title": "Create the Write Contract Component", + "anchor": "create-the-write-contract-component" + }, + { + "depth": 2, + "title": "How It Works", + "anchor": "how-it-works" + }, + { + "depth": 2, + "title": "Conclusion", + "anchor": "conclusion" }, { "depth": 2, @@ -8879,24 +14979,24 @@ } ], "stats": { - "chars": 11627, - "words": 1333, - "headings": 6, - "estimated_token_count_total": 2509 + "chars": 27924, + "words": 3201, + "headings": 12, + "estimated_token_count_total": 6206 }, - "hash": "sha256:205892e350168b3d0da7ccc280c67c3217ad1e45e87a53d124fa1dd69661aa5e", + "hash": "sha256:cb8ddb4a61f6a62182420b69382f1c7ab2adc2f4ae643f7f68c6867680afe81f", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-overview", - "title": "Smart Contracts Overview", - "slug": "smart-contracts-overview", + "id": "tutorials-smart-contracts-launch-your-first-project-test-and-deploy-with-hardhat", + "title": "Test and Deploy with Hardhat", + "slug": "tutorials-smart-contracts-launch-your-first-project-test-and-deploy-with-hardhat", "categories": [ - "Basics", - "Smart Contracts" + "dApp", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md", - "html_url": "https://docs.polkadot.com/smart-contracts/overview/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project-test-and-deploy-with-hardhat.md", + "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/test-and-deploy-with-hardhat/", "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { @@ -8906,200 +15006,155 @@ }, { "depth": 2, - "title": "Native Smart Contracts", - "anchor": "native-smart-contracts" - }, - { - "depth": 3, - "title": "Introduction", - "anchor": "introduction-2" - }, - { - "depth": 3, - "title": "Smart Contract Development", - "anchor": "smart-contract-development" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Technical Architecture", - "anchor": "technical-architecture" + "depth": 2, + "title": "Setting Up the Development Environment", + "anchor": "setting-up-the-development-environment" }, { - "depth": 3, - "title": "Development Tools and Resources", - "anchor": "development-tools-and-resources" + "depth": 2, + "title": "Adding the Smart Contract", + "anchor": "adding-the-smart-contract" }, { - "depth": 3, - "title": "Cross-Chain Capabilities", - "anchor": "cross-chain-capabilities" + "depth": 2, + "title": "Writing Tests", + "anchor": "writing-tests" }, { - "depth": 3, - "title": "Use Cases", - "anchor": "use-cases" + "depth": 2, + "title": "Deploying with Ignition", + "anchor": "deploying-with-ignition" }, { "depth": 2, - "title": "Other Smart Contract Environments", - "anchor": "other-smart-contract-environments" + "title": "Interacting with Your Deployed Contract", + "anchor": "interacting-with-your-deployed-contract" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 6305, - "words": 804, - "headings": 10, - "estimated_token_count_total": 1122 + "chars": 18699, + "words": 2238, + "headings": 8, + "estimated_token_count_total": 4135 }, - "hash": "sha256:ee87115c828928c82937de26f5f938cecd4c3bb1225fdb61627e8092e6ea5951", + "hash": "sha256:ca1d65d450f086a0eb7b81e9589e9894e04b217fe9709a1b464f09beb3ca9dc2", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-precompiles-eth-native", - "title": "Ethereum-Native Precompiles", - "slug": "smart-contracts-precompiles-eth-native", + "id": "tutorials-smart-contracts-launch-your-first-project", + "title": "Launch Your First Project", + "slug": "tutorials-smart-contracts-launch-your-first-project", "categories": [ - "Smart Contracts" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-eth-native.md", - "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/eth-native/", - "preview": "Ethereum-native precompiles are special contract implementations that provide essential cryptographic and utility functions at the runtime level. These precompiles are available at predefined addresses and offer optimized, native implementations of commonly used operations that would be computationally expensive or impractical to implement in pure contract code.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project.md", + "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Kickstart your journey into smart contract development with this comprehensive guide. Learn how to create, deploy, and interact with contracts on Polkadot. Whether you're new to smart contracts or refining your skills, these guides provide a structured approach to launching your project.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "How to Use Precompiles", - "anchor": "how-to-use-precompiles" - }, - { - "depth": 2, - "title": "Standard Precompiles in Polkadot Hub", - "anchor": "standard-precompiles-in-polkadot-hub" + "title": "Development Pathway", + "anchor": "development-pathway" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 5232, - "words": 532, - "headings": 4, - "estimated_token_count_total": 1192 + "chars": 1211, + "words": 161, + "headings": 2, + "estimated_token_count_total": 77 }, - "hash": "sha256:f17db5daca8feae70ce428e03a5a4870ef87dfc8571b07376327cd80d057b759", + "hash": "sha256:8d8fc5f794d4c793586cd3d412627f5e2fe76f182c75c3687abcf33deed5d65e", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-precompiles-xcm", - "title": "Interact with the XCM Precompile", - "slug": "smart-contracts-precompiles-xcm", + "id": "tutorials-smart-contracts", + "title": "Smart Contracts", + "slug": "tutorials-smart-contracts", "categories": [ - "Smart Contracts" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-xcm.md", - "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/xcm/", - "preview": "The [XCM (Cross-Consensus Message)](/parachains/interoperability/get-started/){target=\\_blank} precompile enables Polkadot Hub developers to access XCM functionality directly from their smart contracts using a Solidity interface.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts.md", + "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Get started with deploying and interacting with smart contracts on Polkadot through practical, hands-on tutorials. Whether you're a beginner or an experienced developer, these guides will help you navigate the entire development lifecycle.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Precompile Interface", - "anchor": "precompile-interface" - }, - { - "depth": 2, - "title": "Interact with the XCM Precompile", - "anchor": "interact-with-the-xcm-precompile" - }, - { - "depth": 3, - "title": "Weigh a Message", - "anchor": "weigh-a-message" - }, - { - "depth": 3, - "title": "Execute a Message", - "anchor": "execute-a-message" - }, - { - "depth": 3, - "title": "Send a Message", - "anchor": "send-a-message" - }, - { - "depth": 2, - "title": "Cross Contract Calls", - "anchor": "cross-contract-calls" + "title": "What to Expect from These Tutorials", + "anchor": "what-to-expect-from-these-tutorials" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Start Building", + "anchor": "start-building" }, { "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 10705, - "words": 1436, - "headings": 9, - "estimated_token_count_total": 2325 + "chars": 1057, + "words": 145, + "headings": 3, + "estimated_token_count_total": 130 }, - "hash": "sha256:c084190ea7d676128e7e399e8fe88598ca150f88d684db279a687ee1c3956120", + "hash": "sha256:66bc34a12c50539dde2ffc69fe66891f73d3e1a2da5833ada15e26744ff32209", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-precompiles", - "title": "Advanced Functionalities via Precompiles", - "slug": "smart-contracts-precompiles", + "id": "tutorials", + "title": "Tutorials", + "slug": "tutorials", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles.md", - "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials.md", + "html_url": "https://docs.polkadot.com/tutorials/", + "preview": "Welcome to the Polkadot Tutorials hub! Whether you’re building parachains, integrating system chains, or developing decentralized applications, these step-by-step guides are designed to help you achieve your goals efficiently and effectively.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Polkadot Zero to Hero", + "anchor": "polkadot-zero-to-hero" + }, + { + "depth": 3, + "title": "Parachain Developers", + "anchor": "parachain-developers" }, { "depth": 2, - "title": "What are Precompiles?", - "anchor": "what-are-precompiles" + "title": "Featured Tutorials", + "anchor": "featured-tutorials" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "In This Section", + "anchor": "in-this-section" } ], "stats": { - "chars": 2525, - "words": 328, - "headings": 3, - "estimated_token_count_total": 412 + "chars": 2501, + "words": 355, + "headings": 4, + "estimated_token_count_total": 590 }, - "hash": "sha256:a40e3f34f70db22bfe39e40d68dc5a53a726ce47cb73b602d8605355c61ffd22", + "hash": "sha256:a1d7789d44e4653e98ed41b8a13ea69e7733803c598ca850c9e2fc8f27a2b410", "token_estimator": "heuristic-v1" } ] \ No newline at end of file diff --git a/llms-full.jsonl b/llms-full.jsonl index 9c1a59263..010a38dbe 100644 --- a/llms-full.jsonl +++ b/llms-full.jsonl @@ -431,9 +431,9 @@ {"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 5, "depth": 2, "title": "Compile the Runtime", "anchor": "compile-the-runtime", "start_char": 5097, "end_char": 6061, "estimated_token_count": 189, "token_estimator": "heuristic-v1", "text": "## Compile the Runtime\n\nNow that you understand the template structure, let's compile the runtime to ensure everything is working correctly.\n\n1. Compile the runtime:\n\n ```bash\n cargo build --release --locked\n ```\n\n !!!tip\n Initial compilation may take several minutes, depending on your machine specifications. Use the `--release` flag for improved runtime performance compared to the default `--debug` build. If you need to troubleshoot issues, the `--debug` build provides better diagnostics.\n \n For production deployments, consider using a dedicated `--profile production` flag - this can provide an additional 15-30% performance improvement over the standard `--release` profile.\n\n2. Upon successful compilation, you should see output indicating the build was successful. The compiled runtime will be located at:\n \n `./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`"} {"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 6, "depth": 2, "title": "Verify the Build", "anchor": "verify-the-build", "start_char": 6061, "end_char": 6394, "estimated_token_count": 71, "token_estimator": "heuristic-v1", "text": "## Verify the Build\n\nAfter compilation completes, verify that the runtime was created successfully by checking for the Wasm blob:\n\n```bash\nls -la ./target/release/wbuild/parachain-template-runtime/\n```\n\nYou should see the `parachain_template_runtime.compact.compressed.wasm` file in the output, confirming the build was successful."} {"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 7, "depth": 2, "title": "Run the Node Locally", "anchor": "run-the-node-locally", "start_char": 6394, "end_char": 8108, "estimated_token_count": 343, "token_estimator": "heuristic-v1", "text": "## Run the Node Locally\n\nAfter successfully compiling your runtime, you can spin up a local chain and produce blocks. This process will start your local parachain using the Polkadot Omni Node and allow you to interact with it. You'll first need to generate a chain specification that defines your network's identity, initial connections, and genesis state, providing the foundational configuration for how your nodes connect and what initial state they agree upon.\n\nFollow these steps to launch your node in development mode:\n\n1. Generate the chain specification file of your parachain:\n\n ```bash\n chain-spec-builder create -t development \\\n --relay-chain paseo \\\n --para-id 1000 \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \\\n named-preset development\n ```\n\n2. Start the Omni Node with the generated chain spec. You'll start it in development mode (without a relay chain config), producing and finalizing blocks:\n\n ```bash\n polkadot-omni-node --chain ./chain_spec.json --dev\n ```\n\n The `--dev` option does the following:\n\n - Deletes all active data (keys, blockchain database, networking information) when stopped.\n - Ensures a clean working state each time you restart the node.\n\n3. Verify that your node is running by reviewing the terminal output. You should see log messages indicating block production and finalization.\n\n4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output.\n\nThe details of the log output will be explored in a later tutorial. For now, knowing that your node is running and producing blocks is sufficient."} -{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 8, "depth": 2, "title": "Interact with the Node", "anchor": "interact-with-the-node", "start_char": 8108, "end_char": 9674, "estimated_token_count": 412, "token_estimator": "heuristic-v1", "text": "## Interact with the Node\n\nWhen running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} interface, follow these steps:\n\n1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner:\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp)\n\n2. Connect to your local node:\n\n 1. Scroll to the bottom and select **Development**.\n 2. Choose **Custom**.\n 3. Enter `ws://localhost:9944` in the **custom endpoint** input field.\n 4. Click the **Switch** button.\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp)\n\n3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain.\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp)\n\nYou are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\\_blank} available on the Polkadot Wiki."} -{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 9, "depth": 2, "title": "Stop the Node", "anchor": "stop-the-node", "start_char": 9674, "end_char": 10180, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "## Stop the Node\n\nWhen you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time.\n\nTo stop the local node:\n\n1. Return to the terminal window where the node output is displayed.\n2. Press `Control-C` to stop the running process.\n3. Verify that your terminal returns to the prompt in the `parachain-template` directory."} -{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 10, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 10180, "end_char": 10588, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Tutorial __Deploy to Polkadot__\n\n ---\n\n Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks.\n\n [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md)\n\n
"} +{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 8, "depth": 2, "title": "Interact with the Node", "anchor": "interact-with-the-node", "start_char": 8108, "end_char": 9677, "estimated_token_count": 414, "token_estimator": "heuristic-v1", "text": "## Interact with the Node\n\nWhen running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} interface, follow these steps:\n\n1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner:\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp)\n\n2. Connect to your local node:\n\n 1. Scroll to the bottom and select **Development**.\n 2. Choose **Custom**.\n 3. Enter `ws**: //localhost:9944` in the **custom endpoint** input field.\n 4. Click the **Switch** button.\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp)\n\n3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain.\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp)\n\nYou are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\\_blank} available on the Polkadot Wiki."} +{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 9, "depth": 2, "title": "Stop the Node", "anchor": "stop-the-node", "start_char": 9677, "end_char": 10183, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "## Stop the Node\n\nWhen you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time.\n\nTo stop the local node:\n\n1. Return to the terminal window where the node output is displayed.\n2. Press `Control-C` to stop the running process.\n3. Verify that your terminal returns to the prompt in the `parachain-template` directory."} +{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 10, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 10183, "end_char": 10591, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Tutorial __Deploy to Polkadot__\n\n ---\n\n Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks.\n\n [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md)\n\n
"} {"page_id": "parachains-runtime-maintenance-runtime-upgrades", "page_title": "Runtime Upgrades", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 20, "end_char": 926, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nOne of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.\n\nForkless upgrades are achieved through WebAssembly (Wasm) runtimes stored on-chain, which can be securely swapped and upgraded as part of the blockchain's state. By leveraging decentralized consensus, runtime updates can happen trustlessly, ensuring continuous improvement and evolution without halting operations.\n\nThis guide explains how Polkadot's runtime versioning, Wasm deployment, and storage migrations enable these upgrades, ensuring the blockchain evolves smoothly and securely. You'll also learn how different upgrade processes apply to solo chains and parachains, depending on the network setup."} {"page_id": "parachains-runtime-maintenance-runtime-upgrades", "page_title": "Runtime Upgrades", "index": 1, "depth": 2, "title": "How Runtime Upgrades Work", "anchor": "how-runtime-upgrades-work", "start_char": 926, "end_char": 1650, "estimated_token_count": 165, "token_estimator": "heuristic-v1", "text": "## How Runtime Upgrades Work\n\nIn FRAME, the [`system`](https://paritytech.github.io/polkadot-sdk/master/frame_system/index.html){target=\\_blank} pallet uses the [`set_code`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/enum.Call.html#variant.set_code){target=\\_blank} extrinsic to update the Wasm code for the runtime. This method allows solo chains to upgrade without disruption. \n\nFor parachains, upgrades are more complex. Parachains must first call `authorize_upgrade`, followed by `apply_authorized_upgrade`, to ensure the relay chain approves and applies the changes. Additionally, changes to current functionality that impact storage often require a [storage migration](#storage-migrations)."} {"page_id": "parachains-runtime-maintenance-runtime-upgrades", "page_title": "Runtime Upgrades", "index": 2, "depth": 3, "title": "Runtime Versioning", "anchor": "runtime-versioning", "start_char": 1650, "end_char": 4915, "estimated_token_count": 664, "token_estimator": "heuristic-v1", "text": "### Runtime Versioning\n\nThe executor is the component that selects the runtime execution environment to communicate with. Although you can override the default execution strategies for custom scenarios, in most cases, the executor selects the appropriate binary to use by evaluating and comparing key parameters from the native and Wasm runtime binaries.\n\nThe runtime includes a [runtime version struct](https://paritytech.github.io/polkadot-sdk/master/sp_version/struct.RuntimeVersion.html){target=\\_blank} to provide the needed parameter information to the executor process. A sample runtime version struct might look as follows:\n\n```rust\npub const VERSION: RuntimeVersion = RuntimeVersion {\n spec_name: create_runtime_str!(\"node-template\"),\n impl_name: create_runtime_str!(\"node-template\"),\n authoring_version: 1,\n spec_version: 1,\n impl_version: 1,\n apis: RUNTIME_API_VERSIONS,\n transaction_version: 1,\n};\n```\n\nThe struct provides the following parameter information to the executor:\n\n- **`spec_name`**: The identifier for the different runtimes.\n- **`impl_name`**: The name of the implementation of the spec. Serves only to differentiate code of different implementation teams.\n- **`authoring_version`**: The version of the authorship interface. An authoring node won't attempt to author blocks unless this is equal to its native runtime.\n- **`spec_version`**: The version of the runtime specification. A full node won't attempt to use its native runtime in substitute for the on-chain Wasm runtime unless the `spec_name`, `spec_version`, and `authoring_version` are all the same between the Wasm and native binaries. Updates to the `spec_version` can be automated as a CI process. This parameter is typically incremented when there's an update to the `transaction_version`.\n- **`impl_version`**: The version of the implementation of the specification. Nodes can ignore this. It is only used to indicate that the code is different. As long as the `authoring_version` and the `spec_version` are the same, the code might have changed, but the native and Wasm binaries do the same thing. In general, only non-logic-breaking optimizations would result in a change of the `impl_version`.\n- **`transaction_version`**: The version of the interface for handling transactions. This parameter can be useful to synchronize firmware updates for hardware wallets or other signing devices to verify that runtime transactions are valid and safe to sign. This number must be incremented if there is a change in the index of the pallets in the `construct_runtime!` macro or if there are any changes to dispatchable functions, such as the number of parameters or parameter types. If `transaction_version` is updated, then the `spec_version` must also be updated.\n- **`apis`**: A list of supported [runtime APIs](https://paritytech.github.io/polkadot-sdk/master/sp_api/macro.impl_runtime_apis.html){target=\\_blank} along with their versions.\n\nThe executor follows the same consensus-driven logic for both the native runtime and the Wasm runtime before deciding which to execute. Because runtime versioning is a manual process, there is a risk that the executor could make incorrect decisions if the runtime version is misrepresented or incorrectly defined."} @@ -858,13 +858,6 @@ {"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 4, "depth": 3, "title": "Astar XCM Tools", "anchor": "astar-xcm-tools", "start_char": 2667, "end_char": 4207, "estimated_token_count": 369, "token_estimator": "heuristic-v1", "text": "### Astar XCM Tools\n\nThe [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks:\n\n- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command.\n- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments.\n- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs.\n\nTo start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\\_blank} and compile the xcm-tools package:\n\n```bash\ngit clone https://github.com/AstarNetwork/Astar &&\ncd Astar &&\ncargo build --release -p xcm-tools\n```\n\nAfter compiling, verify the setup with the following command:\n\n```bash\n./target/release/xcm-tools --help\n```\nFor more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\\_blank}."} {"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 5, "depth": 3, "title": "Chopsticks", "anchor": "chopsticks", "start_char": 4207, "end_char": 4517, "estimated_token_count": 65, "token_estimator": "heuristic-v1", "text": "### Chopsticks\n\nThe Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\\_blank} about XCM."} {"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 6, "depth": 3, "title": "Moonbeam XCM SDK", "anchor": "moonbeam-xcm-sdk", "start_char": 4517, "end_char": 6146, "estimated_token_count": 385, "token_estimator": "heuristic-v1", "text": "### Moonbeam XCM SDK\n\nThe [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\\_blank} of the origin or destination assets or which extrinsics are used on which networks.\n\nThe SDK consists of two main packages:\n\n- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem.\n- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum.\n\nKey features include:\n\n- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection.\n- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems.\n- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality.\n- **Comprehensive documentation**: Includes usage guides and API references for both packages.\n\nFor detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\\_blank}."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 0, "end_char": 1097, "estimated_token_count": 199, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need.\n\nPolkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\\_blank} to the [governance](/reference/glossary#governance){target=\\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants.\n\nThis guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 1, "depth": 2, "title": "Polkadot Hub", "anchor": "polkadot-hub", "start_char": 1097, "end_char": 2378, "estimated_token_count": 247, "token_estimator": "heuristic-v1", "text": "## Polkadot Hub\n\n[Polkadot Hub](/reference/polkadot-hub/){target=\\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain.\n\nThe Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include:\n\n- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications.\n- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem.\n- **Staking**: Participate in network security and earn rewards by staking DOT.\n- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov.\n- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities.\n- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem.\n- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 2, "depth": 2, "title": "Parachains", "anchor": "parachains", "start_char": 2378, "end_char": 3697, "estimated_token_count": 293, "token_estimator": "heuristic-v1", "text": "## Parachains\n\n[Parachains](/reference/parachains/){target=\\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers:\n\n- **Accounts**: Deep dive into account types, storage, and management on parachains.\n- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms.\n- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus.\n- **Chain data**: Explore data structures, storage layouts, and state management.\n- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains.\n- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility.\n- **Networks**: Learn about networking protocols and peer-to-peer communication.\n- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\\_blank}, the standard for cross-chain communication.\n- **Randomness**: Understand how randomness is generated and used in Polkadot chains.\n- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 3, "depth": 2, "title": "On-Chain Governance", "anchor": "on-chain-governance", "start_char": 3697, "end_char": 4577, "estimated_token_count": 170, "token_estimator": "heuristic-v1", "text": "## On-Chain Governance\n\n[On-Chain governance](/reference/governance/){target=\\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details:\n\n- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums.\n- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity.\n- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance.\n- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 4, "depth": 2, "title": "Glossary", "anchor": "glossary", "start_char": 4577, "end_char": 5018, "estimated_token_count": 90, "token_estimator": "heuristic-v1", "text": "## Glossary\n\nThe [Glossary](/reference/glossary/){target=\\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include:\n\n- Blockchain concepts (blocks, transactions, state)\n- Consensus mechanisms (validators, collators, finality)\n- Polkadot-specific terms (relay chain, parachain, XCM, FRAME)\n- Network components (nodes, runtimes, storage)\n- Governance terminology (origins, tracks, referendums)"} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 5, "depth": 2, "title": "Tools", "anchor": "tools", "start_char": 5018, "end_char": 6285, "estimated_token_count": 349, "token_estimator": "heuristic-v1", "text": "## Tools\n\nThe [Tools](/reference/tools/){target=\\_blank} section documents essential development and interaction tools for the Polkadot ecosystem:\n\n- **Light clients**: Lightweight solutions for interacting with the network without running full nodes.\n- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\\_blank} and [PAPI](/reference/tools/papi/){target=\\_blank} for building applications.\n- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\\_blank} and other Rust-based libraries for SDK development.\n- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\\_blank} for Python developers.\n- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\\_blank}, and [Omninode](/reference/tools/omninode/){target=\\_blank} for smart contract and parachain testing.\n- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\\_blank} for substrate interaction.\n- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\\_blank} for XCM integration and asset transfers."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 6, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 6285, "end_char": 7648, "estimated_token_count": 334, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor detailed exploration of specific areas, proceed to any of the main sections:\n\n
\n\n- Learn **Polkadot Hub**\n\n ---\n\n Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance.\n\n [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/)\n\n- Learn **Parachains**\n\n ---\n\n Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains.\n\n [:octicons-arrow-right-24: Reference](/reference/parachains/)\n\n- Learn **On-Chain Governance**\n\n ---\n\n Explore Polkadot's decentralized governance framework and how to participate in network decision-making.\n\n [:octicons-arrow-right-24: Reference](/reference/governance/)\n\n- Guide **Glossary**\n\n ---\n\n Quick reference for Polkadot-specific terminology and concepts used throughout the documentation.\n\n [:octicons-arrow-right-24: Reference](/reference/glossary/)\n\n- Guide **Tools**\n\n ---\n\n Discover development tools, libraries, and frameworks for building and interacting with Polkadot.\n\n [:octicons-arrow-right-24: Reference](/reference/tools/)\n\n
"} {"page_id": "smart-contracts-connect", "page_title": "Connect to Polkadot", "index": 0, "depth": 2, "title": "Networks Details", "anchor": "networks-details", "start_char": 951, "end_char": 1604, "estimated_token_count": 137, "token_estimator": "heuristic-v1", "text": "## Networks Details\n\nDevelopers can leverage smart contracts across diverse networks, from TestNets to MainNet. This section outlines the network specifications and connection details for each environment.\n\n=== \"Polkadot Hub TestNet\"\n\n Network name\n\n ```text\n Polkadot Hub TestNet\n ```\n\n ---\n\n Currency symbol\n \n ```text\n PAS\n ```\n\n ---\n \n Chain ID\n \n ```text\n 420420422\n ```\n\n ---\n \n RPC URL\n \n ```text\n https://testnet-passet-hub-eth-rpc.polkadot.io\n ```\n\n ---\n \n Block explorer URL\n \n ```text\n https://blockscout-passet-hub.parity-testnet.parity.io/\n ```"} {"page_id": "smart-contracts-connect", "page_title": "Connect to Polkadot", "index": 1, "depth": 2, "title": "Test Tokens", "anchor": "test-tokens", "start_char": 1604, "end_char": 2618, "estimated_token_count": 233, "token_estimator": "heuristic-v1", "text": "## Test Tokens\n\nYou will need testnet tokens to perform transactions and engage with smart contracts on any chain. Here's how to obtain Paseo (PAS) tokens for testing purposes:\n\n1. Navigate to the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank}. If the desired network is not already selected, choose it from the Network drop-down.\n\n2. Copy your address linked to the TestNet and paste it into the designated field.\n\n ![](/images/smart-contracts/connect/connect-to-polkadot-01.webp)\n\n3. Click the **Get Some PASs** button to request free test PAS tokens. These tokens will be sent to your wallet shortly.\n\n ![](/images/smart-contracts/connect/connect-to-polkadot-02.webp)\n\nNow that you have obtained PAS tokens in your wallet, you’re ready to deploy and interact with smart contracts on Polkadot Hub TestNet! These tokens will allow you to pay for gas fees when executing transactions, deploying contracts, and testing your dApp functionality in a secure testnet environment."} {"page_id": "smart-contracts-connect", "page_title": "Connect to Polkadot", "index": 2, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 2618, "end_char": 3459, "estimated_token_count": 188, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor your next steps, explore the various smart contract guides demonstrating how to use and integrate different tools and development environments into your workflow.\n\n
\n\n- Guide __Deploy your first contract with Remix__\n\n ---\n\n Explore the smart contract development and deployment process on Polkadot Hub using the Remix IDE.\n\n [:octicons-arrow-right-24: Build with Remix IDE](/smart-contracts/dev-environments/remix/get-started/)\n\n- Guide __Interact with the blockchain with viem__\n\n ---\n\n Use viem for interacting with Ethereum-compatible chains, to deploy and interact with smart contracts on Polkadot Hub.\n\n [:octicons-arrow-right-24: Build with viem](/smart-contracts/libraries/viem/)\n\n
"} @@ -982,20 +975,30 @@ {"page_id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", "page_title": "Deploy an NFT to Polkadot Hub with Remix", "index": 4, "depth": 2, "title": "Compile", "anchor": "compile", "start_char": 2209, "end_char": 2528, "estimated_token_count": 88, "token_estimator": "heuristic-v1", "text": "## Compile\n\n1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar).\n2. Click **Compile MyNFT.sol** or press `Ctrl+S`.\n\n![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-02.webp)\n\nCompilation errors and warnings appear in the terminal panel at the bottom of the screen."} {"page_id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", "page_title": "Deploy an NFT to Polkadot Hub with Remix", "index": 5, "depth": 2, "title": "Deploy", "anchor": "deploy", "start_char": 2528, "end_char": 3157, "estimated_token_count": 163, "token_estimator": "heuristic-v1", "text": "## Deploy\n\n1. Navigate to the **Deploy & Run Transactions** tab.\n2. Click the **Environment** dropdown, select **Browser Extension**, and click on **Injected Provider - MetaMask**.\n\n ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-03.webp)\n\n3. In the deploy section, enter the initial owner address in the constructor parameter field.\n4. Click **Deploy**.\n\n ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-04.webp)\n\n5. Approve the transaction in your MetaMask wallet.\n\nYour deployed contract will appear in the **Deployed Contracts** section, ready for interaction."} {"page_id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", "page_title": "Deploy an NFT to Polkadot Hub with Remix", "index": 6, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 3157, "end_char": 3754, "estimated_token_count": 163, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Guide __Verify Your Contract__\n\n ---\n\n Now that you've deployed an NFT contract, learn how to verify it with Remix.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/verify-a-contract/)\n\n- Guide __Deploy an ERC-20__\n\n ---\n\n Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Remix.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/)\n\n
"} -{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 0, "depth": 2, "title": "Get Tokens from the Faucet", "anchor": "get-tokens-from-the-faucet", "start_char": 222, "end_char": 796, "estimated_token_count": 236, "token_estimator": "heuristic-v1", "text": "## Get Tokens from the Faucet\n\n| Title | Difficulty | Tools | Description |\n|------------------------------------|:-----------:|-------|-----------------------------------------------------------------------------------------------------------------------|\n| [Faucet](/smart-contracts/faucet/) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. |"} -{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 1, "depth": 2, "title": "EVM/PVM Smart Contracts", "anchor": "evmpvm-smart-contracts", "start_char": 796, "end_char": 2051, "estimated_token_count": 461, "token_estimator": "heuristic-v1", "text": "## EVM/PVM Smart Contracts\n\n| Title | Difficulty | Tools | Description |\n|---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. |\n| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. |"} -{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 2, "depth": 2, "title": "Port Ethereum DApps", "anchor": "port-ethereum-dapps", "start_char": 2051, "end_char": 2815, "estimated_token_count": 317, "token_estimator": "heuristic-v1", "text": "## Port Ethereum DApps\n\n| Title | Difficulty | Tools | Description |\n|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------|\n| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. |"} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 0, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 996, "end_char": 1270, "estimated_token_count": 47, "token_estimator": "heuristic-v1", "text": "## Overview\n\nHardhat is a robust development environment for Ethereum-compatible chains that makes smart contract development more efficient. This guide walks you through the essentials of using Hardhat to create, compile, test, and deploy smart contracts on Polkadot Hub."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 1270, "end_char": 1843, "estimated_token_count": 159, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore getting started, ensure you have:\n\n- [Node.js](https://nodejs.org/){target=\\_blank} (v16.0.0 or later) and npm installed.\n - Note: Use Node.js 22.5+ and npm version 10.9.0+ to avoid issues with the Polkadot plugin.\n- Basic understanding of Solidity programming.\n- Some PAS test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank}). To learn how to get test tokens, check out the [Test Tokens](/smart-contracts/connect/#test-tokens){target=\\_blank} section."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 2, "depth": 2, "title": "Set Up Hardhat", "anchor": "set-up-hardhat", "start_char": 1843, "end_char": 3260, "estimated_token_count": 317, "token_estimator": "heuristic-v1", "text": "## Set Up Hardhat\n\n1. Create a new directory for your project and navigate into it:\n\n ```bash\n mkdir hardhat-example\n cd hardhat-example\n ```\n\n2. Initialize a new npm project:\n\n ```bash\n npm init -y\n ```\n\n3. To interact with Polkadot, Hardhat requires the following plugin to compile contracts to PolkaVM bytecode and to spawn a local node compatible with PolkaVM:\n\n ```bash\n npm install --save-dev @parity/hardhat-polkadot@0.1.9\n ```\n\n4. Create a Hardhat project:\n\n ```bash\n npx hardhat-polkadot init\n ```\n\n Select **Create a JavaScript project** when prompted and follow the instructions. After that, your project will be created with three main folders:\n\n - **`contracts`**: Where your Solidity smart contracts live.\n - **`test`**: Contains your test files that validate contract functionality.\n - **`ignition`**: Deployment modules for safely deploying your contracts to various networks.\n\n5. Add the following folder to the `.gitignore` file if it is not already there:\n\n ```bash\n echo '/ignition/deployments/' >> .gitignore\n ```\n\n6. Finish the setup by installing all the dependencies:\n\n ```bash\n npm install\n ```\n\n !!! note\n This last step is needed to set up the `hardhat-polkadot` plugin. It will install the `@parity/hardhat-polkadot` package and all its dependencies. In the future, the plugin will handle this automatically."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 3, "depth": 2, "title": "Compile Your Contract", "anchor": "compile-your-contract", "start_char": 3260, "end_char": 6658, "estimated_token_count": 763, "token_estimator": "heuristic-v1", "text": "## Compile Your Contract\n\nThe plugin will compile your Solidity contracts for Solidity versions `0.8.0` and higher to be PolkaVM compatible. When compiling your contract, there are two ways to configure your compilation process:\n\n- **npm compiler**: Uses library [@parity/resolc](https://www.npmjs.com/package/@parity/resolc){target=\\_blank} for simplicity and ease of use.\n- **Binary compiler**: Uses your local `resolc` binary directly for more control and configuration options.\n\nTo compile your project, follow these instructions:\n\n1. Modify your Hardhat configuration file to specify which compilation process you will be using and activate the `polkavm` flag in the Hardhat network:\n\n === \"npm Configuration\"\n\n ```javascript title=\"hardhat.config.js\" hl_lines=\"9-11 14\"\n // hardhat.config.js\n require('@nomicfoundation/hardhat-toolbox');\n\n require('@parity/hardhat-polkadot');\n\n /** @type import('hardhat/config').HardhatUserConfig */\n module.exports = {\n solidity: '0.8.28',\n resolc: {\n compilerSource: 'npm',\n },\n networks: {\n hardhat: {\n polkavm: true,\n },\n },\n };\n ```\n\n === \"Binary Configuration\"\n\n ```javascript title=\"hardhat.config.js\" hl_lines=\"9-14 17\"\n // hardhat.config.js\n require('@nomicfoundation/hardhat-toolbox');\n\n require('@parity/hardhat-polkadot');\n\n /** @type import('hardhat/config').HardhatUserConfig */\n module.exports = {\n solidity: '0.8.28',\n resolc: {\n compilerSource: 'binary',\n settings: {\n compilerPath: 'INSERT_PATH_TO_RESOLC_COMPILER',\n },\n },\n networks: {\n hardhat: {\n polkavm: true,\n },\n },\n };\n ```\n\n For the binary configuration, replace `INSERT_PATH_TO_RESOLC_COMPILER` with the proper path to the binary. To obtain the binary, check the [releases](https://github.com/paritytech/revive/releases){target=\\_blank} section of the `resolc` compiler, and download the latest version.\n\n The default settings used can be found in the [`constants.ts`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/constants.ts#L8-L23){target=\\_blank} file of the `hardhat-polkadot` source code. You can change them according to your project needs. Generally, the recommended settings for optimized outputs are the following:\n\n ```javascript title=\"hardhat.config.js\" hl_lines=\"4-10\"\n resolc: {\n ...\n settings: {\n optimizer: {\n enabled: true,\n parameters: 'z',\n fallbackOz: true,\n runs: 200,\n },\n standardJson: true,\n },\n ...\n }\n ```\n\n You can check the [`ResolcConfig`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/types.ts#L26){target=\\_blank} for more information about compilation settings.\n\n2. Compile the contract with Hardhat:\n\n ```bash\n npx hardhat compile\n ```\n\n3. After successful compilation, you'll see the artifacts generated in the `artifacts-pvm` directory:\n\n ```bash\n ls artifacts-pvm/contracts/*.sol/\n ```\n\n You should see JSON files containing the contract ABI and bytecode of the contracts you compiled."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 4, "depth": 2, "title": "Set Up a Testing Environment", "anchor": "set-up-a-testing-environment", "start_char": 6658, "end_char": 10710, "estimated_token_count": 1069, "token_estimator": "heuristic-v1", "text": "## Set Up a Testing Environment\n\nHardhat allows you to spin up a local testing environment to test and validate your smart contract functionalities before deploying to live networks. The `hardhat-polkadot` plugin provides the possibility to spin up a local node with an ETH-RPC adapter for running local tests.\n\nFor complete isolation and control over the testing environment, you can configure Hardhat to work with a fresh local Substrate node. This approach is ideal when you want to test in a clean environment without any existing state or when you need specific node configurations.\n\nConfigure a local node setup by adding the node binary path along with the ETH-RPC adapter path:\n\n```javascript title=\"hardhat.config.js\" hl_lines=\"12-20\"\n// hardhat.config.js\nrequire('@nomicfoundation/hardhat-toolbox');\n\nrequire('@parity/hardhat-polkadot');\n/** @type import('hardhat/config').HardhatUserConfig */\nmodule.exports = {\n ...\n networks: {\n hardhat: {\n polkavm: true,\n nodeConfig: {\n nodeBinaryPath: 'INSERT_PATH_TO_SUBSTRATE_NODE',\n rpcPort: 8000,\n dev: true,\n },\n adapterConfig: {\n adapterBinaryPath: 'INSERT_PATH_TO_ETH_RPC_ADAPTER',\n dev: true,\n },\n },\n },\n};\n```\n\nReplace `INSERT_PATH_TO_SUBSTRATE_NODE` and `INSERT_PATH_TO_ETH_RPC_ADAPTER` with the actual paths to your compiled binaries. The `dev: true` flag configures both the node and adapter for development mode. To obtain these binaries, check the [Installation](/smart-contracts/dev-environments/local-dev-node/#install-the-substrate-node-and-eth-rpc-adapter){target=\\_blank} section on the Local Development Node page.\n\n!!! warning\n If you're using the default `hardhat.config.js` created by the `hardhat-polkadot` plugin, it includes a `forking` section pointing to the Polkadot Hub TestNet. When you run `npx hardhat node`, Hardhat will start a fork of that network. To use your local node instead, comment out the `forking` section; otherwise, `npx hardhat node` will continue to use the forked network even if a local node is defined in the configuration.\n\nOnce configured, start your chosen testing environment with:\n\n```bash\nnpx hardhat node\n```\n\nThis command will launch either the forked network or local node (depending on your configuration) along with the ETH-RPC adapter, providing you with a complete testing environment ready for contract deployment and interaction. By default, the Substrate node will be running on `localhost:8000` and the ETH-RPC adapter on `localhost:8545`.\n\nThe output will be something like this:\n\n
\n npx hardhat node\n
\n Starting server at 127.0.0.1:8000\n ../bin/substrate-node --rpc-port=8000 --dev\n Starting the Eth RPC Adapter at 127.0.0.1:8545\n ../bin/eth-rpc --node-rpc-url=ws://localhost:8000 --dev\n 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled.\n 2025-05-29 13:00:32 Running in --dev mode, RPC CORS has been disabled.\n 2025-05-29 13:00:32 🌐 Connecting to node at: ws://localhost:8000 ...\n 2025-05-29 13:00:32 Substrate Node\n 2025-05-29 13:00:32 ✌️ version 3.0.0-dev-f73c228b7a1\n 2025-05-29 13:00:32 ❤️ by Parity Technologies <admin@parity.io>, 2017-2025\n 2025-05-29 13:00:32 📋 Chain specification: Development\n 2025-05-29 13:00:32 🏷 Node name: electric-activity-4221\n 2025-05-29 13:00:32 👤 Role: AUTHORITY\n 2025-05-29 13:00:32 💾 Database: RocksDb at /var/folders/f4/7rdt2m9d7j361dm453cpggbm0000gn/T/substrateOaoecu/chains/dev/db/full\n 2025-05-29 13:00:36 [0] 💸 generated 1 npos voters, 1 from validators and 0 nominators\n ...\n
"} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 5, "depth": 2, "title": "Test Your Contract", "anchor": "test-your-contract", "start_char": 10710, "end_char": 11609, "estimated_token_count": 224, "token_estimator": "heuristic-v1", "text": "## Test Your Contract\n\nWhen testing your contract, be aware that [`@nomicfoundation/hardhat-toolbox/network-helpers`](https://hardhat.org/hardhat-network-helpers/docs/overview){target=\\_blank} is not fully compatible with Polkadot Hub's available RPCs. Specifically, Hardhat-only helpers like `time` and `loadFixture` may not work due to missing RPC calls in the node. For more details, refer to the [Compatibility](https://github.com/paritytech/hardhat-polkadot/tree/main/packages/hardhat-polkadot-node#compatibility){target=\\_blank} section in the `hardhat-revive` docs. You should avoid using helpers like `time` and `loadFixture` when writing tests.\n\nTo run your test:\n\n1. Update the `hardhat.config.js` file accordingly to the [Set Up a Testing Environment](#set-up-a-testing-environment) section.\n\n2. Execute the following command to run your tests:\n\n ```bash\n npx hardhat test\n ```"} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 6, "depth": 2, "title": "Deploy to a Local Node", "anchor": "deploy-to-a-local-node", "start_char": 11609, "end_char": 12747, "estimated_token_count": 267, "token_estimator": "heuristic-v1", "text": "## Deploy to a Local Node\n\nBefore deploying to a live network, you can deploy your contract to a local node using [Ignition](https://hardhat.org/ignition/docs/getting-started#overview){target=\\_blank} modules:\n\n1. Update the Hardhat configuration file to add the local network as a target for local deployment:\n\n ```javascript title=\"hardhat.config.js\" hl_lines=\"13-16\"\n // hardhat.config.js\n require('@nomicfoundation/hardhat-toolbox');\n\n require('@parity/hardhat-polkadot');\n /** @type import('hardhat/config').HardhatUserConfig */\n module.exports = {\n ...\n networks: {\n hardhat: {\n ...\n },\n localNode: {\n polkavm: true,\n url: `http://127.0.0.1:8545`,\n },\n },\n },\n };\n ```\n\n2. Start a local node:\n\n ```bash\n npx hardhat node\n ```\n\n This command will spawn a local Substrate node along with the ETH-RPC adapter.\n\n3. In a new terminal window, deploy the contract using Ignition:\n\n ```bash\n npx hardhat ignition deploy ./ignition/modules/MyToken.js --network localNode\n ```"} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 7, "depth": 2, "title": "Deploying to a Live Network", "anchor": "deploying-to-a-live-network", "start_char": 12747, "end_char": 14963, "estimated_token_count": 489, "token_estimator": "heuristic-v1", "text": "## Deploying to a Live Network\n\nAfter testing your contract locally, you can deploy it to a live network. This guide will use the Polkadot Hub TestNet as the target network. Here's how to configure and deploy:\n\n1. Fund your deployment account with enough tokens to cover gas fees. In this case, the needed tokens are PAS (on Polkadot Hub TestNet). You can use the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank} to obtain testing tokens.\n\n2. Export your private key and save it in your Hardhat environment:\n\n ```bash\n npx hardhat vars set PRIVATE_KEY \"INSERT_PRIVATE_KEY\"\n ```\n\n Replace `INSERT_PRIVATE_KEY` with your actual private key. For further details on private key exportation, refer to the article [How to export an account's private key](https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/){target=\\_blank}.\n\n !!! warning\n Never reveal your private key, otherwise anyone with access to it can control your wallet and steal your funds. Store it securely and never share it publicly or commit it to version control systems.\n\n3. Check that your private key has been set up successfully by running:\n\n ```bash\n npx hardhat vars get PRIVATE_KEY\n ```\n\n4. Update your Hardhat configuration file with network settings for the Polkadot network you want to target:\n\n ```javascript title=\"hardhat.config.js\" hl_lines=\"18-22\"\n // hardhat.config.js\n require('@nomicfoundation/hardhat-toolbox');\n\n require('@parity/hardhat-polkadot');\n const { vars } = require('hardhat/config');\n\n /** @type import('hardhat/config').HardhatUserConfig */\n module.exports = {\n ...\n networks: {\n hardhat: {\n ...\n },\n localNode: {\n ...\n },\n polkadotHubTestnet: {\n polkavm: true,\n url: 'https://testnet-passet-hub-eth-rpc.polkadot.io',\n accounts: [vars.get('PRIVATE_KEY')],\n },\n },\n },\n };\n ```\n\n6. Deploy your contract using Ignition:\n\n ```bash\n npx hardhat ignition deploy ./ignition/modules/MyToken.js --network polkadotHubTestnet\n ```"} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 8, "depth": 2, "title": "Interacting with Your Contract", "anchor": "interacting-with-your-contract", "start_char": 14963, "end_char": 16763, "estimated_token_count": 426, "token_estimator": "heuristic-v1", "text": "## Interacting with Your Contract\n\nOnce deployed, you can create a script to interact with your contract. To do so, create a file called `scripts/interact.js` and add some logic to interact with the contract.\n\nFor example, for the default `MyToken.sol` contract, you can use the following file that connects to the contract at its address and retrieves the `unlockTime`, which represents when funds can be withdrawn. The script converts this timestamp into a readable date and logs it. It then checks the contract's balance and displays it. Finally, it attempts to call the withdrawal function on the contract, but it catches and logs the error message if the withdrawal is not yet allowed (e.g., before `unlockTime`).\n\n```javascript title=\"interact.js\"\nconst hre = require('hardhat');\n\nasync function main() {\n // Get the contract factory\n const MyToken = await hre.ethers.getContractFactory('MyToken');\n\n // Replace with your deployed contract address\n const contractAddress = 'INSERT_CONTRACT_ADDRESS';\n\n // Attach to existing contract\n const token = await MyToken.attach(contractAddress);\n\n // Get signers\n const [deployer] = await hre.ethers.getSigners();\n\n // Read contract state\n const name = await token.name();\n const symbol = await token.symbol();\n const totalSupply = await token.totalSupply();\n const balance = await token.balanceOf(deployer.address);\n\n console.log(`Token: ${name} (${symbol})`);\n console.log(\n `Total Supply: ${hre.ethers.formatUnits(totalSupply, 18)} tokens`,\n );\n console.log(\n `Deployer Balance: ${hre.ethers.formatUnits(balance, 18)} tokens`,\n );\n}\n\nmain().catch((error) => {\n console.error(error);\n process.exitCode = 1;\n});\n\n```\n\nRun your interaction script:\n\n```bash\nnpx hardhat run scripts/interact.js --network polkadotHubTestnet\n```"} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 9, "depth": 2, "title": "Upgrading the Plugin", "anchor": "upgrading-the-plugin", "start_char": 16763, "end_char": 17423, "estimated_token_count": 176, "token_estimator": "heuristic-v1", "text": "## Upgrading the Plugin\n\nIf you already have a Hardhat Polkadot project and want to upgrade to a newer version of the plugin, to avoid errors (for example, `Cannot find module 'run-container'`), you can clean your dependencies by running the following commands:\n\n```bash\nrm -rf node_modules package-lock.json\n```\n\nAfter that, you can upgrade the plugin to the latest version by running the following commands:\n\n```bash\nnpm install --save-dev @parity/hardhat-polkadot@latest\nnpm install\n```\n\nConsider using [Node.js](https://nodejs.org/){target=\\_blank} 22.18+ and [npm](https://www.npmjs.com/){target=\\_blank} version 10.9.0+ to avoid issues with the plugin."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 10, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 17423, "end_char": 18514, "estimated_token_count": 253, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nHardhat provides a powerful environment for developing, testing, and deploying smart contracts on Polkadot Hub. Its plugin architecture allows seamless integration with PolkaVM through the `hardhat-resolc` and `hardhat-revive-node` plugins.\n\nExplore more about smart contracts through these resources:\n\n
\n\n- Guide __Get Started with Smart Contracts__\n\n ---\n\n Learn how to get started with smart contracts\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/get-started/)\n\n- External __Hardhat Documentation__\n\n ---\n\n Learn more about Hardhat's advanced features and best practices.\n\n [:octicons-arrow-right-24: Get Started](https://hardhat.org/docs){target=\\_blank}\n\n- External __OpenZeppelin Contracts__\n\n ---\n\n Test your skills by deploying contracts with prebuilt templates.\n\n [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\\_blank}\n\n
"} +{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 0, "depth": 2, "title": "Get Tokens from the Faucet", "anchor": "get-tokens-from-the-faucet", "start_char": 222, "end_char": 521, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Get Tokens from the Faucet\n\n| Title | Difficulty | Tools | Description |\n|-------|:----------:|-------|-------------|\n| [Faucet](/smart-contracts/faucet) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. |"} +{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 1, "depth": 2, "title": "EVM/PVM Smart Contracts", "anchor": "evmpvm-smart-contracts", "start_char": 521, "end_char": 1227, "estimated_token_count": 193, "token_estimator": "heuristic-v1", "text": "## EVM/PVM Smart Contracts\n\n| Title | Difficulty | Tools | Description |\n|-------|:----------:|-------|-------------|\n| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. |\n| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. |"} +{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 2, "depth": 2, "title": "Port Ethereum DApps", "anchor": "port-ethereum-dapps", "start_char": 1227, "end_char": 1586, "estimated_token_count": 114, "token_estimator": "heuristic-v1", "text": "## Port Ethereum DApps\n\n| Title | Difficulty | Tools | Description |\n|-------|:----------:|-------|-------------|\n| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. |"} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 0, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 182, "end_char": 918, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "## Overview\n\nFoundry is a fast, modular, and extensible toolkit for Ethereum application development written in Rust. It provides a suite of command-line tools, including `forge` for compiling, testing, and deploying smart contracts and `cast` for interacting with blockchains.\n\n[`foundry-polkadot`](https://github.com/paritytech/foundry-polkadot/){target=\\_blank} is an adaptation explicitly engineered for the Polkadot Hub, tailored for developers already familiar with Foundry who seek to leverage its capabilities within the Polkadot ecosystem. Additionally, this guide offers detailed information on the `forge` and `cast` commands supported within `foundry-polkadot`, complete with simple, runnable examples for quick reference."} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 1, "depth": 2, "title": "Installation", "anchor": "installation", "start_char": 918, "end_char": 1764, "estimated_token_count": 175, "token_estimator": "heuristic-v1", "text": "## Installation\n\nThe installation process is tailored for the Polkadot variant:\n\n- `foundry-polkadot` is installed via `foundryup-polkadot`, its dedicated installer. To get started, open your terminal and execute:\n\n ```bash\n curl -L https://raw.githubusercontent.com/paritytech/foundry-polkadot/refs/heads/master/foundryup/install | bash\n ```\n\n This command starts the installation of `foundryup-polkadot`. After installation, run the following command to download the precompiled `foundry-polkadot` binaries:\n\n ```bash\n foundryup-polkadot\n ```\n\n This command will install the `forge` and `cast` binaries, which are explained below. Windows users must use a Unix-like terminal environment such as Git BASH or Windows Subsystem for Linux (WSL), as PowerShell and Command Prompt are not currently supported by `foundryup`."} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 2, "depth": 2, "title": "Compiler Integration", "anchor": "compiler-integration", "start_char": 1764, "end_char": 3194, "estimated_token_count": 317, "token_estimator": "heuristic-v1", "text": "## Compiler Integration\n\nA core divergence lies in the underlying Solidity compiler.\n\n- `foundry` is built to interface with the `solc` compiler, which targets Ethereum's Ethereum Virtual Machine (EVM).\n- `foundry-polkadot`, in contrast, introduces and primarily utilizes the `resolc` compiler to compile down Solidity contracts into PolkaVM bytecode. \n\n - **Command-Line Flag**: For commands that involve compilation (e.g., `forge build`), you can use the `--resolc` flag to enable `resolc` compilation. For example:\n\n ```bash\n forge build --resolc\n ```\n\n This command instructs Forge to use `resolc` instead of `solc`, generating bytecode compatible with PolkaVM.\n\n - **Configuration File**: Alternatively, you can configure `resolc` usage in the `foundry.toml` file. Add the following:\n\n ```toml\n [profile.default.resolc]\n resolc_compile = true\n ```\n\n Setting `resolc_compile = false` reverts to using `solc`, ensuring compatibility with Ethereum projects. By default, `foundry-polkadot` uses `solc` unless `resolc` is explicitly enabled. `resolc` also exposes specific options for fine-tuning the compilation process, such as `--use-resolc ` for specifying a compiler version or path, `-O, --resolc-optimizer-mode ` for setting optimization levels, and `--heap-size ` and `--stack-size ` for configuring contract memory."} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 3, "depth": 2, "title": "Command-Line Interface (CLI)", "anchor": "command-line-interface-cli", "start_char": 3194, "end_char": 3571, "estimated_token_count": 85, "token_estimator": "heuristic-v1", "text": "## Command-Line Interface (CLI)\n\n`foundry-polkadot` preserves the familiar `forge` and `cast` subcommand structure. However, it's crucial to note that commands which involve compilation (such as `create`, `bind`, `build`, and `inspect`) will yield different output when `resolc` is utilized, as the generated bytecode is specifically designed for PolkaVM rather than the EVM."} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 4, "depth": 2, "title": "Unsupported or Modified Features", "anchor": "unsupported-or-modified-features", "start_char": 3571, "end_char": 4537, "estimated_token_count": 189, "token_estimator": "heuristic-v1", "text": "## Unsupported or Modified Features\n\nNot all functionalities from the original Foundry are present or behave identically in `foundry-polkadot`:\n\n- **Currently unsupported**:\n - Compilation of Yul code is not yet supported.\n - Support for factory contracts deployment is a known issue that is currently unresolved.\n- **Broader feature limitations**: Integration with `Anvil` and `Chisel` (Foundry's local blockchain and EVM toolkit, respectively) is not available. This limitation directly impacts the support for several key commands, including `forge test` for running tests, `forge snapshot` for creating blockchain state snapshots, and `forge script` for complex deployment and interaction scripts.\n- **Modified feature**: The most notable modification is in the **compilation output**. When ``resolc`` is employed, the resulting bytecode will fundamentally differ from that generated by ``solc``, reflecting PolkaVM's distinct architectural requirements."} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 5, "depth": 2, "title": "Set up a Project", "anchor": "set-up-a-project", "start_char": 4537, "end_char": 5517, "estimated_token_count": 223, "token_estimator": "heuristic-v1", "text": "## Set up a Project\n\nInitialize a new project using `forge init`:\n\n```bash\nforge init my-polkadot-project\ncd my-polkadot-project\n```\n\nThis command creates a complete project structure with the following components:\n\n- **`src/`**: Contains the Solidity smart contracts (includes a sample `Counter.sol` contract by default).\n- **`lib/`**: Houses external dependencies and libraries (`forge-std` testing library is included).\n- **`script/`**: Stores deployment and interaction scripts (includes `Counter.s.sol` deployment script by default).\n- **`test/`**: Contains your contract tests (includes `Counter.t.sol` test file by default).\n- **`foundry.toml`**: Main configuration file for compiler settings, network configurations, and project preferences.\n\nThe default project includes a simple `Counter` contract that demonstrates basic state management through increment and decrement functions, along with corresponding tests and deployment scripts to help you get started quickly."} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 6, "depth": 2, "title": "Compile a Project", "anchor": "compile-a-project", "start_char": 5517, "end_char": 6260, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "## Compile a Project\n\nCompile contracts using `forge build`:\n\n```bash\nforge build --resolc\n```\n\n!!!note \n You can still use `forge build` for compiling to regular EVM bytecode.\n\nPolkaVM bytecode starts with `0x505` prefix. Inspect compiled artifacts with:\n\n```bash\nforge inspect Counter bytecode --resolc\n```\n\nIf successful, you will see the following output:\n\n
\n forge inspect Counter bytecode --resolc\n 0x50564d00008213000000000000010700c13000c0008004808f08000000000e0000001c0000002a0000003500000040000000520000005d00000063616c6c5f646174615f636f707963616c6c5f646174615f6c6f616463616c6c5f646174615f73697a65676574...\n
"} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 7, "depth": 2, "title": "Deploy a Contract", "anchor": "deploy-a-contract", "start_char": 6260, "end_char": 7390, "estimated_token_count": 329, "token_estimator": "heuristic-v1", "text": "## Deploy a Contract\n\nDeploy contracts using `forge create`:\n\n```bash\nforge create Counter \\\n --rpc-url \\\n --private-key \\\n --resolc\n```\n\nIf the operation completes successfully, you'll see the following output (for example, to deploy to the Passet Hub chain):\n\n
\n forge create Counter \\n   --rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io \\n   --private-key <INSERT_PRIVATE_KEY> \\n   --resolc\n
\n [:] Compiling...\n Compiler run successful!\n
\n\nFor contracts with constructor arguments:\n\n```bash\nforge create MyToken \\\n --rpc-url \\\n --private-key \\\n --constructor-args \"MyToken\" \"MTK\" 1000000 \\\n --resolc\n```\n\n!!! note \"Network Compatibility\"\n Use the `--resolc` flag when deploying to PolkaVM-compatible networks. Omit it for Ethereum-compatible networks."} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 8, "depth": 2, "title": "Supported `foundry-polkadot` Commands", "anchor": "supported-foundry-polkadot-commands", "start_char": 7390, "end_char": 7544, "estimated_token_count": 33, "token_estimator": "heuristic-v1", "text": "## Supported `foundry-polkadot` Commands\n\nThis section provides a detailed breakdown of the `forge` and `cast` commands supported in `foundry-polkadot`."} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 9, "depth": 3, "title": "Forge Commands", "anchor": "forge-commands", "start_char": 7544, "end_char": 13032, "estimated_token_count": 1502, "token_estimator": "heuristic-v1", "text": "### Forge Commands\n\n- **`init`**:\n - **Command**: `forge init `.\n - **Description**: Initializes a new Foundry project in the current directory, setting up the basic project structure and installing standard libraries.\n\n- **`bind`**:\n - **Command**: `forge bind [--resolc]`.\n - **Description**: Generates type-safe Rust bindings for your Solidity contracts. Use `--resolc` to ensure compilation with the `resolc` compiler for PolkaVM compatibility.\n\n- **`bind-json`**:\n - **Command**: `forge bind-json [--resolc]`.\n - **Description**: Generates JSON bindings for your Solidity contracts. Use `--resolc` for `resolc`-based compilation.\n\n- **`build`**:\n - **Command**: `forge build [--resolc]`.\n - **Description**: Compiles all Solidity contracts in your project. Specify `--resolc` to compile for PolkaVM.\n\n- **`cache clean`**:\n - **Command**: `forge cache clean`.\n - **Description**: Clears the Foundry cache directory.\n\n- **`cache ls`**:\n - **Command**: `forge cache ls`.\n - **Description**: Lists the contents of the Foundry cache.\n\n- **`clean`**:\n - **Command**: `forge clean`.\n - **Description**: Removes all build artifacts from the project's `out` directory.\n\n- **`compiler resolve`**:\n - **Command**: `forge compiler resolve [--resolc]`.\n - **Description**: Resolves and displays the versions of Solidity compilers Foundry is using. Use `--resolc` to also check for `resolc`.\n\n- **`config`**:\n - **Command**: `forge config`.\n - **Description**: Displays the current Foundry project configuration, including settings from `foundry.toml`.\n\n- **`create`**:\n - **Command**: `forge create [OPTIONS] `.\n - **Required Parameters**: `` (the name of the contract to deploy).\n - **Description**: Deploys a new contract to a specified blockchain network. The `--resolc` flag ensures it's compiled for PolkaVM. You'll typically need to provide an RPC URL, a private key for the deployer account, and potentially constructor arguments.\n\n- **`doc`**:\n - **Command**: `forge doc`.\n - **Description**: Generates documentation for your Solidity contracts.\n\n- **`flatten`**:\n - **Command**: `forge flatten [OPTIONS] `.\n - **Required Parameters**: `` (the path to the Solidity file).\n - **Description**: Combines all imports of a Solidity file into a single file, useful for deployment or verification.\n\n- **`fmt`**:\n - **Command**: `forge fmt`.\n - **Description**: Formats Solidity code according to a predefined style.\n\n- **`geiger`**:\n - **Command**: `forge geiger `.\n - **Required Parameters**: `` (the path to the Solidity file).\n - **Description**: Analyzes Solidity code for potential security vulnerabilities and gas inefficiencies.\n\n- **`generate test`**:\n - **Command**: `forge generate test --contract-name `.\n - **Required Parameters**: `--contract-name ` (the name of the contract for which to generate a test).\n - **Description**: Creates a new test file with boilerplate code for a specified contract.\n\n- **`generate-fig-spec`**:\n - **Command**: `forge generate-fig-spec`.\n - **Description**: Generates a Fig specification for CLI autocompletion tools.\n\n- **`inspect`**:\n - **Command**: `forge inspect [--resolc]`.\n - **Required Parameters**: `` (the contract to inspect), `` (e.g., `bytecode`, `abi`, `methods`, `events`).\n - **Description**: Displays various artifacts of a compiled contract. Use `--resolc` to inspect `resolc`-compiled artifacts; the bytecode will start with `0x505`.\n\n- **`install`**:\n - **Command**: `forge install `.\n - **Description**: Installs a Solidity library or dependency from a Git repository.\n\n- **`update`**:\n - **Command**: `forge update []`.\n - **Description**: Updates installed dependencies. If a repository is specified, only that one is updated.\n\n- **`remappings`**:\n - **Command**: `forge remappings`.\n - **Description**: Lists the currently configured Solidity compiler remappings.\n\n- **`remove`**:\n - **Command**: `forge remove `.\n - **Description**: Removes an installed Solidity dependency. Use `--force` to remove without confirmation.\n\n- **`selectors upload`**:\n - **Command**: `forge selectors upload [--all]`.\n - **Description**: Uploads function selectors from compiled contracts to OpenChain. Use `--all` to upload for all contracts.\n\n- **`selectors list`**:\n - **Command**: `forge selectors list`.\n - **Description**: Lists all known function selectors for contracts in the project.\n\n- **`selectors find`**:\n - **Command**: `forge selectors find `.\n - **Description**: Searches for a function signature given its 4-byte selector.\n\n- **`selectors cache`**:\n - **Command**: `forge selectors cache`.\n - **Description**: Caches function selectors for faster lookup.\n\n- **`tree`**:\n - **Command**: `forge tree`.\n - **Description**: Displays the dependency tree of your Solidity contracts.\n\n!!!warning \"Non-working Commands\"\n\n Consider that some foundry commands are not yet supported in `foundry-polkadot`:\n\n - **`clone`**: This command is not supported in `foundry-polkadot`.\n - **`coverage`**: Code coverage analysis is not supported.\n - **`snapshot`**: Creating blockchain state snapshots is not supported.\n - **`test`**: Running Solidity tests is not supported."} +{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 10, "depth": 3, "title": "Cast Commands", "anchor": "cast-commands", "start_char": 13032, "end_char": 23398, "estimated_token_count": 3084, "token_estimator": "heuristic-v1", "text": "### Cast Commands\n\n- **`4byte`**:\n - **Command**: `cast 4byte [OPTIONS] [TOPIC_0]`.\n - **Description**: Decodes a 4-byte function selector into its human-readable function signature.\n\n- **`4byte-event`**:\n - **Command**: `cast 4byte-event [OPTIONS] [TOPIC_0]`.\n - **Description**: Decodes a 4-byte event topic into its human-readable event signature.\n\n- **`abi-encode`**:\n - **Command**: `cast abi-encode [ARGS]...`.\n - **Required Parameters**: `` (the function signature), `[ARGS]` (arguments to encode).\n - **Description**: ABI-encodes function arguments according to a given signature.\n\n- **`address-zero`**:\n - **Command**: `cast address-zero`.\n - **Description**: Returns the zero address (0x00...00).\n\n- **`age`**:\n - **Command**: `cast age [OPTIONS] [BLOCK]`.\n - **Description**: Converts a block number or tag (e.g., `latest`) into its timestamp.\n\n- **`balance`**:\n - **Command**: `cast balance [OPTIONS] `.\n - **Required Parameters**: `` (the address to check).\n - **Description**: Retrieves the native token balance of a given address on the specified RPC network.\n\n- **`base-fee`**:\n - **Command**: `cast base-fee [OPTIONS] [BLOCK]`.\n - **Description**: Retrieves the base fee per gas for a specific block (defaults to `latest`).\n\n- **`block`**:\n - **Command**: `cast block [OPTIONS] [BLOCK]`.\n - **Description**: Retrieves comprehensive details about a specific block (defaults to `latest`).\n\n- **`block-number`**:\n - **Command**: `cast block-number [OPTIONS] [BLOCK]`.\n - **Description**: Retrieves the number of the latest or a specified block.\n\n- **`call`**:\n - **Command**: `cast call [OPTIONS] [ARGS]...`.\n - **Description**: Executes a read-only (constant) function call on a contract. No transaction is sent to the network.\n\n- **`chain`**:\n - **Command**: `cast chain [OPTIONS]`.\n - **Description**: Displays the human-readable name of the connected blockchain.\n\n- **`chain-id`**:\n - **Command**: `cast chain-id [OPTIONS]`.\n - **Description**: Displays the chain ID of the connected blockchain.\n\n- **`client`**:\n - **Command**: `cast client [OPTIONS]`.\n - **Description**: Retrieves information about the connected RPC client (node software).\n\n- **`code`**:\n - **Command**: `cast code [OPTIONS] `.\n - **Required Parameters**: `` (the contract address).\n - **Description**: Retrieves the bytecode deployed at a given contract address.\n\n- **`codesize`**:\n - **Command**: `cast codesize [OPTIONS] `.\n - **Required Parameters**: `` (the contract address).\n - **Description**: Retrieves the size of the bytecode deployed at a given contract address.\n\n- **`compute-address`**:\n - **Command**: `cast compute-address [OPTIONS] `.\n - **Required Parameters**: `` (the deployer's address).\n - **Description**: Computes the predicted contract address based on the deployer's address and nonce.\n\n- **`decode-abi`**:\n - **Command**: `cast decode-abi `.\n - **Required Parameters**: `` (the function signature), `` (the ABI-encoded data).\n - **Description**: Decodes ABI-encoded output data from a contract call given its signature.\n\n- **`decode-calldata`**:\n - **Command**: `cast decode-calldata `.\n - **Required Parameters**: `` (the function signature), `` (the raw calldata).\n - **Description**: Decodes raw calldata into human-readable arguments using a function signature.\n\n- **`decode-error`**:\n - **Command**: `cast decode-error [--sig ]`.\n - **Required Parameters**: `` (the error data).\n - **Description**: Decodes a custom error message from a transaction revert. You may need to provide the error signature.\n\n- **`decode-event`**:\n - **Command**: `cast decode-event [--sig ]`.\n - **Required Parameters**: `` (the event data).\n - **Description**: Decodes event data from a transaction log.\n\n- **`estimate`**:\n - **Command**: `cast estimate [OPTIONS] [TO] [SIG] [ARGS]...`.\n - **Required Parameters**: `[TO]` (the recipient address or contract), `[SIG]` (function signature), `[ARGS]` (arguments).\n - **Description**: Estimates the gas cost for a transaction or function call.\n\n- **`find-block`**:\n - **Command**: `cast find-block [OPTIONS] `.\n - **Required Parameters**: `` (a Unix timestamp).\n - **Description**: Finds the closest block number to a given Unix timestamp.\n\n- **`gas-price`**:\n - **Command**: `cast gas-price [OPTIONS]`.\n - **Description**: Retrieves the current average gas price on the network.\n\n- **`generate-fig-spec`**:\n - **Command**: `cast generate-fig-spec`.\n - **Description**: Generates a Fig specification for CLI autocompletion.\n\n- **`index-string`**:\n - **Command**: `cast index-string `.\n - **Description**: Computes the Keccak-256 hash of a string, useful for event topics.\n\n- **`index-erc7201`**:\n - **Command**: `cast index-erc7201 `.\n - **Description**: Computes the hash for an ERC-7201 identifier.\n\n- **`logs`**:\n - **Command**: `cast logs [OPTIONS] [SIG_OR_TOPIC] [TOPICS_OR_ARGS]...`.\n - **Required Parameters**: `[SIG_OR_TOPIC]` (a signature or topic hash).\n - **Description**: Filters and displays event logs from transactions.\n\n- **`max-int`**:\n - **Command**: `cast max-int`.\n - **Description**: Displays the maximum value for a signed 256-bit integer.\n\n- **`max-uint`**:\n - **Command**: `cast max-uint`.\n - **Description**: Displays the maximum value for an unsigned 256-bit integer.\n\n- **`min-int`**:\n - **Command**: `cast min-int`.\n - **Description**: Displays the minimum value for a signed 256-bit integer.\n\n- **`mktx`**:\n - **Command**: `cast mktx [OPTIONS] [TO] [SIG] [ARGS]...`.\n - **Required Parameters**: `[TO]` (the recipient address or contract).\n - **Description**: Creates a raw, signed transaction that can be broadcast later.\n\n- **`decode-transaction`**:\n - **Command**: `cast decode-transaction [OPTIONS] [TX]`.\n - **Required Parameters**: `[TX]` (the raw transaction hex string).\n - **Description**: Decodes a raw transaction hex string into its human-readable components.\n\n- **`namehash increment`**:\n - **Command**: `cast namehash `.\n - **Description**: Computes the ENS (Ethereum Name Service) namehash for a given name.\n\n- **`nonce`**:\n - **Command**: `cast nonce [OPTIONS] `.\n - **Required Parameters**: `` (the address to check).\n - **Description**: Retrieves the transaction count (nonce) for a given address.\n\n- **`parse-bytes32-address`**:\n - **Command**: `cast parse-bytes32-address `.\n - **Description**: Parses a 32-byte hex string (e.g., from `bytes32`) into an Ethereum address.\n\n- **`parse-bytes32-string`**:\n - **Command**: `cast parse-bytes32-string `.\n - **Description**: Parses a 32-byte hex string into a human-readable string.\n\n- **`parse-units`**:\n - **Command**: `cast parse-units [UNIT]`.\n - **Description**: Converts a human-readable amount into its smallest unit (e.g., Ether to Wei). Defaults to `ether`.\n\n- **`pretty-calldata`**:\n - **Command**: `cast pretty-calldata [OPTIONS] `.\n - **Required Parameters**: `` (the calldata hex string).\n - **Description**: Attempts to pretty-print and decode a raw calldata string into possible function calls.\n\n- **`publish`**:\n - **Command**: `cast publish [OPTIONS] `.\n - **Description**: Broadcasts a raw, signed transaction to the network.\n\n- **`receipt`**:\n - **Command**: `cast receipt [OPTIONS] `.\n - **Description**: Retrieves the transaction receipt for a given transaction hash, including status, gas usage, and logs.\n\n- **`rpc`**:\n - **Command**: `cast rpc [OPTIONS] [PARAMS]...`.\n - **Required Parameters**: `` (the RPC method to call), `[PARAMS]` (parameters for the method).\n - **Description**: Makes a direct RPC call to the connected blockchain node.\n\n- **`send`**:\n - **Command**: `cast send [OPTIONS] [ARGS]...`.\n - **Required Parameters**: `` (the recipient address or contract).\n - **Description**: Sends a transaction to a contract or address, executing a function or transferring value.\n\n- **`sig`**:\n - **Command**: `cast sig `.\n - **Required Parameters**: `` (the full function signature string).\n - **Description**: Computes the 4-byte function selector for a given function signature.\n\n- **`sig-event`**:\n - **Command**: `cast sig-event `.\n - **Required Parameters**: `` (the full event signature string).\n - **Description**: Computes the Keccak-256 hash (topic) for a given event signature.\n\n- **`storage`**:\n - **Command**: `cast storage [OPTIONS]
[SLOT]`.\n - **Required Parameters**: `
` (the contract address).\n - **Description**: Retrieves the raw value stored at a specific storage slot of a contract.\n\n- **`tx`**:\n - **Command**: `cast tx [OPTIONS] `.\n - **Description**: Retrieves comprehensive details about a specific transaction.\n\n- **`upload-signature`**:\n - **Command**: `cast upload-signature [OPTIONS] `.\n - **Required Parameters**: `` (the function or event signature).\n - **Description**: Uploads a function or event signature to the OpenChain registry.\n\n- **`wallet`**:\n - **Command**: `cast wallet new`.\n - **Description**: Generates a new random Ethereum keypair (private key and address).\n\n- **`wallet new-mnemonic`**:\n - **Command**: `cast wallet new-mnemonic`.\n - **Description**: Generates a new BIP-39 mnemonic phrase and derives the first account from it.\n\n- **`wallet address`**:\n - **Command**: `cast wallet address [OPTIONS]`.\n - **Description**: Derives and displays the Ethereum address from a private key or mnemonic (if provided).\n\n!!!warning \"Non-working Commands\"\n\n Consider that some foundry commands are not yet supported in `foundry-polkadot`:\n\n - **`proof`**: This command, used for generating Merkle proofs, is not supported.\n - **`storage-root`**: This command, used for retrieving the storage root of a contract, is not supported."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 0, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 11, "end_char": 506, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "## Overview\n\nBuilding on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer.\n\nHardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit including compilation, local testing nodes, debugging tools, and deployment automation."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 1, "depth": 2, "title": "Hardhat Workflow", "anchor": "hardhat-workflow", "start_char": 506, "end_char": 1247, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "## Hardhat Workflow\n\nFrom the first sketch of a contract to ongoing operations, Hardhat encourages a repeatable cycle: define the functionality you need, scaffold the workspace, write and refine Solidity code, compile it into deployable artifacts, validate behavior with automated tests, deploy confidently to the target network, and keep iterating with scripts that monitor and interact with what you shipped.\n\n```mermaid\nflowchart LR\n plan[Plan Contract]\n scaffold[Scaffold Project]\n develop[Write & Update Contracts]\n compile[Compile Sources]\n test[Run Automated Tests]\n deploy[Deploy to Target Network]\n operate[Interact & Monitor]\n\n plan --> scaffold --> develop --> compile --> test --> deploy --> operate\n```"} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 2, "depth": 2, "title": "Project Anatomy", "anchor": "project-anatomy", "start_char": 1247, "end_char": 1913, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Project Anatomy\n\nA freshly initialized Hardhat project keeps code, configuration, and automation neatly separated:\n\n```\n.\n├── contracts/\n│ └── MyContract.sol\n├── ignition/\n│ └── modules/\n├── scripts/\n│ └── interact.js\n├── test/\n│ └── MyContract.test.js\n└── hardhat.config.js\n```\n\n- `contracts/`: Solidity sources that define your smart contracts.\n- `test/`: Automated tests written in JavaScript or TypeScript.\n- `ignition/`: Deployment modules that orchestrate repeatable rollouts.\n- `scripts/`: Utility scripts for deploying, validating, or interacting with contracts.\n- `hardhat.config.js`: Central configuration for networks, compilers, and tooling."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 3, "depth": 2, "title": "Core Functionalities", "anchor": "core-functionalities", "start_char": 1913, "end_char": 1938, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Core Functionalities"} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 4, "depth": 3, "title": "Project Setup", "anchor": "project-setup", "start_char": 1938, "end_char": 2313, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "### Project Setup\n\nHardhat provides a structured project initialization with organized folders for contracts, tests, deployment scripts, and automation. Scaffold a workspace quickly and keep configuration in a single `hardhat.config.js` file.\n\n- Learn more in the [Install and Configure](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank} guide."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 5, "depth": 3, "title": "Contract Compilation", "anchor": "contract-compilation", "start_char": 2313, "end_char": 2708, "estimated_token_count": 79, "token_estimator": "heuristic-v1", "text": "### Contract Compilation\n\nCompile your Solidity smart contracts with configurable compiler versions and optimization settings. Hardhat captures build artifacts—ABI, bytecode, metadata—so you can deploy or interact with contracts from scripts and frontends.\n\n- Deep dive into compilation in [Compile Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 6, "depth": 3, "title": "Testing Environment", "anchor": "testing-environment", "start_char": 2708, "end_char": 3096, "estimated_token_count": 80, "token_estimator": "heuristic-v1", "text": "### Testing Environment\n\nRun automated tests against a local Hardhat node, simulate transactions, and debug contract behavior before deploying to public networks. The built-in testing stack uses familiar JavaScript tooling such as Mocha and Chai.\n\n- Master testing capabilities in [Test Your Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 7, "depth": 3, "title": "Deployment", "anchor": "deployment", "start_char": 3096, "end_char": 3424, "estimated_token_count": 66, "token_estimator": "heuristic-v1", "text": "### Deployment\n\nShip your contracts with reusable deployment scripts or Hardhat Ignition modules. Manage credentials securely, target multiple networks, and repeat deployments with confidence.\n\n- Follow deployment steps in [Deploy Smart Contracts](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank}."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 8, "depth": 3, "title": "Contract Interaction", "anchor": "contract-interaction", "start_char": 3424, "end_char": 3738, "estimated_token_count": 67, "token_estimator": "heuristic-v1", "text": "### Contract Interaction\n\nCreate scripts to interact with deployed contracts, read state, execute transactions, and automate maintenance tasks using your generated ABI.\n\n- See practical tips in [Interact with Smart Contracts](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\\_blank}."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 9, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 3738, "end_char": 5817, "estimated_token_count": 518, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nReady to explore the specifics? Dive into these guides to continue your Hardhat journey:\n\n
\n\n- Guide __Install and Configure Hardhat__\n\n ---\n\n Initialize your workspace and adjust project settings for this toolchain.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank}\n\n- Guide __Compile Smart Contracts__\n\n ---\n\n Configure compiler options and generate deployable artifacts.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}\n\n- Guide __Test Your Smart Contracts__\n\n ---\n\n Build automated tests and run them against a local node.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}\n\n- Guide __Deploy Smart Contracts__\n\n ---\n\n Roll out contracts to local, test, or production networks with repeatable scripts.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank}\n\n- Guide __Interact with Smart Contracts__\n\n ---\n\n Script on-chain interactions and automate maintenance tasks.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\\_blank}\n\n- External __Hardhat Documentation__\n\n ---\n\n Explore Hardhat's official documentation for advanced features and best practices.\n\n [:octicons-arrow-right-24: Learn More](https://hardhat.org/docs){target=\\_blank}\n\n- External __OpenZeppelin Contracts__\n\n ---\n\n Use prebuilt, audited contract templates to bootstrap your projects.\n\n [:octicons-arrow-right-24: Explore](https://www.openzeppelin.com/solidity-contracts){target=\\_blank}\n\n
"} {"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 196, "end_char": 699, "estimated_token_count": 97, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nA local development node provides an isolated blockchain environment where you can deploy, test, and debug smart contracts without incurring network fees or waiting for block confirmations. This guide demonstrates how to set up a local Polkadot SDK-based node with smart contract capabilities.\n\nBy the end of this guide, you'll have:\n\n- A running node with smart contract support.\n- An ETH-RPC adapter for Ethereum-compatible tooling integration accessible at `http://localhost:8545`."} {"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 699, "end_char": 1028, "estimated_token_count": 76, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore getting started, ensure you have done the following:\n\n- Completed the [Install Polkadot SDK Dependencies](/parachains/install-polkadot-sdk/){target=\\_blank} guide and successfully installed [Rust](https://rust-lang.org/){target=\\_blank} and the required packages to set up your development environment."} {"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 2, "depth": 2, "title": "Install the Revive Dev Node and ETH-RPC Adapter", "anchor": "install-the-revive-dev-node-and-eth-rpc-adapter", "start_char": 1028, "end_char": 2561, "estimated_token_count": 343, "token_estimator": "heuristic-v1", "text": "## Install the Revive Dev Node and ETH-RPC Adapter\n\nThe Polkadot SDK repository contains both the [Revive Dev node](https://github.com/paritytech/polkadot-sdk/tree/8e2b6f742a38bb13688e12abacded0aab2dbbb23/substrate/frame/revive/dev-node){target=\\_blank} implementation and the [ETH-RPC adapter](https://github.com/paritytech/polkadot-sdk/tree/8e2b6f742a38bb13688e12abacded0aab2dbbb23/substrate/frame/revive/rpc){target=\\_blank} required for Ethereum compatibility. Start by cloning the repository and navigating to the project directory:\n\n```bash\ngit clone https://github.com/paritytech/polkadot-sdk.git\ncd polkadot-sdk\ngit checkout 8e2b6f742a38bb13688e12abacded0aab2dbbb23\n```\n\nNext, you need to compile the two essential components for your development environment. The Substrate node provides the core blockchain runtime with smart contract support, while the ETH-RPC adapter enables Ethereum JSON-RPC compatibility for existing tooling:\n\n```bash\ncargo build -p revive-dev-node --bin revive-dev-node --release\ncargo build -p pallet-revive-eth-rpc --bin eth-rpc --release\n```\n\nThe compilation process may take some time depending on your system specifications, potentially up to 30 minutes. Release builds are optimized for performance but take longer to compile than debug builds. After successful compilation, you can verify the binaries are available in the `target/release` directory:\n\n- **Revive Dev node path**: `polkadot-sdk/target/release/revive-dev-node`\n- **ETH-RPC adapter path**: `polkadot-sdk/target/release/eth-rpc`"} @@ -1058,41 +1061,41 @@ {"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 4, "depth": 2, "title": "Dynamic Gas Pricing", "anchor": "dynamic-gas-pricing", "start_char": 2547, "end_char": 3440, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Dynamic Gas Pricing\n\nPallet revive uses dynamic pricing through a \"fee multiplier\" that adjusts based on network congestion:\n\n- When blocks are full, the multiplier increases, making transactions more expensive.\n- When blocks are empty, the multiplier decreases, making transactions cheaper.\n- The multiplier updates after every block based on utilization.\n\nThis creates a market-based pricing mechanism similar to Ethereum's base fee, helping to manage network resources efficiently.\n\nThe gas price returned during estimation is simply the current fee multiplier value.\n\n!!! warning \"Important for Users\"\n Because the fee multiplier can change between when you estimate gas and when your transaction executes, you can add a safety buffer (10-20%) to both your gas limit and gas price. This ensures your transaction will execute successfully even if network conditions change slightly."} {"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 5, "depth": 2, "title": "Transaction Execution Flow", "anchor": "transaction-execution-flow", "start_char": 3440, "end_char": 4936, "estimated_token_count": 353, "token_estimator": "heuristic-v1", "text": "## Transaction Execution Flow\n\nThe following diagram illustrates the complete lifecycle of a transaction from submission to settlement:\n\n```mermaid\ngraph TD\n U[User/Wallet] --> M[Transaction pool]\n M --> P[Pre-dispatch convert gas to weight and create hold]\n P --> C{Sufficient funds}\n C -->|No| R[Rejected]\n C -->|Yes| X[Execute contract within limits]\n X --> S[Settle fee from actual weight and length; refund]\n S --> B[Included in block]\n```\n\nThe transaction execution flow is as follows:\n\n- **Pool and pre-dispatch**: The transaction enters the pool, `gas` is mapped to `weight`, and a temporary hold is created for the maximum fee exposure. Weight is a two-dimensional tuple (`ref_time`, `proof_size`). Each dimension is tracked independently. The [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\\_blank} conversion takes the maximum of the two dimensions (after applying their respective coefficients) to determine the fee.\n- **Funds check**: If the hold is insufficient, the transaction is rejected before any execution.\n- **Execution**: If sufficient, the contract runs within the derived weight limits; a `storage_deposit` may be reserved when new storage is created.\n- **Settlement**: Fees are charged from the actual `weight` used plus the length fee; any unused hold is refunded.\n- **Inclusion**: After settlement, the transaction is included in the block."} {"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 6, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 4936, "end_char": 5234, "estimated_token_count": 51, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nThe Polkadot Hub's gas model is designed to be Ethereum-compatible while providing the flexibility and efficiency of Polkadot's resource metering system. Developers can build on Ethereum tooling while leveraging Polkadot's advanced features like multi-dimensional resource tracking."} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 187, "end_char": 679, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\\_blank} and provides examples of how to use them.\n\nThis guide uses the Polkadot Hub TestNet endpoint:\n\n```text\nhttps://testnet-passet-hub-eth-rpc.polkadot.io\n```"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 1, "depth": 2, "title": "Available Methods", "anchor": "available-methods", "start_char": 679, "end_char": 701, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Available Methods"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 2, "depth": 3, "title": "eth_accounts", "anchor": "eth_accounts", "start_char": 701, "end_char": 1132, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "### eth_accounts\n\nReturns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_accounts\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_accounts\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 3, "depth": 3, "title": "eth_blockNumber", "anchor": "eth_blocknumber", "start_char": 1132, "end_char": 1571, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "### eth_blockNumber\n\nReturns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_blockNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_blockNumber\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 4, "depth": 3, "title": "eth_call", "anchor": "eth_call", "start_char": 1571, "end_char": 3795, "estimated_token_count": 707, "token_estimator": "heuristic-v1", "text": "### eth_call\n\nExecutes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_call\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_call\",\n \"params\":[{\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_CALL\"\n }, \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 5, "depth": 3, "title": "eth_chainId", "anchor": "eth_chainid", "start_char": 3795, "end_char": 4225, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "### eth_chainId\n\nReturns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_chainId\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_chainId\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 6, "depth": 3, "title": "eth_estimateGas", "anchor": "eth_estimategas", "start_char": 4225, "end_char": 6411, "estimated_token_count": 694, "token_estimator": "heuristic-v1", "text": "### eth_estimateGas\n\nEstimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_estimateGas\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_estimateGas\",\n \"params\":[{\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_FUNCTION_CALL\"\n }],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 7, "depth": 3, "title": "eth_gasPrice", "anchor": "eth_gasprice", "start_char": 6411, "end_char": 6831, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "### eth_gasPrice\n\nReturns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_gasPrice\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_gasPrice\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 8, "depth": 3, "title": "eth_getBalance", "anchor": "eth_getbalance", "start_char": 6831, "end_char": 7873, "estimated_token_count": 330, "token_estimator": "heuristic-v1", "text": "### eth_getBalance\n\nReturns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_getBalance\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBalance\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 9, "depth": 3, "title": "eth_getBlockByHash", "anchor": "eth_getblockbyhash", "start_char": 7873, "end_char": 8768, "estimated_token_count": 266, "token_estimator": "heuristic-v1", "text": "### eth_getBlockByHash\n\nReturns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`fullTransactions` ++\"boolean\"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes.\n\n**Example**:\n\n```bash title=\"eth_getBlockByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockByHash\",\n \"params\":[\"INSERT_BLOCK_HASH\", INSERT_BOOLEAN],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 10, "depth": 3, "title": "eth_getBlockByNumber", "anchor": "eth_getblockbynumber", "start_char": 8768, "end_char": 9787, "estimated_token_count": 301, "token_estimator": "heuristic-v1", "text": "### eth_getBlockByNumber\n\nReturns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`fullTransactions` ++\"boolean\"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes.\n\n**Example**:\n\n```bash title=\"eth_getBlockByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\", INSERT_BOOLEAN],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 11, "depth": 3, "title": "eth_getBlockTransactionCountByNumber", "anchor": "eth_getblocktransactioncountbynumber", "start_char": 9787, "end_char": 10710, "estimated_token_count": 260, "token_estimator": "heuristic-v1", "text": "### eth_getBlockTransactionCountByNumber\n\nReturns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_getBlockTransactionCountByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockTransactionCountByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 12, "depth": 3, "title": "eth_getBlockTransactionCountByHash", "anchor": "eth_getblocktransactioncountbyhash", "start_char": 10710, "end_char": 11520, "estimated_token_count": 228, "token_estimator": "heuristic-v1", "text": "### eth_getBlockTransactionCountByHash\n\nReturns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getBlockTransactionCountByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockTransactionCountByHash\",\n \"params\":[\"INSERT_BLOCK_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 13, "depth": 3, "title": "eth_getCode", "anchor": "eth_getcode", "start_char": 11520, "end_char": 12548, "estimated_token_count": 327, "token_estimator": "heuristic-v1", "text": "### eth_getCode\n\nReturns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getCode\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getCode\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 14, "depth": 3, "title": "eth_getLogs", "anchor": "eth_getlogs", "start_char": 12548, "end_char": 14499, "estimated_token_count": 630, "token_estimator": "heuristic-v1", "text": "### eth_getLogs\n\nReturns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\\_blank}.\n\n**Parameters**:\n\n- **`filter` ++\"object\"++**: The filter object.\n - **`fromBlock` ++\"string\"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n - **`toBlock` ++\"string\"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n - **`address` ++\"string\" or \"array of strings\"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`topics` ++\"array of strings\"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string or an array of such strings (meaning OR).\n - **`blockhash` ++\"string\"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getLogs\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getLogs\",\n \"params\":[{\n \"fromBlock\": \"latest\",\n \"toBlock\": \"latest\"\n }],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 15, "depth": 3, "title": "eth_getStorageAt", "anchor": "eth_getstorageat", "start_char": 14499, "end_char": 15811, "estimated_token_count": 402, "token_estimator": "heuristic-v1", "text": "### eth_getStorageAt\n\nReturns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`storageKey` ++\"string\"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getStorageAt\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getStorageAt\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_STORAGE_KEY\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 16, "depth": 3, "title": "eth_getTransactionCount", "anchor": "eth_gettransactioncount", "start_char": 15811, "end_char": 16898, "estimated_token_count": 329, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionCount\n\nReturns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getTransactionCount\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionCount\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 17, "depth": 3, "title": "eth_getTransactionByHash", "anchor": "eth_gettransactionbyhash", "start_char": 16898, "end_char": 17668, "estimated_token_count": 222, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByHash\n\nReturns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByHash\",\n \"params\":[\"INSERT_TRANSACTION_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 18, "depth": 3, "title": "eth_getTransactionByBlockNumberAndIndex", "anchor": "eth_gettransactionbyblocknumberandindex", "start_char": 17668, "end_char": 18874, "estimated_token_count": 330, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByBlockNumberAndIndex\n\nReturns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`transactionIndex` ++\"string\"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByBlockNumberAndIndex\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByBlockNumberAndIndex\",\n \"params\":[\"INSERT_BLOCK_VALUE\", \"INSERT_TRANSACTION_INDEX\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 19, "depth": 3, "title": "eth_getTransactionByBlockHashAndIndex", "anchor": "eth_gettransactionbyblockhashandindex", "start_char": 18874, "end_char": 19955, "estimated_token_count": 296, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByBlockHashAndIndex\n\nReturns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`transactionIndex` ++\"string\"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByBlockHashAndIndex\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByBlockHashAndIndex\",\n \"params\":[\"INSERT_BLOCK_HASH\", \"INSERT_TRANSACTION_INDEX\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 20, "depth": 3, "title": "eth_getTransactionReceipt", "anchor": "eth_gettransactionreceipt", "start_char": 19955, "end_char": 20734, "estimated_token_count": 223, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionReceipt\n\nReturns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\\_blank}.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionReceipt\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionReceipt\",\n \"params\":[\"INSERT_TRANSACTION_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 21, "depth": 3, "title": "eth_maxPriorityFeePerGas", "anchor": "eth_maxpriorityfeepergas", "start_char": 20734, "end_char": 21149, "estimated_token_count": 125, "token_estimator": "heuristic-v1", "text": "### eth_maxPriorityFeePerGas\n\nReturns an estimate of the current priority fee per gas, in Wei, to be included in a block.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_maxPriorityFeePerGas\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_maxPriorityFeePerGas\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 22, "depth": 3, "title": "eth_sendRawTransaction", "anchor": "eth_sendrawtransaction", "start_char": 21149, "end_char": 21852, "estimated_token_count": 214, "token_estimator": "heuristic-v1", "text": "### eth_sendRawTransaction\n\nSubmits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\\_blank}.\n\n**Parameters**:\n\n- **`callData` ++\"string\"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_sendRawTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_sendRawTransaction\",\n \"params\":[\"INSERT_CALL_DATA\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_CALL_DATA` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 23, "depth": 3, "title": "eth_sendTransaction", "anchor": "eth_sendtransaction", "start_char": 21852, "end_char": 24207, "estimated_token_count": 714, "token_estimator": "heuristic-v1", "text": "### eth_sendTransaction\n\nCreates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction object.\n - **`from` ++\"string\"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`to` ++\"string\"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`nonce` ++\"string\"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_sendTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_sendTransaction\",\n \"params\":[{\n \"from\": \"INSERT_SENDER_ADDRESS\",\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"gas\": \"INSERT_GAS_LIMIT\",\n \"gasPrice\": \"INSERT_GAS_PRICE\",\n \"value\": \"INSERT_VALUE\",\n \"input\": \"INSERT_INPUT_DATA\",\n \"nonce\": \"INSERT_NONCE\"\n }],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 24, "depth": 3, "title": "eth_syncing", "anchor": "eth_syncing", "start_char": 24207, "end_char": 24648, "estimated_token_count": 150, "token_estimator": "heuristic-v1", "text": "### eth_syncing\n\nReturns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_syncing\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_syncing\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 25, "depth": 3, "title": "net_listening", "anchor": "net_listening", "start_char": 24648, "end_char": 25130, "estimated_token_count": 155, "token_estimator": "heuristic-v1", "text": "### net_listening\n\nReturns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_listening\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_listening\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 26, "depth": 3, "title": "net_peerCount", "anchor": "net_peercount", "start_char": 25130, "end_char": 25483, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "### net_peerCount\n\nReturns the number of peers currently connected to the client.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_peerCount\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_peerCount\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 27, "depth": 3, "title": "net_version", "anchor": "net_version", "start_char": 25483, "end_char": 25905, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "### net_version\n\nReturns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_version\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_version\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 28, "depth": 3, "title": "system_health", "anchor": "system_health", "start_char": 25905, "end_char": 26247, "estimated_token_count": 113, "token_estimator": "heuristic-v1", "text": "### system_health\n\nReturns information about the health of the system.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"system_health\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"system_health\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 29, "depth": 3, "title": "web3_clientVersion", "anchor": "web3_clientversion", "start_char": 26247, "end_char": 26689, "estimated_token_count": 142, "token_estimator": "heuristic-v1", "text": "### web3_clientVersion\n\nReturns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"web3_clientVersion\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"web3_clientVersion\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 30, "depth": 3, "title": "debug_traceBlockByNumber", "anchor": "debug_traceblockbynumber", "start_char": 26689, "end_char": 27765, "estimated_token_count": 324, "token_estimator": "heuristic-v1", "text": "### debug_traceBlockByNumber \n\nTraces a block's execution by its number and returns a detailed execution trace for each transaction.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options.\n - **`tracer` ++\"string\"++**: The name of the tracer to use (e.g., `\"callTracer\"`, `\"opTracer\"`).\n - Other tracer-specific options may be supported.\n\n**Example**:\n\n```bash title=\"debug_traceBlockByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceBlockByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 31, "depth": 3, "title": "debug_traceTransaction", "anchor": "debug_tracetransaction", "start_char": 27765, "end_char": 28609, "estimated_token_count": 249, "token_estimator": "heuristic-v1", "text": "### debug_traceTransaction\n\nTraces the execution of a single transaction by its hash and returns a detailed execution trace.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options (e.g., `tracer: \"callTracer\"`).\n\n**Example**:\n\n```bash title=\"debug_traceTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceTransaction\",\n \"params\":[\"INSERT_TRANSACTION_HASH\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper value.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 32, "depth": 3, "title": "debug_traceCall", "anchor": "debug_tracecall", "start_char": 28609, "end_char": 31042, "estimated_token_count": 751, "token_estimator": "heuristic-v1", "text": "### debug_traceCall\n\nExecutes a new message call and returns a detailed execution trace without creating a transaction on the blockchain.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object, similar to `eth_call` parameters.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options (e.g., `tracer: \"callTracer\"`).\n\n**Example**:\n\n```bash title=\"debug_traceCall\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceCall\",\n \"params\":[{\n \"from\": \"INSERT_SENDER_ADDRESS\",\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_CALL\"\n }, \"INSERT_BLOCK_VALUE\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 33, "depth": 2, "title": "Response Format", "anchor": "response-format", "start_char": 31042, "end_char": 31225, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "## Response Format\n\nAll responses follow the standard JSON-RPC 2.0 format:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"result\": ... // The return value varies by method\n}\n```"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 34, "depth": 2, "title": "Error Handling", "anchor": "error-handling", "start_char": 31225, "end_char": 31444, "estimated_token_count": 64, "token_estimator": "heuristic-v1", "text": "## Error Handling\n\nIf an error occurs, the response will include an error object:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"error\": {\n \"code\": -32000,\n \"message\": \"Error message here\"\n }\n}\n```"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 187, "end_char": 682, "estimated_token_count": 117, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/en/developers/docs/apis/json-rpc/#json-rpc-methods){target=\\_blank} and provides examples of how to use them.\n\nThis guide uses the Polkadot Hub TestNet endpoint:\n\n```text\nhttps://testnet-passet-hub-eth-rpc.polkadot.io\n```"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 1, "depth": 2, "title": "Available Methods", "anchor": "available-methods", "start_char": 682, "end_char": 704, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Available Methods"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 2, "depth": 3, "title": "eth_accounts", "anchor": "eth_accounts", "start_char": 704, "end_char": 1138, "estimated_token_count": 148, "token_estimator": "heuristic-v1", "text": "### eth_accounts\n\nReturns a list of addresses owned by the client. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_accounts){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_accounts\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_accounts\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 3, "depth": 3, "title": "eth_blockNumber", "anchor": "eth_blocknumber", "start_char": 1138, "end_char": 1580, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "### eth_blockNumber\n\nReturns the number of the most recent block. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_blocknumber){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_blockNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_blockNumber\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 4, "depth": 3, "title": "eth_call", "anchor": "eth_call", "start_char": 1580, "end_char": 3831, "estimated_token_count": 725, "token_estimator": "heuristic-v1", "text": "### eth_call\n\nExecutes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_call){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_call\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_call\",\n \"params\":[{\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_CALL\"\n }, \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 5, "depth": 3, "title": "eth_chainId", "anchor": "eth_chainid", "start_char": 3831, "end_char": 4264, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "### eth_chainId\n\nReturns the chain ID used for signing transactions. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_chainid){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_chainId\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_chainId\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 6, "depth": 3, "title": "eth_estimateGas", "anchor": "eth_estimategas", "start_char": 4264, "end_char": 6477, "estimated_token_count": 712, "token_estimator": "heuristic-v1", "text": "### eth_estimateGas\n\nEstimates gas required for a transaction. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_estimateGas\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_estimateGas\",\n \"params\":[{\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_FUNCTION_CALL\"\n }],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 7, "depth": 3, "title": "eth_gasPrice", "anchor": "eth_gasprice", "start_char": 6477, "end_char": 6900, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "### eth_gasPrice\n\nReturns the current gas price in Wei. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gasprice){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_gasPrice\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_gasPrice\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 8, "depth": 3, "title": "eth_getBalance", "anchor": "eth_getbalance", "start_char": 6900, "end_char": 7954, "estimated_token_count": 338, "token_estimator": "heuristic-v1", "text": "### eth_getBalance\n\nReturns the balance of a given address. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getbalance){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_getBalance\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBalance\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 9, "depth": 3, "title": "eth_getBlockByHash", "anchor": "eth_getblockbyhash", "start_char": 7954, "end_char": 8855, "estimated_token_count": 270, "token_estimator": "heuristic-v1", "text": "### eth_getBlockByHash\n\nReturns information about a block by its hash. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`fullTransactions` ++\"boolean\"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes.\n\n**Example**:\n\n```bash title=\"eth_getBlockByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockByHash\",\n \"params\":[\"INSERT_BLOCK_HASH\", INSERT_BOOLEAN],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 10, "depth": 3, "title": "eth_getBlockByNumber", "anchor": "eth_getblockbynumber", "start_char": 8855, "end_char": 9883, "estimated_token_count": 307, "token_estimator": "heuristic-v1", "text": "### eth_getBlockByNumber\n\nReturns information about a block by its number. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`fullTransactions` ++\"boolean\"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes.\n\n**Example**:\n\n```bash title=\"eth_getBlockByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\", INSERT_BOOLEAN],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 11, "depth": 3, "title": "eth_getBlockTransactionCountByNumber", "anchor": "eth_getblocktransactioncountbynumber", "start_char": 9883, "end_char": 10815, "estimated_token_count": 266, "token_estimator": "heuristic-v1", "text": "### eth_getBlockTransactionCountByNumber\n\nReturns the number of transactions in a block from a block number. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_getBlockTransactionCountByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockTransactionCountByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 12, "depth": 3, "title": "eth_getBlockTransactionCountByHash", "anchor": "eth_getblocktransactioncountbyhash", "start_char": 10815, "end_char": 11631, "estimated_token_count": 232, "token_estimator": "heuristic-v1", "text": "### eth_getBlockTransactionCountByHash\n\nReturns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getBlockTransactionCountByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockTransactionCountByHash\",\n \"params\":[\"INSERT_BLOCK_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 13, "depth": 3, "title": "eth_getCode", "anchor": "eth_getcode", "start_char": 11631, "end_char": 12671, "estimated_token_count": 335, "token_estimator": "heuristic-v1", "text": "### eth_getCode\n\nReturns the code at a given address. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getcode){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getCode\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getCode\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 14, "depth": 3, "title": "eth_getLogs", "anchor": "eth_getlogs", "start_char": 12671, "end_char": 14646, "estimated_token_count": 646, "token_estimator": "heuristic-v1", "text": "### eth_getLogs\n\nReturns an array of all logs matching a given filter object. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getlogs){target=\\_blank}.\n\n**Parameters**:\n\n- **`filter` ++\"object\"++**: The filter object.\n - **`fromBlock` ++\"string\"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n - **`toBlock` ++\"string\"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n - **`address` ++\"string\" or \"array of strings\"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`topics` ++\"array of strings\"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string or an array of such strings (meaning OR).\n - **`blockhash` ++\"string\"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getLogs\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getLogs\",\n \"params\":[{\n \"fromBlock\": \"latest\",\n \"toBlock\": \"latest\"\n }],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 15, "depth": 3, "title": "eth_getStorageAt", "anchor": "eth_getstorageat", "start_char": 14646, "end_char": 15973, "estimated_token_count": 412, "token_estimator": "heuristic-v1", "text": "### eth_getStorageAt\n\nReturns the value from a storage position at a given address. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`storageKey` ++\"string\"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getStorageAt\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getStorageAt\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_STORAGE_KEY\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 16, "depth": 3, "title": "eth_getTransactionCount", "anchor": "eth_gettransactioncount", "start_char": 15973, "end_char": 17072, "estimated_token_count": 337, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionCount\n\nReturns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getTransactionCount\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionCount\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 17, "depth": 3, "title": "eth_getTransactionByHash", "anchor": "eth_gettransactionbyhash", "start_char": 17072, "end_char": 17848, "estimated_token_count": 226, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByHash\n\nReturns information about a transaction by its hash. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByHash\",\n \"params\":[\"INSERT_TRANSACTION_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 18, "depth": 3, "title": "eth_getTransactionByBlockNumberAndIndex", "anchor": "eth_gettransactionbyblocknumberandindex", "start_char": 17848, "end_char": 19066, "estimated_token_count": 338, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByBlockNumberAndIndex\n\nReturns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`transactionIndex` ++\"string\"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByBlockNumberAndIndex\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByBlockNumberAndIndex\",\n \"params\":[\"INSERT_BLOCK_VALUE\", \"INSERT_TRANSACTION_INDEX\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 19, "depth": 3, "title": "eth_getTransactionByBlockHashAndIndex", "anchor": "eth_gettransactionbyblockhashandindex", "start_char": 19066, "end_char": 20156, "estimated_token_count": 302, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByBlockHashAndIndex\n\nReturns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`transactionIndex` ++\"string\"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByBlockHashAndIndex\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByBlockHashAndIndex\",\n \"params\":[\"INSERT_BLOCK_HASH\", \"INSERT_TRANSACTION_INDEX\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 20, "depth": 3, "title": "eth_getTransactionReceipt", "anchor": "eth_gettransactionreceipt", "start_char": 20156, "end_char": 20941, "estimated_token_count": 227, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionReceipt\n\nReturns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\\_blank}.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionReceipt\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionReceipt\",\n \"params\":[\"INSERT_TRANSACTION_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 21, "depth": 3, "title": "eth_maxPriorityFeePerGas", "anchor": "eth_maxpriorityfeepergas", "start_char": 20941, "end_char": 21356, "estimated_token_count": 125, "token_estimator": "heuristic-v1", "text": "### eth_maxPriorityFeePerGas\n\nReturns an estimate of the current priority fee per gas, in Wei, to be included in a block.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_maxPriorityFeePerGas\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_maxPriorityFeePerGas\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 22, "depth": 3, "title": "eth_sendRawTransaction", "anchor": "eth_sendrawtransaction", "start_char": 21356, "end_char": 22065, "estimated_token_count": 218, "token_estimator": "heuristic-v1", "text": "### eth_sendRawTransaction\n\nSubmits a raw transaction. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\\_blank}.\n\n**Parameters**:\n\n- **`callData` ++\"string\"++**: Signed transaction data. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_sendRawTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_sendRawTransaction\",\n \"params\":[\"INSERT_CALL_DATA\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_CALL_DATA` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 23, "depth": 3, "title": "eth_sendTransaction", "anchor": "eth_sendtransaction", "start_char": 22065, "end_char": 24444, "estimated_token_count": 730, "token_estimator": "heuristic-v1", "text": "### eth_sendTransaction\n\nCreates and sends a new transaction. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction object.\n - **`from` ++\"string\"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`to` ++\"string\"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`nonce` ++\"string\"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_sendTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_sendTransaction\",\n \"params\":[{\n \"from\": \"INSERT_SENDER_ADDRESS\",\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"gas\": \"INSERT_GAS_LIMIT\",\n \"gasPrice\": \"INSERT_GAS_PRICE\",\n \"value\": \"INSERT_VALUE\",\n \"input\": \"INSERT_INPUT_DATA\",\n \"nonce\": \"INSERT_NONCE\"\n }],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 24, "depth": 3, "title": "eth_syncing", "anchor": "eth_syncing", "start_char": 24444, "end_char": 24888, "estimated_token_count": 152, "token_estimator": "heuristic-v1", "text": "### eth_syncing\n\nReturns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_syncing){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_syncing\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_syncing\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 25, "depth": 3, "title": "net_listening", "anchor": "net_listening", "start_char": 24888, "end_char": 25373, "estimated_token_count": 157, "token_estimator": "heuristic-v1", "text": "### net_listening\n\nReturns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#net_listening){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_listening\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_listening\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 26, "depth": 3, "title": "net_peerCount", "anchor": "net_peercount", "start_char": 25373, "end_char": 25726, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "### net_peerCount\n\nReturns the number of peers currently connected to the client.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_peerCount\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_peerCount\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 27, "depth": 3, "title": "net_version", "anchor": "net_version", "start_char": 25726, "end_char": 26151, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "### net_version\n\nReturns the current network ID as a string. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#net_version){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_version\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_version\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 28, "depth": 3, "title": "system_health", "anchor": "system_health", "start_char": 26151, "end_char": 26493, "estimated_token_count": 113, "token_estimator": "heuristic-v1", "text": "### system_health\n\nReturns information about the health of the system.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"system_health\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"system_health\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 29, "depth": 3, "title": "web3_clientVersion", "anchor": "web3_clientversion", "start_char": 26493, "end_char": 26938, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "### web3_clientVersion\n\nReturns the current client version. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#web3_clientversion){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"web3_clientVersion\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"web3_clientVersion\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 30, "depth": 3, "title": "debug_traceBlockByNumber", "anchor": "debug_traceblockbynumber", "start_char": 26938, "end_char": 28020, "estimated_token_count": 328, "token_estimator": "heuristic-v1", "text": "### debug_traceBlockByNumber \n\nTraces a block's execution by its number and returns a detailed execution trace for each transaction.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options.\n - **`tracer` ++\"string\"++**: The name of the tracer to use (e.g., `\"callTracer\"`, `\"opTracer\"`).\n - Other tracer-specific options may be supported.\n\n**Example**:\n\n```bash title=\"debug_traceBlockByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceBlockByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 31, "depth": 3, "title": "debug_traceTransaction", "anchor": "debug_tracetransaction", "start_char": 28020, "end_char": 28867, "estimated_token_count": 251, "token_estimator": "heuristic-v1", "text": "### debug_traceTransaction\n\nTraces the execution of a single transaction by its hash and returns a detailed execution trace.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options (e.g., `tracer: \"callTracer\"`).\n\n**Example**:\n\n```bash title=\"debug_traceTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceTransaction\",\n \"params\":[\"INSERT_TRANSACTION_HASH\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper value.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 32, "depth": 3, "title": "debug_traceCall", "anchor": "debug_tracecall", "start_char": 28867, "end_char": 31324, "estimated_token_count": 767, "token_estimator": "heuristic-v1", "text": "### debug_traceCall\n\nExecutes a new message call and returns a detailed execution trace without creating a transaction on the blockchain.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object, similar to `eth_call` parameters.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options (e.g., `tracer: \"callTracer\"`).\n\n**Example**:\n\n```bash title=\"debug_traceCall\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceCall\",\n \"params\":[{\n \"from\": \"INSERT_SENDER_ADDRESS\",\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_CALL\"\n }, \"INSERT_BLOCK_VALUE\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 33, "depth": 2, "title": "Response Format", "anchor": "response-format", "start_char": 31324, "end_char": 31507, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "## Response Format\n\nAll responses follow the standard JSON-RPC 2.0 format:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"result\": ... // The return value varies by method\n}\n```"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 34, "depth": 2, "title": "Error Handling", "anchor": "error-handling", "start_char": 31507, "end_char": 31726, "estimated_token_count": 64, "token_estimator": "heuristic-v1", "text": "## Error Handling\n\nIf an error occurs, the response will include an error object:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"error\": {\n \"code\": -32000,\n \"message\": \"Error message here\"\n }\n}\n```"} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 37, "end_char": 303, "estimated_token_count": 40, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThis guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns."} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 1, "depth": 2, "title": "Migration Considerations", "anchor": "migration-considerations", "start_char": 303, "end_char": 645, "estimated_token_count": 62, "token_estimator": "heuristic-v1", "text": "## Migration Considerations\n\nTake into account the following considerations before migrating your contracts:\n\n- Standard ERC-20, ERC-721, ERC-1155 tokens work without changes.\n- DeFi protocols, DEXs, and AMMs migrate seamlessly.\n- DAOs and governance contracts are fully compatible.\n- Most Solidity contracts deploy identically to Ethereum."} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 2, "depth": 2, "title": "Migration Checklist", "anchor": "migration-checklist", "start_char": 645, "end_char": 1058, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "## Migration Checklist\n\nBefore migrating your contracts, review this checklist:\n\n- Factory contracts using PVM bytecode need pre-uploaded dependencies.\n- Contracts using `EXTCODECOPY` for runtime manipulation require review (for projects that will use PVM bytecode, not EVM bytecode).\n- Replace `transfer()` and `send()` with proper reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode)."} @@ -1103,15 +1106,15 @@ {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 7, "depth": 3, "title": "How do gas costs compare?", "anchor": "how-do-gas-costs-compare", "start_char": 3177, "end_char": 3328, "estimated_token_count": 47, "token_estimator": "heuristic-v1", "text": "### How do gas costs compare?\n\nFor more information on gas costs, see the [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\\_blank} page."} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 8, "depth": 3, "title": "Which Solidity features are not supported?", "anchor": "which-solidity-features-are-not-supported", "start_char": 3328, "end_char": 3915, "estimated_token_count": 133, "token_estimator": "heuristic-v1", "text": "### Which Solidity features are not supported?\n\nFor REVM, any Solidity feature will function smoothly without requiring changes or adaptations. For PVM, there are considerations, as was mentioned above. \n\nFor PolkaVM, there are some considerations:\n\n- `EXTCODECOPY`: Only works in constructor code.\n- Runtime code modification: Use on-chain constructors instead.\n- **Gas stipends**: `address.send()` and `address.transfer()` don't provide reentrancy protection.\n- **Unsupported operations**: `pc`, `extcodecopy`, `selfdestruct`, `blobhash`, and `blobbasefee` (blob-related operations)."} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 9, "depth": 3, "title": "How do I handle the existential deposit?", "anchor": "how-do-i-handle-the-existential-deposit", "start_char": 3915, "end_char": 4518, "estimated_token_count": 121, "token_estimator": "heuristic-v1", "text": "### How do I handle the existential deposit?\n\nPolkadot requires accounts to maintain a minimum balance (existential deposit or ED) to remain active.\n\nThis is handled automatically for you:\n\n- Balance queries via Ethereum RPC automatically deduct the ED.\n- New account transfers include ED in transaction fees.\n- Contract-to-contract transfers draw ED from the transaction signer.\n\nYou typically don't need to do anything special, but be aware:\n\n- Accounts below ED threshold are automatically deleted.\n- ED is around 0.01 DOT (varies by network).\n- Your contracts don't need to manage this explicitly."} -{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 10, "depth": 3, "title": "Can I use my existing development tools?", "anchor": "can-i-use-my-existing-development-tools", "start_char": 4518, "end_char": 5319, "estimated_token_count": 257, "token_estimator": "heuristic-v1", "text": "### Can I use my existing development tools?\n\nYes. Both backends support:\n\n- **Wallets**: [MetaMask](https://metamask.io/){target=\\_blank}, [Talisman](https://talisman.xyz/){target=\\_blank}, [SubWallet](https://www.subwallet.app/){target=\\_blank}\n- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\\_blank}\n- **Libraries**: [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank}, [Web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank}, [viem](/smart-contracts/libraries/viem/){target=\\_blank}\n- **Testing tools**: Your existing test suites work\n\nConnect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow."} -{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 11, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 5319, "end_char": 6067, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nMost Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance.\n\nThere are a few key points to keep in mind during migration:\n\n- Replace `transfer()` and `send()` with `.call{value}(\"\")` and use reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode).\n- PolkaVM factory contracts using PVM bytecode need pre-uploaded dependencies.\n- Don't hardcode gas values.\n- Test thoroughly on [TestNet](/smart-contracts/connect/#__tabbed_1_1){target=\\_blank} before mainnet deployment.\n\nYour existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns."} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 0, "depth": 2, "title": "Quick Starts", "anchor": "quick-starts", "start_char": 173, "end_char": 1860, "estimated_token_count": 462, "token_estimator": "heuristic-v1", "text": "## Quick Starts\n\nKick off development fast with curated links for connecting, funding, exploring, and deploying your first contract.\n\n| Quick Start | Tools | Description |\n|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:|\n| [Connect to Polkadot](/smart-contracts/connect/){target=\\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer |\n| [Get Test Tokens](/smart-contracts/faucets/){target=\\_blank} | - | Request test funds to deploy and interact with contracts |\n| [Explore Transactions](/smart-contracts/explorers/){target=\\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state |\n| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\\_blank} | Remix | One‑click browser deployment to Polkadot Hub |\n| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\\_blank} | Foundry | Scripted deployments and testing from the CLI |\n| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank} | Hardhat | Project scaffolding, testing, and deployments |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 1, "depth": 2, "title": "Build and Test Locally", "anchor": "build-and-test-locally", "start_char": 1860, "end_char": 4067, "estimated_token_count": 604, "token_estimator": "heuristic-v1", "text": "## Build and Test Locally\n\nSet up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying.\n\n| Build and Test Locally | Tools | Description |\n|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:|\n| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\\_blank} | Polkadot SDK node | Spin up a local node for iterative development |\n| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts |\n| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\\_blank} | Remix | Publish verified source on explorers |\n| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\\_blank} | Foundry | Install toolchain and configure networks |\n| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\\_blank} | Foundry | Write and run Solidity tests locally |\n| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\\_blank} | Foundry | Verify deployed bytecode and metadata |\n| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank} | Hardhat | Initialize a project and configure networks |\n| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank} | Hardhat | Unit test contracts and run scripts |\n| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\\_blank} | Hardhat | Verify deployments on explorers |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 2, "depth": 2, "title": "Ethereum Developer Resources", "anchor": "ethereum-developer-resources", "start_char": 4067, "end_char": 5795, "estimated_token_count": 492, "token_estimator": "heuristic-v1", "text": "## Ethereum Developer Resources\n\nBridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment.\n\n| Ethereum Developer Guides | Description |\n|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:|\n| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts |\n| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\\_blank} | Transaction types, fees, and multi‑dimensional metering |\n| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\\_blank} | Gas vs. weight, proof size, and storage deposits |\n| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\\_blank} | Deployment patterns and best practices on Polkadot Hub |\n| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\\_blank} | Supported Ethereum JSON‑RPC methods and examples |\n| [Migration](/smart-contracts/for-eth-devs/migration/){target=\\_blank} | Port existing apps and tooling to Polkadot Hub |\n| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\\_blank} | Overview of EVM and native execution on the Hub |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 3, "depth": 2, "title": "Cookbook: Hands‑on Tutorials", "anchor": "cookbook-handson-tutorials", "start_char": 5795, "end_char": 7141, "estimated_token_count": 427, "token_estimator": "heuristic-v1", "text": "## Cookbook: Hands‑on Tutorials\n\nFollow step‑by‑step guides that walk through common tasks and complete dApp examples.\n\n| Tutorial | Tools | Description |\n|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:|\n| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\\_blank} | Remix | Minimal deployment walkthrough |\n| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token |\n| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection |\n| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\\_blank} | Hardhat | Full dApp project: compile, test, deploy |\n| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\\_blank} | Multiple | End‑to‑end dApp patterns and practices |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 4, "depth": 2, "title": "Libraries", "anchor": "libraries", "start_char": 7141, "end_char": 8154, "estimated_token_count": 317, "token_estimator": "heuristic-v1", "text": "## Libraries\n\nChoose the client libraries that fit your stack for connecting wallets and calling contracts.\n\n| Library | Description |\n|:------------------------------------------------------------------:|:-------------------------------------------------------:|\n| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank} | Connect, sign, and interact with contracts using Ethers |\n| [viem](/smart-contracts/libraries/viem/){target=\\_blank} | Type‑safe EVM interactions and utilities |\n| [Wagmi](/smart-contracts/libraries/wagmi/){target=\\_blank} | React hooks for wallet connections and contract calls |\n| [Web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank} | Web3 provider and contract APIs |\n| [Web3.py](/smart-contracts/libraries/web3-py/){target=\\_blank} | Python toolkit for on‑chain interactions and scripts |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 5, "depth": 2, "title": "Integrations", "anchor": "integrations", "start_char": 8154, "end_char": 8842, "estimated_token_count": 224, "token_estimator": "heuristic-v1", "text": "## Integrations\n\nIntegrate essential services like wallets, indexers, and oracles to round out your dApp.\n\n| Integration | Description |\n|:-------------------------------------------------------------------:|:-----------------------------------------:|\n| [Wallets](/smart-contracts/integrations/wallets/){target=\\_blank} | Supported wallets and configuration notes |\n| [Indexers](/smart-contracts/integrations/indexers/){target=\\_blank} | Index and query blockchain data |\n| [Oracles](/smart-contracts/integrations/oracles/){target=\\_blank} | Bring external data on‑chain |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 6, "depth": 2, "title": "Precompiles", "anchor": "precompiles", "start_char": 8842, "end_char": 10103, "estimated_token_count": 362, "token_estimator": "heuristic-v1", "text": "## Precompiles\n\nDiscover precompiled system contracts available on the Hub and how to use them.\n\n| Topic | Description |\n|:------------------------------------------------------------------------:|:---------------------------------------------------:|\n| [Overview of Precompiles](/smart-contracts/precompiles/){target=\\_blank} | What precompiles are available on the Hub |\n| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\\_blank} | EVM precompiles and interfaces |\n| [Staking](/smart-contracts/precompiles/staking/){target=\\_blank} | Interact with staking functionality via precompiles |\n| [XCM](/smart-contracts/precompiles/xcm/){target=\\_blank} | Cross‑chain messaging helpers for contracts |\n\nFrom here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\\_blank} or reach out in the community channels."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 10, "depth": 3, "title": "Can I use my existing development tools?", "anchor": "can-i-use-my-existing-development-tools", "start_char": 4518, "end_char": 5499, "estimated_token_count": 304, "token_estimator": "heuristic-v1", "text": "### Can I use my existing development tools?\n\nYes. Both backends support:\n\n- **Wallets**: [MetaMask](https://metamask.io/){target=\\_blank}, [Talisman](https://talisman.xyz/){target=\\_blank}, [SubWallet](https://www.subwallet.app/){target=\\_blank}\n- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\\_blank}, [Foundry](/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/){target=\\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\\_blank} (just consider that for PVM bytecode, you will use the Polkadot version of the tooling)\n- **Libraries**: [ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank}, [web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank}, [viem](/smart-contracts/libraries/viem/){target=\\_blank}\n- **Testing tools**: Your existing test suites work\n\nConnect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 11, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 5499, "end_char": 6247, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nMost Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance.\n\nThere are a few key points to keep in mind during migration:\n\n- Replace `transfer()` and `send()` with `.call{value}(\"\")` and use reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode).\n- PolkaVM factory contracts using PVM bytecode need pre-uploaded dependencies.\n- Don't hardcode gas values.\n- Test thoroughly on [TestNet](/smart-contracts/connect/#__tabbed_1_1){target=\\_blank} before mainnet deployment.\n\nYour existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns."} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 0, "depth": 2, "title": "Quick Starts", "anchor": "quick-starts", "start_char": 173, "end_char": 1843, "estimated_token_count": 456, "token_estimator": "heuristic-v1", "text": "## Quick Starts\n\nKick off development fast with curated links for connecting, funding, exploring, and deploying your first contract.\n\n| Quick Start | Tools | Description |\n| :-------------------------------------------------------------------------------------------------: | :-------------------: | :-------------------------------------------------------------: |\n| [Connect to Polkadot](/smart-contracts/connect/){target=\\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer |\n| [Get Test Tokens](/smart-contracts/faucets/){target=\\_blank} | - | Request test funds to deploy and interact with contracts |\n| [Explore Transactions](/smart-contracts/explorers/){target=\\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state |\n| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\\_blank} | Remix | One‑click browser deployment to Polkadot Hub |\n| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\\_blank} | Foundry | Scripted deployments and testing from the CLI |\n| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank} | Hardhat | Project scaffolding, testing, and deployments |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 1, "depth": 2, "title": "Build and Test Locally", "anchor": "build-and-test-locally", "start_char": 1843, "end_char": 4050, "estimated_token_count": 596, "token_estimator": "heuristic-v1", "text": "## Build and Test Locally\n\nSet up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying.\n\n| Build and Test Locally | Tools | Description |\n| :--------------------------------------------------------------------------------------------------------: | :---------------: | :--------------------------------------------------: |\n| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\\_blank} | Polkadot SDK node | Spin up a local node for iterative development |\n| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts |\n| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\\_blank} | Remix | Publish verified source on explorers |\n| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\\_blank} | Foundry | Install toolchain and configure networks |\n| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\\_blank} | Foundry | Write and run Solidity tests locally |\n| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\\_blank} | Foundry | Verify deployed bytecode and metadata |\n| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank} | Hardhat | Initialize a project and configure networks |\n| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank} | Hardhat | Unit test contracts and run scripts |\n| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\\_blank} | Hardhat | Verify deployments on explorers |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 2, "depth": 2, "title": "Ethereum Developer Resources", "anchor": "ethereum-developer-resources", "start_char": 4050, "end_char": 5794, "estimated_token_count": 488, "token_estimator": "heuristic-v1", "text": "## Ethereum Developer Resources\n\nBridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment.\n\n| Ethereum Developer Guides | Description |\n| :-------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------: |\n| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts |\n| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\\_blank} | Transaction types, fees, and multi‑dimensional metering |\n| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\\_blank} | Gas vs. weight, proof size, and storage deposits |\n| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\\_blank} | Deployment patterns and best practices on Polkadot Hub |\n| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\\_blank} | Supported Ethereum JSON‑RPC methods and examples |\n| [Migration](/smart-contracts/for-eth-devs/migration/){target=\\_blank} | Port existing apps and tooling to Polkadot Hub |\n| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\\_blank} | Overview of EVM and native execution on the Hub |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 3, "depth": 2, "title": "Cookbook: Hands‑on Tutorials", "anchor": "cookbook-handson-tutorials", "start_char": 5794, "end_char": 7098, "estimated_token_count": 409, "token_estimator": "heuristic-v1", "text": "## Cookbook: Hands‑on Tutorials\n\nFollow step‑by‑step guides that walk through common tasks and complete dApp examples.\n\n| Tutorial | Tools | Description |\n| :------------------------------------------------------------------------------------------------: | :-----------------: | :---------------------------------------: |\n| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/){target=\\_blank} | Remix | Minimal deployment walkthrough |\n| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/){target=\\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token |\n| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/){target=\\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection |\n| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\\_blank} | Hardhat | Full dApp project: compile, test, deploy |\n| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\\_blank} | Multiple | End‑to‑end dApp patterns and practices |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 4, "depth": 2, "title": "Libraries", "anchor": "libraries", "start_char": 7098, "end_char": 8111, "estimated_token_count": 313, "token_estimator": "heuristic-v1", "text": "## Libraries\n\nChoose the client libraries that fit your stack for connecting wallets and calling contracts.\n\n| Library | Description |\n| :----------------------------------------------------------------: | :-----------------------------------------------------: |\n| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank} | Connect, sign, and interact with contracts using Ethers |\n| [viem](/smart-contracts/libraries/viem/){target=\\_blank} | Type‑safe EVM interactions and utilities |\n| [Wagmi](/smart-contracts/libraries/wagmi/){target=\\_blank} | React hooks for wallet connections and contract calls |\n| [Web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank} | Web3 provider and contract APIs |\n| [Web3.py](/smart-contracts/libraries/web3-py/){target=\\_blank} | Python toolkit for on‑chain interactions and scripts |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 5, "depth": 2, "title": "Integrations", "anchor": "integrations", "start_char": 8111, "end_char": 8799, "estimated_token_count": 220, "token_estimator": "heuristic-v1", "text": "## Integrations\n\nIntegrate essential services like wallets, indexers, and oracles to round out your dApp.\n\n| Integration | Description |\n| :-----------------------------------------------------------------: | :---------------------------------------: |\n| [Wallets](/smart-contracts/integrations/wallets/){target=\\_blank} | Supported wallets and configuration notes |\n| [Indexers](/smart-contracts/integrations/indexers/){target=\\_blank} | Index and query blockchain data |\n| [Oracles](/smart-contracts/integrations/oracles/){target=\\_blank} | Bring external data on‑chain |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 6, "depth": 2, "title": "Precompiles", "anchor": "precompiles", "start_char": 8799, "end_char": 10060, "estimated_token_count": 358, "token_estimator": "heuristic-v1", "text": "## Precompiles\n\nDiscover precompiled system contracts available on the Hub and how to use them.\n\n| Topic | Description |\n| :----------------------------------------------------------------------: | :-------------------------------------------------: |\n| [Overview of Precompiles](/smart-contracts/precompiles/){target=\\_blank} | What precompiles are available on the Hub |\n| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\\_blank} | EVM precompiles and interfaces |\n| [Staking](/smart-contracts/precompiles/staking/){target=\\_blank} | Interact with staking functionality via precompiles |\n| [XCM](/smart-contracts/precompiles/xcm/){target=\\_blank} | Cross‑chain messaging helpers for contracts |\n\nFrom here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\\_blank} or reach out in the community channels."} {"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 198, "end_char": 665, "estimated_token_count": 75, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nConnecting a compatible wallet is the first essential step for interacting with the Polkadot Hub ecosystem. This guide explores wallet options that support both Substrate and Ethereum compatible layers, enabling transactions and smart contract interactions. Whether you're a developer testing on Polkadot Hub or a user accessing the MainNet, understanding wallet configuration is crucial for accessing the full range of Polkadot Hub's capabilities."} {"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 1, "depth": 2, "title": "Connect Your Wallet", "anchor": "connect-your-wallet", "start_char": 665, "end_char": 689, "estimated_token_count": 5, "token_estimator": "heuristic-v1", "text": "## Connect Your Wallet"} {"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 2, "depth": 3, "title": "MetaMask", "anchor": "metamask", "start_char": 689, "end_char": 2383, "estimated_token_count": 403, "token_estimator": "heuristic-v1", "text": "### MetaMask\n\n[MetaMask](https://metamask.io/){target=\\_blank} is a popular wallet for interacting with Ethereum-compatible chains. It allows users to connect to test networks that support Ethereum-based smart contracts. However, it's important to emphasize that MetaMask primarily facilitates interactions with smart contracts, giving users access to various chain functionalities. \n\nTo get started with MetaMask, you need to install the [MetaMask extension](https://metamask.io/download/){target=\\_blank} and add it to the browser. Once you install MetaMask, you can set up a new wallet and securely store your seed phrase. This phrase is crucial for recovery in case you lose access.\n\nFor example, to connect to the Polkadot Hub TestNet via MetaMask, you need to follow these steps:\n\n1. Open the MetaMask extension and click on the network icon to switch to the Polkadot Hub TestNet.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-1.webp){: .browser-extension}\n\n2. Click on the **Add a custom network** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-2.webp){: .browser-extension}\n\n3. Complete the necessary fields, then click the **Save** button (refer to the [Networks](/smart-contracts/connect/#networks-details){target=\\_blank} section for copy and paste parameters).\n\n ![](/images/smart-contracts/integrations/wallets/wallets-3.webp){: .browser-extension}\n\n4. Click on **Polkadot Hub TestNet** to switch the network.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-4.webp){: .browser-extension}\n\nThe steps in the preceding section can be used to connect to any chain by modifying the network specification and endpoint parameters."} diff --git a/llms.txt b/llms.txt index 98d224c83..78de7de68 100644 --- a/llms.txt +++ b/llms.txt @@ -61,7 +61,7 @@ Docs: Smart Contracts - [Deploy an NFT to Polkadot Hub with Hardhat](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md): Learn how to deploy an ERC-721 NFT contract to Polkadot Hub with Hardhat, a comprehenive development environment with built-in deployment capabilities. - [Deploy an NFT to Polkadot Hub with Remix](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md): Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Remix, a browser-based IDE for quick prototyping and learning. - [Smart Contracts Cookbook Index](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md): Explore our full collection of tutorials and guides to learn step-by-step how to build, deploy, and work with smart contracts on Polkadot. -- [Use Hardhat with Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md): Learn how to create, compile, test, and deploy smart contracts on Polkadot Hub using Hardhat, a powerful development environment for blockchain developers. +- [Use Hardhat with Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md): Overview of Hardhat, a powerful development environment for creating, compiling, testing, and deploying smart contracts on Polkadot Hub. - [Local Development Node](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-local-dev-node.md): Follow this step-by-step guide to install a Revive Dev node and ETH-RPC adapter for smart contract development in a local environment. - [Use the Polkadot Remix IDE](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md): Explore the smart contract development and deployment process on Asset Hub using Remix IDE, a visual IDE for blockchain developers. - [Block Explorers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-explorers.md): Access PolkaVM explorers like Subscan, BlockScout, and Routescan to track transactions, analyze contracts, and view on-chain data from smart contracts. @@ -160,6 +160,8 @@ Docs: Infrastructure - [Rewards Payout](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-rewards.md): Learn how validator rewards work on the network, including era points, payout distribution, running multiple validators, and nominator payments. Docs: Tooling +- [Quickstart Parachain Development with Pop CLI](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-quickstart-pop-cli.md): Quickly bootstrap parachain projects, scaffold templates, deploy local networks, and streamline development workflows using Pop CLI. +- [Write Tests](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet-write-tests.md): Write and execute tests for blockchain networks with Zombienet's DSL. Learn to evaluate metrics, logs, events, and more for robust validation. - [Install Polkadot SDK](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md): Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. - [Indexers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md): Discover blockchain indexers. Enhance data access, enable fast and complex queries, and optimize blockchain data for seamless app performance. - [Oracles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md): Learn about blockchain oracles, the essential bridges connecting blockchains with real-world data for decentralized applications in the Polkadot ecosystem. @@ -179,7 +181,7 @@ Docs: Tooling - [XCM Tools](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md): Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. - [Zero to Hero Smart Contract DApp](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md): Learn how to build a decentralized application on Polkadot Hub using Viem and Next.js by creating a simple dApp that interacts with a smart contract. - [Deploying Uniswap V2 on Polkadot](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md): Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. -- [Use Hardhat with Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md): Learn how to create, compile, test, and deploy smart contracts on Polkadot Hub using Hardhat, a powerful development environment for blockchain developers. +- [Use Hardhat with Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md): Overview of Hardhat, a powerful development environment for creating, compiling, testing, and deploying smart contracts on Polkadot Hub. - [Use the Polkadot Remix IDE](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md): Explore the smart contract development and deployment process on Asset Hub using Remix IDE, a visual IDE for blockchain developers. - [Block Explorers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-explorers.md): Access PolkaVM explorers like Subscan, BlockScout, and Routescan to track transactions, analyze contracts, and view on-chain data from smart contracts. - [Wallets for Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md): Comprehensive guide to connecting and managing wallets for Polkadot Hub, covering step-by-step instructions for interacting with the ecosystem. @@ -234,6 +236,14 @@ Docs: Uncategorized - [reference-tools-chopsticks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md): No description available. - [ParaSpell XCM SDK](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md): A powerful open-source library that simplifies XCM integration, enabling developers to easily build interoperable dApps on Polkadot. - [reference-tools-zombienet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md): No description available. +- [reference](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md): No description available. +- [smart-contracts-cookbook-smart-contracts-deploy-basic](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic.md): No description available. +- [smart-contracts-dev-environments-foundry-compile-and-test](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-compile-and-test.md): No description available. +- [smart-contracts-dev-environments-foundry-deploy-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-deploy-a-contract.md): No description available. +- [Use Foundry with Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-get-started.md): Learn to install, configure, and use foundry-polkadot for smart contract development on Polkadot with PolkaVM bytecode compilation. +- [smart-contracts-dev-environments-foundry-install-and-config](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-install-and-config.md): No description available. +- [smart-contracts-dev-environments-foundry-troubleshooting](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-troubleshooting.md): No description available. +- [smart-contracts-dev-environments-foundry-verify-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-verify-a-contract.md): No description available. - [smart-contracts-dev-environments-hardhat-compile-and-test](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-compile-and-test.md): No description available. - [smart-contracts-dev-environments-hardhat-deploy-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-deploy-a-contract.md): No description available. - [smart-contracts-dev-environments-hardhat-install-and-config](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-install-and-config.md): No description available. diff --git a/smart-contracts/dev-environments/hardhat/get-started.md b/smart-contracts/dev-environments/hardhat/get-started.md index 4be906e3d..0710360e9 100644 --- a/smart-contracts/dev-environments/hardhat/get-started.md +++ b/smart-contracts/dev-environments/hardhat/get-started.md @@ -1,338 +1,125 @@ --- title: Use Hardhat with Polkadot Hub -description: Learn how to create, compile, test, and deploy smart contracts on Polkadot Hub using Hardhat, a powerful development environment for blockchain developers. +description: Overview of Hardhat, a powerful development environment for creating, compiling, testing, and deploying smart contracts on Polkadot Hub. categories: Smart Contracts, Tooling --- # Hardhat ---8<-- 'text/smart-contracts/polkaVM-warning.md' - -
-- :octicons-code-16:{ .lg .middle } __Test and Deploy with Hardhat__ - - --- - - Master Solidity smart contract development with Hardhat. Learn testing, deployment, and network interaction in one comprehensive tutorial. - -
- [:octicons-arrow-right-24: Get Started](/tutorials/smart-contracts/launch-your-first-project/test-and-deploy-with-hardhat){target=\_blank} - -
- ---8<-- 'text/smart-contracts/code-size.md' - ## Overview -Hardhat is a robust development environment for Ethereum-compatible chains that makes smart contract development more efficient. This guide walks you through the essentials of using Hardhat to create, compile, test, and deploy smart contracts on Polkadot Hub. - -## Prerequisites - -Before getting started, ensure you have: - -- [Node.js](https://nodejs.org/){target=\_blank} (v16.0.0 or later) and npm installed. - - Note: Use Node.js 22.5+ and npm version 10.9.0+ to avoid issues with the Polkadot plugin. -- Basic understanding of Solidity programming. -- Some PAS test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}). To learn how to get test tokens, check out the [Test Tokens](/smart-contracts/connect/#test-tokens){target=\_blank} section. - -## Set Up Hardhat - -1. Create a new directory for your project and navigate into it: - - ```bash - mkdir hardhat-example - cd hardhat-example - ``` - -2. Initialize a new npm project: - - ```bash - npm init -y - ``` - -3. To interact with Polkadot, Hardhat requires the following plugin to compile contracts to PolkaVM bytecode and to spawn a local node compatible with PolkaVM: - - ```bash - npm install --save-dev @parity/hardhat-polkadot@0.1.9 - ``` - -4. Create a Hardhat project: - - ```bash - npx hardhat-polkadot init - ``` - - Select **Create a JavaScript project** when prompted and follow the instructions. After that, your project will be created with three main folders: - - - **`contracts`**: Where your Solidity smart contracts live. - - **`test`**: Contains your test files that validate contract functionality. - - **`ignition`**: Deployment modules for safely deploying your contracts to various networks. - -5. Add the following folder to the `.gitignore` file if it is not already there: - - ```bash - echo '/ignition/deployments/' >> .gitignore - ``` - -6. Finish the setup by installing all the dependencies: - - ```bash - npm install - ``` - - !!! note - This last step is needed to set up the `hardhat-polkadot` plugin. It will install the `@parity/hardhat-polkadot` package and all its dependencies. In the future, the plugin will handle this automatically. - -## Compile Your Contract - -The plugin will compile your Solidity contracts for Solidity versions `0.8.0` and higher to be PolkaVM compatible. When compiling your contract, there are two ways to configure your compilation process: - -- **npm compiler**: Uses library [@parity/resolc](https://www.npmjs.com/package/@parity/resolc){target=\_blank} for simplicity and ease of use. -- **Binary compiler**: Uses your local `resolc` binary directly for more control and configuration options. - -To compile your project, follow these instructions: - -1. Modify your Hardhat configuration file to specify which compilation process you will be using and activate the `polkavm` flag in the Hardhat network: - - === "npm Configuration" - - ```javascript title="hardhat.config.js" hl_lines="9-11 14" - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:1:14' - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:33:35' - ``` - - === "Binary Configuration" - - ```javascript title="hardhat.config.js" hl_lines="9-14 17" - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/binary-hardhat.config.js:1:17' - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/binary-hardhat.config.js:36:38' - ``` - - For the binary configuration, replace `INSERT_PATH_TO_RESOLC_COMPILER` with the proper path to the binary. To obtain the binary, check the [releases](https://github.com/paritytech/revive/releases){target=\_blank} section of the `resolc` compiler, and download the latest version. - - The default settings used can be found in the [`constants.ts`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/constants.ts#L8-L23){target=\_blank} file of the `hardhat-polkadot` source code. You can change them according to your project needs. Generally, the recommended settings for optimized outputs are the following: - - ```javascript title="hardhat.config.js" hl_lines="4-10" - resolc: { - ... - settings: { - optimizer: { - enabled: true, - parameters: 'z', - fallbackOz: true, - runs: 200, - }, - standardJson: true, - }, - ... - } - ``` - - You can check the [`ResolcConfig`](https://github.com/paritytech/hardhat-polkadot/blob/v0.1.5/packages/hardhat-polkadot-resolc/src/types.ts#L26){target=\_blank} for more information about compilation settings. - -2. Compile the contract with Hardhat: - - ```bash - npx hardhat compile - ``` - -3. After successful compilation, you'll see the artifacts generated in the `artifacts-pvm` directory: - - ```bash - ls artifacts-pvm/contracts/*.sol/ - ``` +Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer. - You should see JSON files containing the contract ABI and bytecode of the contracts you compiled. +Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit, including compilation, local testing nodes, debugging tools, and deployment automation. -## Set Up a Testing Environment +## Hardhat Workflow -Hardhat allows you to spin up a local testing environment to test and validate your smart contract functionalities before deploying to live networks. The `hardhat-polkadot` plugin provides the possibility to spin up a local node with an ETH-RPC adapter for running local tests. +From the first sketch of a contract to ongoing operations, Hardhat encourages a repeatable cycle: define the functionality you need, scaffold the workspace, write and refine Solidity code, compile it into deployable artifacts, validate behavior with automated tests, deploy confidently to the target network, and keep iterating with scripts that monitor and interact with what you shipped. -For complete isolation and control over the testing environment, you can configure Hardhat to work with a fresh local Substrate node. This approach is ideal when you want to test in a clean environment without any existing state or when you need specific node configurations. +```mermaid +flowchart LR + plan[Plan Contract] + scaffold[Scaffold Project] + develop[Write & Update Contracts] + compile[Compile Sources] + test[Run Automated Tests] + deploy[Deploy to Target Network] + operate[Interact & Monitor] -Configure a local node setup by adding the node binary path along with the ETH-RPC adapter path: - -```javascript title="hardhat.config.js" hl_lines="12-20" ---8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:1:4' - ---8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:6:7' - ... - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:12:24' ---8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:34:35' + plan --> scaffold --> develop --> compile --> test --> deploy --> operate ``` -Replace `INSERT_PATH_TO_SUBSTRATE_NODE` and `INSERT_PATH_TO_ETH_RPC_ADAPTER` with the actual paths to your compiled binaries. The `dev: true` flag configures both the node and adapter for development mode. To obtain these binaries, check the [Installation](/smart-contracts/dev-environments/local-dev-node/#install-the-substrate-node-and-eth-rpc-adapter){target=\_blank} section on the Local Development Node page. - -!!! warning - If you're using the default `hardhat.config.js` created by the `hardhat-polkadot` plugin, it includes a `forking` section pointing to the Polkadot Hub TestNet. When you run `npx hardhat node`, Hardhat will start a fork of that network. To use your local node instead, comment out the `forking` section; otherwise, `npx hardhat node` will continue to use the forked network even if a local node is defined in the configuration. +## Project Anatomy -Once configured, start your chosen testing environment with: +A freshly initialized Hardhat project keeps code, configuration, and automation neatly separated: -```bash -npx hardhat node +``` +. +├── contracts/ +│ └── MyContract.sol +├── ignition/ +│ └── modules/ +├── scripts/ +│ └── interact.js +├── test/ +│ └── MyContract.test.js +└── hardhat.config.js ``` -This command will launch either the forked network or local node (depending on your configuration) along with the ETH-RPC adapter, providing you with a complete testing environment ready for contract deployment and interaction. By default, the Substrate node will be running on `localhost:8000` and the ETH-RPC adapter on `localhost:8545`. - -The output will be something like this: - ---8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat-node-output.html' - -## Test Your Contract - -When testing your contract, be aware that [`@nomicfoundation/hardhat-toolbox/network-helpers`](https://hardhat.org/hardhat-network-helpers/docs/overview){target=\_blank} is not fully compatible with Polkadot Hub's available RPCs. Specifically, Hardhat-only helpers like `time` and `loadFixture` may not work due to missing RPC calls in the node. For more details, refer to the [Compatibility](https://github.com/paritytech/hardhat-polkadot/tree/main/packages/hardhat-polkadot-node#compatibility){target=\_blank} section in the `hardhat-revive` docs. You should avoid using helpers like `time` and `loadFixture` when writing tests. - -To run your test: - -1. Update the `hardhat.config.js` file accordingly to the [Set Up a Testing Environment](#set-up-a-testing-environment) section. - -2. Execute the following command to run your tests: - - ```bash - npx hardhat test - ``` - -## Deploy to a Local Node - -Before deploying to a live network, you can deploy your contract to a local node using [Ignition](https://hardhat.org/ignition/docs/getting-started#overview){target=\_blank} modules: - -1. Update the Hardhat configuration file to add the local network as a target for local deployment: - - ```javascript title="hardhat.config.js" hl_lines="13-16" - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:1:4' - - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:6:7' - ... - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:12:13' - ... - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:24:28' - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:33:35' - ``` - -2. Start a local node: - - ```bash - npx hardhat node - ``` - - This command will spawn a local Substrate node along with the ETH-RPC adapter. - -3. In a new terminal window, deploy the contract using Ignition: - - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network localNode - ``` - -## Deploying to a Live Network - -After testing your contract locally, you can deploy it to a live network. This guide will use the Polkadot Hub TestNet as the target network. Here's how to configure and deploy: - -1. Fund your deployment account with enough tokens to cover gas fees. In this case, the needed tokens are PAS (on Polkadot Hub TestNet). You can use the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank} to obtain testing tokens. - -2. Export your private key and save it in your Hardhat environment: - - ```bash - npx hardhat vars set PRIVATE_KEY "INSERT_PRIVATE_KEY" - ``` - - Replace `INSERT_PRIVATE_KEY` with your actual private key. For further details on private key exportation, refer to the article [How to export an account's private key](https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/){target=\_blank}. - - !!! warning - Never reveal your private key, otherwise anyone with access to it can control your wallet and steal your funds. Store it securely and never share it publicly or commit it to version control systems. - -3. Check that your private key has been set up successfully by running: - - ```bash - npx hardhat vars get PRIVATE_KEY - ``` - -4. Update your Hardhat configuration file with network settings for the Polkadot network you want to target: +- `contracts/`: Solidity sources that define your smart contracts. +- `test/`: Automated tests written in JavaScript or TypeScript. +- `ignition/`: Deployment modules that orchestrate repeatable rollouts. +- `scripts/`: Utility scripts for deploying, validating, or interacting with contracts. +- `hardhat.config.js`: Central configuration for networks, compilers, and tooling. - ```javascript title="hardhat.config.js" hl_lines="18-22" - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:1:4' +## Core Functionalities - const { vars } = require('hardhat/config'); +- **Project structure**: Organizes contracts, tests, scripts, and configuration into a consistent workspace. Provides a clear folder layout and a single configuration file (`hardhat.config.js`) to manage compilers, networks, and tooling. +- **Compilation**: Compiles Solidity sources, supports multiple compiler versions, and generates ABI and bytecode artifacts. +- **Local testing**: Runs tests written in JavaScript or TypeScript against an integrated local network, enabling fast feedback when validating contract behavior. +- **Task automation**: Automates deployments, maintenance operations, and recurring workflows through custom scripts and Hardhat tasks. +- **Contract interaction**: Enables reading contract state, sending transactions, and calling contract functions. - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:6:7' - ... - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:12:13' - ... - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:24:24' - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:25:25' - ... - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:28:33' - --8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/hardhat.config.js:33:35' - ``` +## Where to Go Next -6. Deploy your contract using Ignition: +Ready to explore the specifics? Dive into these guides to continue your Hardhat journey: - ```bash - npx hardhat ignition deploy ./ignition/modules/MyToken.js --network polkadotHubTestnet - ``` +
-## Interacting with Your Contract +- Guide __Install and Configure Hardhat__ -Once deployed, you can create a script to interact with your contract. To do so, create a file called `scripts/interact.js` and add some logic to interact with the contract. + --- -For example, for the default `MyToken.sol` contract, you can use the following file that connects to the contract at its address and retrieves the `unlockTime`, which represents when funds can be withdrawn. The script converts this timestamp into a readable date and logs it. It then checks the contract's balance and displays it. Finally, it attempts to call the withdrawal function on the contract, but it catches and logs the error message if the withdrawal is not yet allowed (e.g., before `unlockTime`). + Initialize your workspace and adjust project settings for this toolchain. -```javascript title="interact.js" ---8<-- 'code/smart-contracts/dev-environments/hardhat/get-started/interact.js' -``` + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} -Run your interaction script: +- Guide __Compile Smart Contracts__ -```bash -npx hardhat run scripts/interact.js --network polkadotHubTestnet -``` + --- -## Upgrading the Plugin + Configure compiler options and generate deployable artifacts. -If you already have a Hardhat Polkadot project and want to upgrade to a newer version of the plugin, to avoid errors (for example, `Cannot find module 'run-container'`), you can clean your dependencies by running the following commands: + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} -```bash -rm -rf node_modules package-lock.json -``` +- Guide __Test Your Smart Contracts__ -After that, you can upgrade the plugin to the latest version by running the following commands: + --- -```bash -npm install --save-dev @parity/hardhat-polkadot@latest -npm install -``` + Build automated tests and run them against a local node. -Consider using [Node.js](https://nodejs.org/){target=\_blank} 22.18+ and [npm](https://www.npmjs.com/){target=\_blank} version 10.9.0+ to avoid issues with the plugin. + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} -## Where to Go Next +- Guide __Deploy Smart Contracts__ -Hardhat provides a powerful environment for developing, testing, and deploying smart contracts on Polkadot Hub. Its plugin architecture allows seamless integration with PolkaVM through the `hardhat-resolc` and `hardhat-revive-node` plugins. + --- -Explore more about smart contracts through these resources: + Roll out contracts to local, test, or production networks with repeatable scripts. -
+ [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} -- Guide __Get Started with Smart Contracts__ +- Guide __Interact with Smart Contracts__ --- - Learn how to get started with smart contracts + Script on-chain interactions and automate maintenance tasks. - [:octicons-arrow-right-24: Get Started](/smart-contracts/get-started/) + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank} - External __Hardhat Documentation__ --- - Learn more about Hardhat's advanced features and best practices. + Explore Hardhat's official documentation for advanced features and best practices. - [:octicons-arrow-right-24: Get Started](https://hardhat.org/docs){target=\_blank} + [:octicons-arrow-right-24: Learn More](https://hardhat.org/docs){target=\_blank} - External __OpenZeppelin Contracts__ --- - Test your skills by deploying contracts with prebuilt templates. + Use prebuilt, audited contract templates to bootstrap your projects. - [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank} + [:octicons-arrow-right-24: Explore](https://www.openzeppelin.com/solidity-contracts){target=\_blank} -
+
\ No newline at end of file From dcc644be29b8243fef9d3336f6ed928e196627f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hussein?= <80422357+nhussein11@users.noreply.github.com> Date: Tue, 18 Nov 2025 14:56:13 -0300 Subject: [PATCH 09/12] Fix local dev node (#1226) * Remove outdated warning reference from local development node documentation * fix: llms * fix: llms --------- Co-authored-by: Erin Shaben --- .ai/categories/smart-contracts.md | 478 +- .ai/categories/tooling.md | 37 +- ...ts-dev-environments-hardhat-get-started.md | 37 +- ...ntracts-dev-environments-local-dev-node.md | 3 - .../smart-contracts-for-eth-devs-migration.md | 4 +- .ai/site-index.json | 15221 +++++----------- llms-full.jsonl | 141 +- llms.txt | 10 - .../dev-environments/local-dev-node.md | 3 - 9 files changed, 4654 insertions(+), 11280 deletions(-) diff --git a/.ai/categories/smart-contracts.md b/.ai/categories/smart-contracts.md index dfd3931b5..5412f63f8 100644 --- a/.ai/categories/smart-contracts.md +++ b/.ai/categories/smart-contracts.md @@ -4439,280 +4439,6 @@ By defining weights, you can trade-off the number of transactions per second and Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. ---- - -Page Title: hardhat - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-hardhat/ -- Summary: Learn how to deploy a basic smart contract to Polkadot Hub using Hardhat, Perfect for professional workflows requiring comprehensive testing and debugging. - -[Hardhat](https://hardhat.org/){target=\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects. - -**Prerequisites:** - -- Basic understanding of Solidity programming. -- [Node.js](https://nodejs.org/en/download){target=\_blank} v22.13.1 or later. -- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). -- A wallet with a private key for signing transactions. - -### Setup - -Initialize your Hardhat project: - -```bash -mkdir hardhat-deployment -cd hardhat-deployment -npx hardhat --init -``` - -### Configure Hardhat - -Edit `hardhat.config.js`: - -```javascript title="hardhat.config.js" hl_lines="39-43" -import type { HardhatUserConfig } from "hardhat/config"; - -import hardhatToolboxViemPlugin from "@nomicfoundation/hardhat-toolbox-viem"; -import { configVariable } from "hardhat/config"; - -const config: HardhatUserConfig = { - plugins: [hardhatToolboxViemPlugin], - solidity: { - profiles: { - default: { - version: "0.8.28", - }, - production: { - version: "0.8.28", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - }, - }, - networks: { - hardhatMainnet: { - type: "edr-simulated", - chainType: "l1", - }, - hardhatOp: { - type: "edr-simulated", - chainType: "op", - }, - sepolia: { - type: "http", - chainType: "l1", - url: configVariable("SEPOLIA_RPC_URL"), - accounts: [configVariable("SEPOLIA_PRIVATE_KEY")], - }, - polkadotHubTestnet: { - url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - accounts: [configVariable("PRIVATE_KEY")], - }, - }, -}; - -export default config; - -``` - -### Create Your Contract - -Replace the default contract in `contracts/Storage.sol`: - -```solidity -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -contract Storage { - uint256 private storedNumber; - - function store(uint256 num) public { - storedNumber = num; - } - - function retrieve() public view returns (uint256) { - return storedNumber; - } -} -``` - -### Compile - -```bash -npx hardhat build -``` - -### Set Up Deployment - -Create a deployment module in `ignition/modules/Storage.ts`: - -```typescript title="ignition/modules/Storage.ts" -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; - -export default buildModule('StorageModule', (m) => { - const storage = m.contract('Storage'); - return { storage }; -}); -``` - -### Deploy - -Deploy to Polkadot Hub TestNet: - -```bash -npx hardhat ignition deploy ignition/modules/Storage.ts --network polkadotHubTestnet -``` - -### Next Steps - -- Deploy an ERC-20 token on Polkadot Hub, either using the [Deploy an ERC-20](/smart-contracts/cookbook/smart-contracts/deploy-erc20) guide or the [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20) guide. -- Deploy an NFT on Polkadot Hub, either using the [Deploy an NFT](/smart-contracts/cookbook/smart-contracts/deploy-nft) guide or the [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft) guide. -- Check out in details each [development environment](/smart-contracts/dev-environments/). - - ---- - -Page Title: hardhat - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-hardhat/ -- Summary: Learn how to deploy a basic smart contract to Polkadot Hub using Hardhat, Perfect for professional workflows requiring comprehensive testing and debugging. - -[Hardhat](https://hardhat.org/){target=\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects. - -**Prerequisites:** - -- Basic understanding of Solidity programming. -- [Node.js](https://nodejs.org/en/download){target=\_blank} v22.13.1 or later. -- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). -- A wallet with a private key for signing transactions. - -### Setup - -Initialize your Hardhat project: - -```bash -mkdir hardhat-deployment -cd hardhat-deployment -npx hardhat --init -``` - -### Configure Hardhat - -Edit `hardhat.config.js`: - -```javascript title="hardhat.config.js" hl_lines="39-43" -import type { HardhatUserConfig } from "hardhat/config"; - -import hardhatToolboxViemPlugin from "@nomicfoundation/hardhat-toolbox-viem"; -import { configVariable } from "hardhat/config"; - -const config: HardhatUserConfig = { - plugins: [hardhatToolboxViemPlugin], - solidity: { - profiles: { - default: { - version: "0.8.28", - }, - production: { - version: "0.8.28", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - }, - }, - networks: { - hardhatMainnet: { - type: "edr-simulated", - chainType: "l1", - }, - hardhatOp: { - type: "edr-simulated", - chainType: "op", - }, - sepolia: { - type: "http", - chainType: "l1", - url: configVariable("SEPOLIA_RPC_URL"), - accounts: [configVariable("SEPOLIA_PRIVATE_KEY")], - }, - polkadotHubTestnet: { - url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - accounts: [configVariable("PRIVATE_KEY")], - }, - }, -}; - -export default config; - -``` - -### Create Your Contract - -Replace the default contract in `contracts/Storage.sol`: - -```solidity -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -contract Storage { - uint256 private storedNumber; - - function store(uint256 num) public { - storedNumber = num; - } - - function retrieve() public view returns (uint256) { - return storedNumber; - } -} -``` - -### Compile - -```bash -npx hardhat build -``` - -### Set Up Deployment - -Create a deployment module in `ignition/modules/Storage.ts`: - -```typescript title="ignition/modules/Storage.ts" -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; - -export default buildModule('StorageModule', (m) => { - const storage = m.contract('Storage'); - return { storage }; -}); -``` - -### Deploy - -Deploy to Polkadot Hub TestNet: - -```bash -npx hardhat ignition deploy ignition/modules/Storage.ts --network polkadotHubTestnet -``` - -### Next Steps - -- Deploy an ERC-20 token on Polkadot Hub, either using the [Deploy an ERC-20](/smart-contracts/cookbook/smart-contracts/deploy-erc20) guide or the [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20) guide. -- Deploy an NFT on Polkadot Hub, either using the [Deploy an NFT](/smart-contracts/cookbook/smart-contracts/deploy-nft) guide or the [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft) guide. -- Check out in details each [development environment](/smart-contracts/dev-environments/). - - --- Page Title: Install Polkadot SDK @@ -5134,16 +4860,6 @@ To stop the node, press `Control-C` in the terminal.
-- __Get Started with Parachain Development__ - - --- - - Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. - - [:octicons-arrow-right-24: Get Started](/parachains/get-started/) - -
- --- @@ -6413,8 +6129,6 @@ Page Title: Local Development Node # Local Development Node -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction A local development node provides an isolated blockchain environment where you can deploy, test, and debug smart contracts without incurring network fees or waiting for block confirmations. This guide demonstrates how to set up a local Polkadot SDK-based node with smart contract capabilities. @@ -6437,7 +6151,6 @@ The Polkadot SDK repository contains both the [Revive Dev node](https://github.c ```bash git clone https://github.com/paritytech/polkadot-sdk.git cd polkadot-sdk -git checkout 8e2b6f742a38bb13688e12abacded0aab2dbbb23 ``` Next, you need to compile the two essential components for your development environment. The Substrate node provides the core blockchain runtime with smart contract support, while the ETH-RPC adapter enables Ethereum JSON-RPC compatibility for existing tooling: @@ -6674,160 +6387,6 @@ You typically don't need to do anything special, but be aware: Yes. Both backends support: -- **Wallets**: [MetaMask](https://metamask.io/){target=\_blank}, [Talisman](https://talisman.xyz/){target=\_blank}, [SubWallet](https://www.subwallet.app/){target=\_blank} -- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\_blank}, [Foundry](/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/){target=\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} (just consider that for PVM bytecode, you will use the Polkadot version of the tooling) -- **Libraries**: [ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank}, [web3.js](/smart-contracts/libraries/web3-js/){target=\_blank}, [viem](/smart-contracts/libraries/viem/){target=\_blank} -- **Testing tools**: Your existing test suites work - -Connect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow. - -## Conclusion - -Most Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance. - -There are a few key points to keep in mind during migration: - -- Replace `transfer()` and `send()` with `.call{value}("")` and use reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode). -- PolkaVM factory contracts using PVM bytecode need pre-uploaded dependencies. -- Don't hardcode gas values. -- Test thoroughly on [TestNet](/smart-contracts/connect/#__tabbed_1_1){target=\_blank} before mainnet deployment. - -Your existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns. - - ---- - -Page Title: Networks - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/ -- Summary: Learn how to migrate your existing Ethereum contracts to the Polkadot Hub using REVM and PolkaVM by following these considerations. - -# Migration FAQs and Considerations - -## Introduction - -This guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns. - -## Migration Considerations - -Take into account the following considerations before migrating your contracts: - -- Standard ERC-20, ERC-721, ERC-1155 tokens work without changes. -- DeFi protocols, DEXs, and AMMs migrate seamlessly. -- DAOs and governance contracts are fully compatible. -- Most Solidity contracts deploy identically to Ethereum. - -## Migration Checklist - -Before migrating your contracts, review this checklist: - -- Factory contracts using PVM bytecode need pre-uploaded dependencies. -- Contracts using `EXTCODECOPY` for runtime manipulation require review (for projects that will use PVM bytecode, not EVM bytecode). -- Replace `transfer()` and `send()` with proper reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode). - -## Migration FAQs - -### Which backend should I choose? - -- Choose REVM if you want: - - - Zero-modification deployment of existing Ethereum contracts. - - Exact EVM behavior for audited code. - - Compatibility with tools that inspect EVM bytecode. - - Rapid deployment without optimization. - -- Choose PolkaVM if you want: - - - Better performance for computation-heavy applications. - - Lower execution costs for intensive operations. - - Access to next-generation smart contract features. - -If you are unsure which to choose, start with REVM for immediate compatibility, then consider PolkaVM for performance optimization once deployed. - -### Do I need to rewrite my Solidity code? - -No, for most contracts. Standard Solidity patterns work on both backends. - -### What about factory contracts? - -- **REVM**: Factory contracts work identically to Ethereum with no changes needed. - - The original factory pattern is: - - ```solidity - contract TokenFactory { - function createToken(string memory name) public returns (address) { - // Creates new contract at runtime - Token newToken = new Token(name); - return address(newToken); - } - } - ``` - -- **PolkaVM**: Factory contracts require pre-uploading dependent contracts. - - Here's how to adapt the original factory pattern: - - ```solidity - contract TokenFactory { - // Reference pre-uploaded Token contract by hash - bytes32 public tokenCodeHash; - - constructor(bytes32 _tokenCodeHash) { - tokenCodeHash = _tokenCodeHash; - } - - function createToken(string memory name) public returns (address) { - // Instantiate from pre-uploaded code - Token newToken = new Token{salt: keccak256(abi.encode(name))}(name); - return address(newToken); - } - } - ``` - -The deployment steps for PolkaVM factories are: - -1. Upload the contract code to the chain. -2. Note the returned code hash. -3. Deploy the Factory contract with the contract code hash. -4. Factory can now instantiate contracts using the pre-uploaded code. - -### How do gas costs compare? - -For more information on gas costs, see the [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} page. - -### Which Solidity features are not supported? - -For REVM, any Solidity feature will function smoothly without requiring changes or adaptations. For PVM, there are considerations, as was mentioned above. - -For PolkaVM, there are some considerations: - -- `EXTCODECOPY`: Only works in constructor code. -- Runtime code modification: Use on-chain constructors instead. -- **Gas stipends**: `address.send()` and `address.transfer()` don't provide reentrancy protection. -- **Unsupported operations**: `pc`, `extcodecopy`, `selfdestruct`, `blobhash`, and `blobbasefee` (blob-related operations). - -### How do I handle the existential deposit? - -Polkadot requires accounts to maintain a minimum balance (existential deposit or ED) to remain active. - -This is handled automatically for you: - -- Balance queries via Ethereum RPC automatically deduct the ED. -- New account transfers include ED in transaction fees. -- Contract-to-contract transfers draw ED from the transaction signer. - -You typically don't need to do anything special, but be aware: - -- Accounts below ED threshold are automatically deleted. -- ED is around 0.01 DOT (varies by network). -- Your contracts don't need to manage this explicitly. - -### Can I use my existing development tools? - -Yes. Both backends support: - - **Wallets**: [MetaMask](https://metamask.io/){target=\_blank}, [Talisman](https://talisman.xyz/){target=\_blank}, [SubWallet](https://www.subwallet.app/){target=\_blank} - **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} - **Libraries**: [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank}, [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank}, [viem](/smart-contracts/libraries/viem/){target=\_blank} @@ -9422,7 +8981,7 @@ Page Title: Use Hardhat with Polkadot Hub Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer. -Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit including compilation, local testing nodes, debugging tools, and deployment automation. +Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit, including compilation, local testing nodes, debugging tools, and deployment automation. ## Hardhat Workflow @@ -9466,36 +9025,11 @@ A freshly initialized Hardhat project keeps code, configuration, and automation ## Core Functionalities -### Project Setup - -Hardhat provides a structured project initialization with organized folders for contracts, tests, deployment scripts, and automation. Scaffold a workspace quickly and keep configuration in a single `hardhat.config.js` file. - -- Learn more in the [Install and Configure](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} guide. - -### Contract Compilation - -Compile your Solidity smart contracts with configurable compiler versions and optimization settings. Hardhat captures build artifacts—ABI, bytecode, metadata—so you can deploy or interact with contracts from scripts and frontends. - -- Deep dive into compilation in [Compile Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. - -### Testing Environment - -Run automated tests against a local Hardhat node, simulate transactions, and debug contract behavior before deploying to public networks. The built-in testing stack uses familiar JavaScript tooling such as Mocha and Chai. - -- Master testing capabilities in [Test Your Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. - -### Deployment - -Ship your contracts with reusable deployment scripts or Hardhat Ignition modules. Manage credentials securely, target multiple networks, and repeat deployments with confidence. - -- Follow deployment steps in [Deploy Smart Contracts](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank}. - -### Contract Interaction - -Create scripts to interact with deployed contracts, read state, execute transactions, and automate maintenance tasks using your generated ABI. - -- See practical tips in [Interact with Smart Contracts](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank}. - +- **Project structure**: Organizes contracts, tests, scripts, and configuration into a consistent workspace. Provides a clear folder layout and a single configuration file (`hardhat.config.js`) to manage compilers, networks, and tooling. +- **Compilation**: Compiles Solidity sources, supports multiple compiler versions, and generates ABI and bytecode artifacts. +- **Local testing**: Runs tests written in JavaScript or TypeScript against an integrated local network, enabling fast feedback when validating contract behavior. +- **Task automation**: Automates deployments, maintenance operations, and recurring workflows through custom scripts and Hardhat tasks. +- **Contract interaction**: Enables reading contract state, sending transactions, and calling contract functions. ## Where to Go Next diff --git a/.ai/categories/tooling.md b/.ai/categories/tooling.md index 8364c8937..7b85f85c4 100644 --- a/.ai/categories/tooling.md +++ b/.ai/categories/tooling.md @@ -10991,7 +10991,7 @@ Page Title: Use Hardhat with Polkadot Hub Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer. -Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit including compilation, local testing nodes, debugging tools, and deployment automation. +Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit, including compilation, local testing nodes, debugging tools, and deployment automation. ## Hardhat Workflow @@ -11035,36 +11035,11 @@ A freshly initialized Hardhat project keeps code, configuration, and automation ## Core Functionalities -### Project Setup - -Hardhat provides a structured project initialization with organized folders for contracts, tests, deployment scripts, and automation. Scaffold a workspace quickly and keep configuration in a single `hardhat.config.js` file. - -- Learn more in the [Install and Configure](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} guide. - -### Contract Compilation - -Compile your Solidity smart contracts with configurable compiler versions and optimization settings. Hardhat captures build artifacts—ABI, bytecode, metadata—so you can deploy or interact with contracts from scripts and frontends. - -- Deep dive into compilation in [Compile Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. - -### Testing Environment - -Run automated tests against a local Hardhat node, simulate transactions, and debug contract behavior before deploying to public networks. The built-in testing stack uses familiar JavaScript tooling such as Mocha and Chai. - -- Master testing capabilities in [Test Your Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. - -### Deployment - -Ship your contracts with reusable deployment scripts or Hardhat Ignition modules. Manage credentials securely, target multiple networks, and repeat deployments with confidence. - -- Follow deployment steps in [Deploy Smart Contracts](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank}. - -### Contract Interaction - -Create scripts to interact with deployed contracts, read state, execute transactions, and automate maintenance tasks using your generated ABI. - -- See practical tips in [Interact with Smart Contracts](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank}. - +- **Project structure**: Organizes contracts, tests, scripts, and configuration into a consistent workspace. Provides a clear folder layout and a single configuration file (`hardhat.config.js`) to manage compilers, networks, and tooling. +- **Compilation**: Compiles Solidity sources, supports multiple compiler versions, and generates ABI and bytecode artifacts. +- **Local testing**: Runs tests written in JavaScript or TypeScript against an integrated local network, enabling fast feedback when validating contract behavior. +- **Task automation**: Automates deployments, maintenance operations, and recurring workflows through custom scripts and Hardhat tasks. +- **Contract interaction**: Enables reading contract state, sending transactions, and calling contract functions. ## Where to Go Next diff --git a/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md b/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md index 08e237fa1..5b568e84e 100644 --- a/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md +++ b/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md @@ -11,7 +11,7 @@ url: https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/get-star Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer. -Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit including compilation, local testing nodes, debugging tools, and deployment automation. +Hardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit, including compilation, local testing nodes, debugging tools, and deployment automation. ## Hardhat Workflow @@ -55,36 +55,11 @@ A freshly initialized Hardhat project keeps code, configuration, and automation ## Core Functionalities -### Project Setup - -Hardhat provides a structured project initialization with organized folders for contracts, tests, deployment scripts, and automation. Scaffold a workspace quickly and keep configuration in a single `hardhat.config.js` file. - -- Learn more in the [Install and Configure](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} guide. - -### Contract Compilation - -Compile your Solidity smart contracts with configurable compiler versions and optimization settings. Hardhat captures build artifacts—ABI, bytecode, metadata—so you can deploy or interact with contracts from scripts and frontends. - -- Deep dive into compilation in [Compile Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. - -### Testing Environment - -Run automated tests against a local Hardhat node, simulate transactions, and debug contract behavior before deploying to public networks. The built-in testing stack uses familiar JavaScript tooling such as Mocha and Chai. - -- Master testing capabilities in [Test Your Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank}. - -### Deployment - -Ship your contracts with reusable deployment scripts or Hardhat Ignition modules. Manage credentials securely, target multiple networks, and repeat deployments with confidence. - -- Follow deployment steps in [Deploy Smart Contracts](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank}. - -### Contract Interaction - -Create scripts to interact with deployed contracts, read state, execute transactions, and automate maintenance tasks using your generated ABI. - -- See practical tips in [Interact with Smart Contracts](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\_blank}. - +- **Project structure**: Organizes contracts, tests, scripts, and configuration into a consistent workspace. Provides a clear folder layout and a single configuration file (`hardhat.config.js`) to manage compilers, networks, and tooling. +- **Compilation**: Compiles Solidity sources, supports multiple compiler versions, and generates ABI and bytecode artifacts. +- **Local testing**: Runs tests written in JavaScript or TypeScript against an integrated local network, enabling fast feedback when validating contract behavior. +- **Task automation**: Automates deployments, maintenance operations, and recurring workflows through custom scripts and Hardhat tasks. +- **Contract interaction**: Enables reading contract state, sending transactions, and calling contract functions. ## Where to Go Next diff --git a/.ai/pages/smart-contracts-dev-environments-local-dev-node.md b/.ai/pages/smart-contracts-dev-environments-local-dev-node.md index 63db1bf60..4944c49b5 100644 --- a/.ai/pages/smart-contracts-dev-environments-local-dev-node.md +++ b/.ai/pages/smart-contracts-dev-environments-local-dev-node.md @@ -7,8 +7,6 @@ url: https://docs.polkadot.com/smart-contracts/dev-environments/local-dev-node/ # Local Development Node -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction A local development node provides an isolated blockchain environment where you can deploy, test, and debug smart contracts without incurring network fees or waiting for block confirmations. This guide demonstrates how to set up a local Polkadot SDK-based node with smart contract capabilities. @@ -31,7 +29,6 @@ The Polkadot SDK repository contains both the [Revive Dev node](https://github.c ```bash git clone https://github.com/paritytech/polkadot-sdk.git cd polkadot-sdk -git checkout 8e2b6f742a38bb13688e12abacded0aab2dbbb23 ``` Next, you need to compile the two essential components for your development environment. The Substrate node provides the core blockchain runtime with smart contract support, while the ETH-RPC adapter enables Ethereum JSON-RPC compatibility for existing tooling: diff --git a/.ai/pages/smart-contracts-for-eth-devs-migration.md b/.ai/pages/smart-contracts-for-eth-devs-migration.md index 58c91eb15..1586dde8f 100644 --- a/.ai/pages/smart-contracts-for-eth-devs-migration.md +++ b/.ai/pages/smart-contracts-for-eth-devs-migration.md @@ -131,8 +131,8 @@ You typically don't need to do anything special, but be aware: Yes. Both backends support: - **Wallets**: [MetaMask](https://metamask.io/){target=\_blank}, [Talisman](https://talisman.xyz/){target=\_blank}, [SubWallet](https://www.subwallet.app/){target=\_blank} -- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\_blank}, [Foundry](/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/){target=\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} (just consider that for PVM bytecode, you will use the Polkadot version of the tooling) -- **Libraries**: [ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank}, [web3.js](/smart-contracts/libraries/web3-js/){target=\_blank}, [viem](/smart-contracts/libraries/viem/){target=\_blank} +- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} +- **Libraries**: [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank}, [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank}, [viem](/smart-contracts/libraries/viem/){target=\_blank} - **Testing tools**: Your existing test suites work Connect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow. diff --git a/.ai/site-index.json b/.ai/site-index.json index 0aac957f9..39d5f0a1d 100644 --- a/.ai/site-index.json +++ b/.ai/site-index.json @@ -671,28 +671,7 @@ ], "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions.md", "html_url": "https://docs.polkadot.com/chain-interactions/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-interoperability-send-messages", - "title": "Send XCM Messages", - "slug": "develop-interoperability-send-messages", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-send-messages.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/send-messages/", - "preview": "One of the core FRAME pallets that enables parachains to engage in cross-chain communication using the Cross-Consensus Message (XCM) format is [`pallet-xcm`](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm/pallet/index.html){target=\\_blank}. It facilitates the sending, execution, and management of XCM messages, thereby allowing parachains to interact with other chains within the ecosystem. Additionally, `pallet-xcm`, also referred to as the XCM pallet, supports essential operations l", + "preview": "Chain interactions form the foundation of building applications on Polkadot. Whether you're querying on-chain data, executing transactions, enabling cross-chain communication, or managing accounts, understanding how to interact with Polkadot-based chains is essential for application developers.", "outline": [ { "depth": 2, @@ -716,515 +695,436 @@ }, { "depth": 3, - "title": "Send", - "anchor": "send" + "title": "Send Cross-Chain Transactions", + "anchor": "send-cross-chain-transactions" + }, + { + "depth": 3, + "title": "Manage Tokens", + "anchor": "manage-tokens" + }, + { + "depth": 3, + "title": "Manage Accounts", + "anchor": "manage-accounts" }, { "depth": 2, - "title": "XCM Router", - "anchor": "xcm-router" + "title": "Development Tools and SDKs", + "anchor": "development-tools-and-sdks" + }, + { + "depth": 2, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 7146, - "words": 978, - "headings": 7, - "estimated_token_count_total": 1635 + "chars": 6632, + "words": 831, + "headings": 9, + "estimated_token_count_total": 1488 }, - "hash": "sha256:46252e238b0b51105148dc622da6d8809c55ec11da7ec7b2953c35ca52f5f585", + "hash": "sha256:ff1d106bd19f80de0c8108b0a658cfef83d73a4560a012ace9c842acdeefd1a5", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-test-and-debug", - "title": "Testing and Debugging", - "slug": "develop-interoperability-test-and-debug", + "id": "get-support-ai-ready-docs", + "title": "AI Ready Docs", + "slug": "get-support-ai-ready-docs", "categories": [ - "Basics", - "Polkadot Protocol" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-test-and-debug.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/test-and-debug/", - "preview": "Cross-Consensus Messaging (XCM) is a core feature of the Polkadot ecosystem, enabling communication between parachains, relay chains, and system chains. To ensure the reliability of XCM-powered blockchains, thorough testing and debugging are essential before production deployment.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-ai-ready-docs.md", + "html_url": "https://docs.polkadot.com/get-support/ai-ready-docs/", + "preview": "Polkadot provides files to make documentation content available in a structure optimized for use with large language models (LLMs) and AI tools. These resources help build AI assistants, power code search, or enable custom tooling trained on Polkadot’s documentation.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "How to Use These Files", + "anchor": "how-to-use-these-files" }, { "depth": 2, - "title": "XCM Emulator", - "anchor": "xcm-emulator" - }, - { - "depth": 3, - "title": "Manage Tokens", - "anchor": "manage-tokens" - }, - { - "depth": 3, - "title": "How Does It Work?", - "anchor": "how-does-it-work" + "title": "Download LLM Files", + "anchor": "download-llm-files" } ], "stats": { - "chars": 7750, - "words": 838, - "headings": 4, - "estimated_token_count_total": 1491 + "chars": 7998, + "words": 825, + "headings": 2, + "estimated_token_count_total": 2232 }, - "hash": "sha256:db37b2f5888f283b5eb5bd84a5f8c81fc66b2313e3f94f510a73dfeb310ae3f0", + "hash": "sha256:5a8da69a5cea8bd598ee4d102b9abed5d1a29153802a567e22bb4ee720410b32", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-versions-v5-asset-claimer", - "title": "Asset claimer", - "slug": "develop-interoperability-versions-v5-asset-claimer", + "id": "get-support-explore-resources", + "title": "Subscribe to Updates", + "slug": "get-support-explore-resources", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-asset-claimer.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/asset-claimer/", - "preview": "XCMv5 introduces the [`AssetClaimer`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Hint.html#variant.AssetClaimer){target=\\_blank} execution hint through [`SetHints`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Instruction.html#variant.SetHints){target=\\_blank}, which significantly simplifies the process of recovering trapped assets when XCM execution fails.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md", + "html_url": "https://docs.polkadot.com/get-support/explore-resources/", + "preview": "Looking for answers beyond the documentation? These platforms are full of useful content and experienced developers sharing insights.", "outline": [ { "depth": 2, - "title": "The problem before v5", - "anchor": "the-problem-before-v5" + "title": "🧠 Stack Exchange", + "anchor": "stack-exchange" }, { "depth": 2, - "title": "The V5 Solution: `AssetClaimer` Hint", - "anchor": "the-v5-solution-assetclaimer-hint" + "title": "🧵 Reddit: r/Polkadot", + "anchor": "reddit-rpolkadot" }, { "depth": 2, - "title": "How it Improves the Situation", - "anchor": "how-it-improves-the-situation" + "title": "💬 Discord (Community Threads Only)", + "anchor": "discord-community-threads-only" }, { "depth": 2, - "title": "Key Improvements", - "anchor": "key-improvements" + "title": "🎥 YouTube: @PolkadotNetwork", + "anchor": "youtube-polkadotnetwork" }, { "depth": 2, - "title": "Best Practices", - "anchor": "best-practices" + "title": "Community-Led Platforms and Ecosystem Updates", + "anchor": "community-led-platforms-and-ecosystem-updates" + }, + { + "depth": 3, + "title": "🔷 X (Twitter): Official Accounts", + "anchor": "x-twitter-official-accounts" }, { "depth": 3, - "title": "Set Hint Early", - "anchor": "set-hint-early" + "title": "🔁 X (Twitter): Community Accounts", + "anchor": "x-twitter-community-accounts" }, { "depth": 3, - "title": "Use for Cross-Chain Transfers", - "anchor": "use-for-cross-chain-transfers" + "title": "🗣️ Polkadot Forum", + "anchor": "polkadot-forum" }, { "depth": 3, - "title": "Consider Origin Preservation", - "anchor": "consider-origin-preservation" + "title": "🧑‍⚖️ Polkassembly: OpenGov", + "anchor": "polkassembly-opengov" }, { - "depth": 2, - "title": "Migration Impact", - "anchor": "migration-impact" + "depth": 3, + "title": "📸 Instagram", + "anchor": "instagram" } ], "stats": { - "chars": 5080, - "words": 582, - "headings": 9, - "estimated_token_count_total": 955 + "chars": 2426, + "words": 295, + "headings": 10, + "estimated_token_count_total": 579 }, - "hash": "sha256:72ee7394fd1308c111a8d548cb4dc63c6b9bc5b6e2bb556dd1baacbaedb92286", + "hash": "sha256:670221ac20ab1f1b550ba2a1db06cd924c24bd3afc4d8a768b617d8a409243cb", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-versions-v5-fees", - "title": "Fees", - "slug": "develop-interoperability-versions-v5-fees", + "id": "get-support-get-in-touch", + "title": "Get in Touch", + "slug": "get-support-get-in-touch", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-fees.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/fees/", - "preview": "XCM V5 introduces a new fee payment mechanism that simplifies and unifies the handling of fees across various XCM operations.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-get-in-touch.md", + "html_url": "https://docs.polkadot.com/get-support/get-in-touch/", + "preview": "Use one of the channels below to get live technical support or ask questions.", "outline": [ { "depth": 2, - "title": "Key Changes from V4", - "anchor": "key-changes-from-v4" - }, - { - "depth": 3, - "title": "BuyExecution vs. PayFees", - "anchor": "buyexecution-vs-payfees" - }, - { - "depth": 3, - "title": "PayFees Instruction", - "anchor": "payfees-instruction" + "title": "Need Help Fast?", + "anchor": "need-help-fast" }, { "depth": 2, - "title": "Backward Compatibility", - "anchor": "backward-compatibility" + "title": "📱 Telegram: Polkadot Developer Support", + "anchor": "telegram-polkadot-developer-support" }, { "depth": 2, - "title": "Migration Considerations", - "anchor": "migration-considerations" + "title": "🔌 Discord: Polkadot Official Server", + "anchor": "discord-polkadot-official-server" }, { "depth": 2, - "title": "`RefundSurplus` Instruction", - "anchor": "refundsurplus-instruction" + "title": "🧬 Matrix: Polkadot Developer Support", + "anchor": "matrix-polkadot-developer-support" } ], "stats": { - "chars": 4145, - "words": 531, - "headings": 6, - "estimated_token_count_total": 876 + "chars": 1949, + "words": 258, + "headings": 4, + "estimated_token_count_total": 557 }, - "hash": "sha256:d6cb22337280a19bdf24981dcba98f337d48ee4f79ce7ac040466ef1cb4b330b", + "hash": "sha256:993e93b05c8fbdfc2f7510c61ac86bc4c2ff0f03e573695b2f260933c8b62f78", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-versions-v5-migration-guide", - "title": "Migration Guide (XCM V4 → XCM V5)", - "slug": "develop-interoperability-versions-v5-migration-guide", + "id": "get-support", + "title": "Support", + "slug": "get-support", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-migration-guide.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/migration-guide/", - "preview": "This guide helps migrate existing code that uses XCM from XCM V4 to XCM V5. Most XCM V4 code continues to work, but XCM V5 introduces powerful new patterns that improve flexibility and developer experience.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support.md", + "html_url": "https://docs.polkadot.com/get-support/", + "preview": "Use one of the channels below to get live technical support or ask questions.", "outline": [ { "depth": 2, - "title": "When to migrate", - "anchor": "when-to-migrate" - }, - { - "depth": 2, - "title": "Key Changes", - "anchor": "key-changes" - }, - { - "depth": 3, - "title": "From Dedicated Extrinsics to Raw XCMs", - "anchor": "from-dedicated-extrinsics-to-raw-xcms" - }, - { - "depth": 3, - "title": "Unified Transfer Instructions", - "anchor": "unified-transfer-instructions" - }, - { - "depth": 3, - "title": "Predictable fee payment", - "anchor": "predictable-fee-payment" - }, - { - "depth": 2, - "title": "Migration Examples", - "anchor": "migration-examples" - }, - { - "depth": 3, - "title": "Simple Teleport", - "anchor": "simple-teleport" - }, - { - "depth": 3, - "title": "Example 2: Multi-Asset Transfer and a Transact", - "anchor": "example-2-multi-asset-transfer-and-a-transact" + "title": "Need More than Just Documentation?", + "anchor": "need-more-than-just-documentation" }, { "depth": 2, - "title": "Breaking Changes to Watch Out For", - "anchor": "breaking-changes-to-watch-out-for" - }, - { - "depth": 3, - "title": "`fallback_max_weight` in `Transact`", - "anchor": "fallback_max_weight-in-transact" - }, - { - "depth": 3, - "title": "Network IDs Cleanup", - "anchor": "network-ids-cleanup" + "title": "What You Can Do Here", + "anchor": "what-you-can-do-here" }, { "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" + "title": "Help Us Improve", + "anchor": "help-us-improve" } ], "stats": { - "chars": 13459, - "words": 1562, - "headings": 12, - "estimated_token_count_total": 2744 + "chars": 1658, + "words": 244, + "headings": 3, + "estimated_token_count_total": 280 }, - "hash": "sha256:1a2d34ccab19bd71263763bbc294977acf34f5800398f51398753594cfc7d7a6", + "hash": "sha256:5bdc575ac798a971867a15651c2b4d5139bf0b1fe6854d1865deff280ae6d7f6", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-versions-v5-transact", - "title": "Transact", - "slug": "develop-interoperability-versions-v5-transact", + "id": "index", + "title": "Polkadot Developer Docs", + "slug": "index", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-transact.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/transact/", - "preview": "XCM V5 improves the [`Transact`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Instruction.html#variant.Transact){target=\\_blank} instruction by introducing optional weight specification through the `fallback_max_weight` parameter, making cross-chain calls more flexible and reliable.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/index.md", + "html_url": "https://docs.polkadot.com/index/", + "preview": "Explore everything you need to start building on top of Polkadot, a protocol that provides parachains with shared security and interoperability using XCM.", + "outline": [], + "stats": { + "chars": 0, + "words": 0, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-node-bootnode", + "title": "Set Up a Bootnode", + "slug": "nodes-and-validators-run-a-node-bootnode", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-bootnode.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/bootnode/", + "preview": "Bootnodes are essential for helping blockchain nodes discover peers and join the network. When a node starts, it needs to find other nodes, and bootnodes provide an initial point of contact. Once connected, a node can expand its peer connections and play its role in the network, like participating as a validator.", "outline": [ { "depth": 2, - "title": "Changes from V4", - "anchor": "changes-from-v4" + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Weight Parameter Evolution", - "anchor": "weight-parameter-evolution" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "The `fallback_max_weight` Parameter", - "anchor": "the-fallback_max_weight-parameter" + "title": "Accessing the Bootnode", + "anchor": "accessing-the-bootnode" }, { - "depth": 3, - "title": "When to Use `undefined`", - "anchor": "when-to-use-undefined" + "depth": 2, + "title": "Node Key", + "anchor": "node-key" }, { - "depth": 3, - "title": "When to Specify Weight", - "anchor": "when-to-specify-weight" + "depth": 2, + "title": "Running the Bootnode", + "anchor": "running-the-bootnode" }, { "depth": 2, - "title": "Benefits of the New Approach", - "anchor": "benefits-of-the-new-approach" + "title": "Testing Bootnode Connection", + "anchor": "testing-bootnode-connection" }, { "depth": 3, - "title": "Problems Solved", - "anchor": "problems-solved" + "title": "P2P", + "anchor": "p2p" }, { "depth": 3, - "title": "XCM V5 Improvements", - "anchor": "xcm-v5-improvements" - }, - { - "depth": 2, - "title": "Migration Strategy", - "anchor": "migration-strategy" + "title": "P2P/WS", + "anchor": "p2pws" }, { - "depth": 2, - "title": "Fee Implications", - "anchor": "fee-implications" + "depth": 3, + "title": "P2P/WSS", + "anchor": "p2pwss" } ], "stats": { - "chars": 3637, - "words": 370, - "headings": 10, - "estimated_token_count_total": 608 + "chars": 4538, + "words": 647, + "headings": 9, + "estimated_token_count_total": 1044 }, - "hash": "sha256:7bba6105d99721373aa6f494627d20af97b1851c19703f26be26c32f0c83524b", + "hash": "sha256:d84a5af1a0237a911d25a68c077f508ebbce608f673ef4f9055e8e434daa96b9", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-versions-v5-transfers", - "title": "Transfers", - "slug": "develop-interoperability-versions-v5-transfers", + "id": "nodes-and-validators-run-a-node-full-node", + "title": "Set Up a Node", + "slug": "nodes-and-validators-run-a-node-full-node", "categories": [ - "Uncategorized" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-transfers.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/transfers/", - "preview": "XCM V5 introduces the unified [`InitiateTransfer`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Instruction.html#variant.InitiateTransfer){target=\\_blank} instruction that consolidates and enhances cross-chain transfer capabilities.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-full-node.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/full-node/", + "preview": "Running a node on Polkadot provides direct interaction with the network, enhanced privacy, and full control over RPC requests, transactions, and data queries. As the backbone of the network, nodes ensure decentralized data propagation, transaction validation, and seamless communication across the ecosystem.", "outline": [ { "depth": 2, - "title": "Changes from v4", - "anchor": "changes-from-v4" - }, - { - "depth": 3, - "title": "Instruction Consolidation", - "anchor": "instruction-consolidation" - }, - { - "depth": 3, - "title": "Enhanced Transfer Specification", - "anchor": "enhanced-transfer-specification" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Key Enhancements", - "anchor": "key-enhancements" + "title": "Set Up a Node", + "anchor": "set-up-a-node" }, { "depth": 3, - "title": "Mixed Transfer Types", - "anchor": "mixed-transfer-types" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 3, - "title": "Origin Preservation", - "anchor": "origin-preservation" + "title": "Install and Build the Polkadot Binary", + "anchor": "install-and-build-the-polkadot-binary" }, { "depth": 3, - "title": "Integrated Fee Handling", - "anchor": "integrated-fee-handling" + "title": "Use Docker", + "anchor": "use-docker" }, { "depth": 2, - "title": "Backward Compatibility", - "anchor": "backward-compatibility" + "title": "Configure and Run Your Node", + "anchor": "configure-and-run-your-node" + }, + { + "depth": 3, + "title": "RPC Configurations", + "anchor": "rpc-configurations" }, { "depth": 2, - "title": "Migration Benefits", - "anchor": "migration-benefits" + "title": "Sync Your Node", + "anchor": "sync-your-node" + }, + { + "depth": 3, + "title": "Connect to Your Node", + "anchor": "connect-to-your-node" } ], "stats": { - "chars": 3243, - "words": 336, + "chars": 15944, + "words": 2481, "headings": 9, - "estimated_token_count_total": 1488 + "estimated_token_count_total": 4196 }, - "hash": "sha256:b79fe56c9604712825bdf30d17667fd8f237fce9691be0d8d042d38691dbba7a", + "hash": "sha256:924fab837818610c825be5cefde0a7bacd46985b4fa05cfa0376a941105b9869", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-versions-v5-writing-xcm-programs", - "title": "Writing XCM Programs", - "slug": "develop-interoperability-versions-v5-writing-xcm-programs", + "id": "nodes-and-validators-run-a-node-secure-wss", + "title": "Set Up Secure WebSocket", + "slug": "nodes-and-validators-run-a-node-secure-wss", "categories": [ - "Uncategorized" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5-writing-xcm-programs.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/writing-xcm-programs/", - "preview": "XCM V5 shifts the recommended approach from using dedicated extrinsics to executing raw XCM programs directly.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-secure-wss.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/secure-wss/", + "preview": "Ensuring secure WebSocket communication is crucial for maintaining the integrity and security of a Polkadot or Kusama node when interacting with remote clients. This guide walks you through setting up a secure WebSocket (WSS) connection for your node by leveraging SSL encryption with popular web server proxies like nginx or Apache.", "outline": [ { "depth": 2, - "title": "The Paradigm Shift", - "anchor": "the-paradigm-shift" + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Previous Approach", - "anchor": "previous-approach" + "depth": 2, + "title": "Secure a WebSocket Port", + "anchor": "secure-a-websocket-port" }, { "depth": 3, - "title": "XCM V5 Recommendation", - "anchor": "xcm-v5-recommendation" + "title": "Obtain an SSL Certificate", + "anchor": "obtain-an-ssl-certificate" }, { "depth": 2, - "title": "Execution Approach", - "anchor": "execution-approach" + "title": "Install a Proxy Server", + "anchor": "install-a-proxy-server" }, { - "depth": 2, - "title": "Benefits of Direct Execution", - "anchor": "benefits-of-direct-execution" + "depth": 3, + "title": "Use nginx", + "anchor": "use-nginx" }, { - "depth": 2, - "title": "Migration Considerations", - "anchor": "migration-considerations" - } - ], - "stats": { - "chars": 1830, - "words": 215, - "headings": 6, - "estimated_token_count_total": 348 - }, - "hash": "sha256:11cd8d428fa9c3e70490da5c63ce4597cd89ec46306d2bb49b016ced6aa68c3d", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-interoperability-versions-v5", - "title": "XCMv5", - "slug": "develop-interoperability-versions-v5", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions-v5.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/versions/v5/", - "preview": "The latest iteration of XCM is version 5. The main RFCs defining the changes in version 5 are the following:", - "outline": [ - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 2970, - "words": 438, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:3821c2ef97699091b76e1de58e6d95e866df69d39fca16f2a15c156b71da5b22", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-interoperability-versions", - "title": "XCM Versions", - "slug": "develop-interoperability-versions", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-versions.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/versions/", - "preview": "XCM is a versioned language that evolves to meet the growing needs of cross-chain communication in the Polkadot ecosystem. Understanding XCM versioning is essential for developers building interoperable applications to keep up with the latest improvements.", - "outline": [ + "depth": 3, + "title": "Use Apache2", + "anchor": "use-apache2" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Connect to the Node", + "anchor": "connect-to-the-node" } ], "stats": { - "chars": 835, - "words": 114, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 5568, + "words": 774, + "headings": 7, + "estimated_token_count_total": 1280 }, - "hash": "sha256:634e299f347beb8ad690697943bb7f99915d62d40cda4227179619ed18abe2ff", + "hash": "sha256:992082e4ad87348b283f6c37ea886ae0e7bf016852b6470000876f3d169c65a4", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-xcm-channels", - "title": "XCM Channels", - "slug": "develop-interoperability-xcm-channels", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", + "title": "Validator Key Management", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", "categories": [ - "Basics", - "Polkadot Protocol" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-channels.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-channels/", - "preview": "Polkadot is designed to enable interoperability between its connected parachains. At the core of this interoperability is the [Cross-Consensus Message Format (XCM)](/parachains/interoperability/get-started/){target=\\_blank}, a standard language that allows parachains to communicate and interact with each other.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/", + "preview": "After setting up your node environment as shown in the [Setup](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/){target=\\_blank} section, you'll need to configure multiple keys for your validator to operate properly. This includes setting up session keys, which are essential for participating in the consensus process, and configuring a node key that maintains a stable network identity. This guide walks you through the key management process, showing you how to g", "outline": [ { "depth": 2, @@ -1233,45 +1133,59 @@ }, { "depth": 2, - "title": "Establishing HRMP Channels", - "anchor": "establishing-hrmp-channels" + "title": "Set Session Keys", + "anchor": "set-session-keys" + }, + { + "depth": 3, + "title": "Generate Session Keys", + "anchor": "generate-session-keys" }, { "depth": 3, - "title": "Relay Chain Parameters", - "anchor": "relay-chain-parameters" + "title": "Submit Transaction to Set Keys", + "anchor": "submit-transaction-to-set-keys" }, { "depth": 3, - "title": "Dispatching Extrinsics", - "anchor": "dispatching-extrinsics" + "title": "Verify Session Key Setup", + "anchor": "verify-session-key-setup" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Set the Node Key", + "anchor": "set-the-node-key" + }, + { + "depth": 3, + "title": "Generate the Node Key", + "anchor": "generate-the-node-key" + }, + { + "depth": 3, + "title": "Set Node Key", + "anchor": "set-node-key" } ], "stats": { - "chars": 6422, - "words": 870, - "headings": 5, - "estimated_token_count_total": 1365 + "chars": 8227, + "words": 1183, + "headings": 8, + "estimated_token_count_total": 1840 }, - "hash": "sha256:5f8fa89fc725c5c559975012fe2f9ae92c3b62f10024b5688dcd118331118f1a", + "hash": "sha256:0fb5a83835aab263c0b9aa886028c8aa8a2d6d0897d7b9fff4b5258835d30dfe", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-xcm-config", - "title": "XCM Config", - "slug": "develop-interoperability-xcm-config", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", + "title": "Set Up a Validator", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", "categories": [ - "Reference", - "Polkadot Protocol" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-config.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-config/", - "preview": "The [XCM executor](https://paritytech.github.io/polkadot-sdk/master/staging_xcm_executor/index.html){target=\\_blank} is a crucial component responsible for interpreting and executing XCM messages (XCMs) with Polkadot SDK-based chains. It processes and manages XCM instructions, ensuring they are executed correctly and in sequentially. Adhering to the [Cross-Consensus Virtual Machine (XCVM) specification](https://paritytech.github.io/xcm-docs/overview/xcvm.html#the-xcvm){target=\\_blank}, the XCM e", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/", + "preview": "Setting up a Polkadot validator node is essential for securing the network and earning staking rewards. This guide walks you through the technical steps to set up a validator, from installing the necessary software to managing keys and synchronizing your node with the chain.", "outline": [ { "depth": 2, @@ -1280,105 +1194,79 @@ }, { "depth": 2, - "title": "XCM Executor Configuration", - "anchor": "xcm-executor-configuration" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Config Items", - "anchor": "config-items" + "title": "Initial Setup", + "anchor": "initial-setup" }, { "depth": 3, - "title": "Inner Config", - "anchor": "inner-config" + "title": "Install Network Time Protocol Client", + "anchor": "install-network-time-protocol-client" }, { "depth": 3, - "title": "Outer Config", - "anchor": "outer-config" + "title": "Verify Landlock is Activated", + "anchor": "verify-landlock-is-activated" }, { "depth": 2, - "title": "Multiple Implementations", - "anchor": "multiple-implementations" - } - ], - "stats": { - "chars": 21710, - "words": 2458, - "headings": 6, - "estimated_token_count_total": 4979 - }, - "hash": "sha256:ed3b7c8101b69f9c907cca7c5edfef67fdb5e7bc3c8df8d9fbad297f9dd3c80a", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-interoperability-xcm-guides-from-apps-claiming-trapped-assets", - "title": "Claiming Trapped Assets", - "slug": "develop-interoperability-xcm-guides-from-apps-claiming-trapped-assets", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps-claiming-trapped-assets.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/claiming-trapped-assets/", - "preview": "When XCM execution fails or succeeds, leftover assets can become \"trapped\" on the destination chain. These assets are held by the system but are not accessible through normal means. XCM provides mechanisms to claim these trapped assets and recover them. This guide details the process and required steps to claim trapped assets.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Install the Polkadot Binaries", + "anchor": "install-the-polkadot-binaries" }, { - "depth": 2, - "title": "Trapped Assets Causes", - "anchor": "trapped-assets-causes" + "depth": 3, + "title": "Install from Official Releases", + "anchor": "install-from-official-releases" }, { - "depth": 2, - "title": "The `ClaimAsset` Instruction", - "anchor": "the-claimasset-instruction" + "depth": 3, + "title": "Install with Package Managers", + "anchor": "install-with-package-managers" }, { "depth": 3, - "title": "Parameters", - "anchor": "parameters" + "title": "Install with Ansible", + "anchor": "install-with-ansible" }, { "depth": 3, - "title": "Basic Claiming Process", - "anchor": "basic-claiming-process" + "title": "Install with Docker", + "anchor": "install-with-docker" }, { - "depth": 2, - "title": "The `AssetClaimer` Hint", - "anchor": "the-assetclaimer-hint" + "depth": 3, + "title": "Build from Sources", + "anchor": "build-from-sources" }, { "depth": 2, - "title": "Best practices", - "anchor": "best-practices" + "title": "Verify Installation", + "anchor": "verify-installation" } ], "stats": { - "chars": 8821, - "words": 958, - "headings": 7, - "estimated_token_count_total": 1781 + "chars": 11921, + "words": 1678, + "headings": 12, + "estimated_token_count_total": 2592 }, - "hash": "sha256:35c71a215558cd0642d363e4515ad240093995d42720e6495cd2994c859243e4", + "hash": "sha256:d2c1c91734bc8185057d8eeec6829ea91e0316f7ba884c5dc3922a5e5778815e", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-xcm-guides-from-apps-fees", - "title": "Fees", - "slug": "develop-interoperability-xcm-guides-from-apps-fees", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", + "title": "Start Validating", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", "categories": [ - "Uncategorized" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps-fees.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/fees/", - "preview": "In blockchain systems, fees are crucial. They prevent malicious actors from exhausting the results of the network, making such attacks expensive. The XCM subsystem has its own way of dealing with fees, flexible enough to allow feeless execution in situations that warrant it.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/start-validating/", + "preview": "After configuring your node keys as shown in the [Key Management](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/){target=\\_blank} section and ensuring your system is set up, you're ready to begin the validator setup process. This guide will walk you through choosing a network, synchronizing your node with the blockchain, bonding your DOT tokens, and starting your validator.", "outline": [ { "depth": 2, @@ -1387,90 +1275,84 @@ }, { "depth": 2, - "title": "Execution", - "anchor": "execution" + "title": "Choose a Network", + "anchor": "choose-a-network" }, { "depth": 2, - "title": "Delivery", - "anchor": "delivery" + "title": "Synchronize Chain Data", + "anchor": "synchronize-chain-data" }, { - "depth": 2, - "title": "PayFees", - "anchor": "payfees" + "depth": 3, + "title": "Database Snapshot Services", + "anchor": "database-snapshot-services" }, { "depth": 2, - "title": "Estimations", - "anchor": "estimations" - } - ], - "stats": { - "chars": 6291, - "words": 925, - "headings": 5, - "estimated_token_count_total": 1447 - }, - "hash": "sha256:0e39aee80fbcf3dfaa19133f31d664914ed45b42a1a929270f05d8ae876b89e2", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-interoperability-xcm-guides-from-apps-transact", - "title": "Transact", - "slug": "develop-interoperability-xcm-guides-from-apps-transact", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps-transact.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/transact/", - "preview": "The [`Transact`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/opaque/type.Instruction.html#variant.Transact){target=\\_blank} instruction enables arbitrary cross-chain execution of pallet calls or smart contract functions. It's one of the most powerful XCM instructions because it allows you to perform any operation that would normally be done locally on a remote chain. However, it requires knowing the implementation details of the destination chain.", - "outline": [ + "title": "Bond DOT", + "anchor": "bond-dot" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Bonding DOT on Polkadot.js Apps", + "anchor": "bonding-dot-on-polkadotjs-apps" }, { "depth": 2, - "title": "Chain-Specific Knowledge Required", - "anchor": "chain-specific-knowledge-required" + "title": "Validate", + "anchor": "validate" + }, + { + "depth": 3, + "title": "Verify Sync via Telemetry", + "anchor": "verify-sync-via-telemetry" }, { "depth": 3, - "title": "Required Knowledge", - "anchor": "required-knowledge" + "title": "Activate using Polkadot.js Apps", + "anchor": "activate-using-polkadotjs-apps" }, { "depth": 3, - "title": "Examples of Chain-Specific Requirements", - "anchor": "examples-of-chain-specific-requirements" + "title": "Monitor Validation Status and Slots", + "anchor": "monitor-validation-status-and-slots" }, { "depth": 2, - "title": "Origin Considerations", - "anchor": "origin-considerations" + "title": "Run a Validator Using Systemd", + "anchor": "run-a-validator-using-systemd" + }, + { + "depth": 3, + "title": "Create the Systemd Service File", + "anchor": "create-the-systemd-service-file" + }, + { + "depth": 3, + "title": "Run the Service", + "anchor": "run-the-service" } ], "stats": { - "chars": 4444, - "words": 562, - "headings": 5, - "estimated_token_count_total": 1082 + "chars": 15820, + "words": 2446, + "headings": 13, + "estimated_token_count_total": 3861 }, - "hash": "sha256:ec82957c768c2c07a272e7a28659c812b223df836e21372b1642f0bb249d7b39", + "hash": "sha256:67a43e787805244196e1e9cb962069292c69ed5fdb1110df57c942019892b953", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-xcm-guides-from-apps-transfers", - "title": "Transfers", - "slug": "develop-interoperability-xcm-guides-from-apps-transfers", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", + "title": "Stop Validating", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", "categories": [ - "Uncategorized" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps-transfers.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/transfers/", - "preview": "The [`InitiateTransfer`](https://paritytech.github.io/polkadot-sdk/master/staging_xcm/v5/enum.Instruction.html#variant.InitiateTransfer){target=\\_blank} instruction is the primary mechanism for cross-chain transfers in XCM. It provides a unified interface for different types of transfers and brings additional functionalities not possible with previous instruction versions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/", + "preview": "If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability.", "outline": [ { "depth": 2, @@ -1479,97 +1361,44 @@ }, { "depth": 2, - "title": "Transfer Types", - "anchor": "transfer-types" - }, - { - "depth": 2, - "title": "Remote Fees", - "anchor": "remote-fees" + "title": "Pause Versus Stop", + "anchor": "pause-versus-stop" }, { "depth": 2, - "title": "Origin Preservation", - "anchor": "origin-preservation" - } - ], - "stats": { - "chars": 20264, - "words": 2291, - "headings": 4, - "estimated_token_count_total": 4178 - }, - "hash": "sha256:d480791a76082937b47c77f7cf3794e701f193452ed347fcb1c04c3c67577bf5", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-interoperability-xcm-guides-from-apps", - "title": "From Apps", - "slug": "develop-interoperability-xcm-guides-from-apps", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides-from-apps.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/from-apps/", - "preview": "This section shows how to interact with XCM from applications, providing practical guidance for implementing cross-chain functionality in your dApps and services.", - "outline": [ - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 511, - "words": 70, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:63584f5b1dab7b67b18b35b47dfc19d00ad5c013804772f0d653a11ac3fca38d", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-interoperability-xcm-guides", - "title": "XCM Guides", - "slug": "develop-interoperability-xcm-guides", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-guides.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-guides/", - "preview": "This section provides comprehensive guides for implementing XCM functionality, including application development patterns, fee management, asset transfers, and cross-chain transaction handling.", - "outline": [ + "title": "Chill Validator", + "anchor": "chill-validator" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Purge Validator Session Keys", + "anchor": "purge-validator-session-keys" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Unbond Your Tokens", + "anchor": "unbond-your-tokens" } ], "stats": { - "chars": 1663, - "words": 215, - "headings": 2, - "estimated_token_count_total": 340 + "chars": 3230, + "words": 500, + "headings": 5, + "estimated_token_count_total": 629 }, - "hash": "sha256:d4c2d7fd46ddf60f638f948c88ba3940de6d69f140923ba8df52ed787b0afede", + "hash": "sha256:0d6db361bfa7a3022849bbe39989bfdac0429537498d7f534adadec131afca98", "token_estimator": "heuristic-v1" }, { - "id": "develop-interoperability-xcm-runtime-apis", - "title": "XCM Runtime APIs", - "slug": "develop-interoperability-xcm-runtime-apis", + "id": "nodes-and-validators-run-a-validator-operational-tasks-general-management", + "title": "General Management", + "slug": "nodes-and-validators-run-a-validator-operational-tasks-general-management", "categories": [ - "Reference", - "Polkadot Protocol" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability-xcm-runtime-apis.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/xcm-runtime-apis/", - "preview": "Runtime APIs allow node-side code to extract information from the runtime state. While simple storage access retrieves stored values directly, runtime APIs enable arbitrary computation, making them a powerful tool for interacting with the chain's state.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-general-management.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/general-management/", + "preview": "Validator performance is pivotal in maintaining the security and stability of the Polkadot network. As a validator, optimizing your setup ensures efficient transaction processing, minimizes latency, and maintains system reliability during high-demand periods. Proper configuration and proactive monitoring also help mitigate risks like slashing and service interruptions.", "outline": [ { "depth": 2, @@ -1578,131 +1407,83 @@ }, { "depth": 2, - "title": "Dry Run API", - "anchor": "dry-run-api" + "title": "Configuration Optimization", + "anchor": "configuration-optimization" + }, + { + "depth": 3, + "title": "Deactivate Simultaneous Multithreading", + "anchor": "deactivate-simultaneous-multithreading" }, { "depth": 3, - "title": "Dry Run Call", - "anchor": "dry-run-call" + "title": "Deactivate Automatic NUMA Balancing", + "anchor": "deactivate-automatic-numa-balancing" }, { "depth": 3, - "title": "Dry Run XCM", - "anchor": "dry-run-xcm" + "title": "Spectre and Meltdown Mitigations", + "anchor": "spectre-and-meltdown-mitigations" }, { "depth": 2, - "title": "XCM Payment API", - "anchor": "xcm-payment-api" + "title": "Monitor Your Node", + "anchor": "monitor-your-node" }, { "depth": 3, - "title": "Query Acceptable Payment Assets", - "anchor": "query-acceptable-payment-assets" + "title": "Environment Setup", + "anchor": "environment-setup" }, { "depth": 3, - "title": "Query XCM Weight", - "anchor": "query-xcm-weight" + "title": "Install and Configure Prometheus", + "anchor": "install-and-configure-prometheus" }, { "depth": 3, - "title": "Query Weight to Asset Fee", - "anchor": "query-weight-to-asset-fee" + "title": "Start Prometheus", + "anchor": "start-prometheus" }, { "depth": 3, - "title": "Query Delivery Fees", - "anchor": "query-delivery-fees" - } - ], - "stats": { - "chars": 33176, - "words": 3163, - "headings": 9, - "estimated_token_count_total": 6510 - }, - "hash": "sha256:353ad782303ef79bce1262bfa945e6f11b3c3c9ca1edf5705b778c46bada6200", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-interoperability", - "title": "Interoperability", - "slug": "develop-interoperability", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-interoperability.md", - "html_url": "https://docs.polkadot.com/develop/interoperability/", - "preview": "This section covers everything you need to know about building and implementing [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\\_blank} solutions in the Polkadot ecosystem. Whether you're working on establishing cross-chain channels, sending and receiving XCM messages, or testing and debugging your cross-chain configurations, you'll find the essential resources and tools here to support your interoperability needs, regardless of your development focus.", - "outline": [ - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Install and Configure Grafana", + "anchor": "install-and-configure-grafana" }, { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 2363, - "words": 323, - "headings": 2, - "estimated_token_count_total": 402 - }, - "hash": "sha256:5da6bdeec1deee5ef3d7ab1a43f546067bcef91acdc67df4ce114ee8f8669e82", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-networks", - "title": "Networks", - "slug": "develop-networks", - "categories": [ - "Basics", - "Networks" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-networks.md", - "html_url": "https://docs.polkadot.com/develop/networks/", - "preview": "The Polkadot ecosystem consists of multiple networks designed to support different stages of blockchain development, from main networks to test networks. Each network serves a unique purpose, providing developers with flexible environments for building, testing, and deploying blockchain applications.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Install and Configure Alertmanager", + "anchor": "install-and-configure-alertmanager" }, { "depth": 2, - "title": "Production Networks", - "anchor": "production-networks" + "title": "Secure Your Validator", + "anchor": "secure-your-validator" }, { "depth": 3, - "title": "Polkadot", - "anchor": "polkadot" + "title": "Key Management", + "anchor": "key-management" }, { "depth": 3, - "title": "Kusama", - "anchor": "kusama" + "title": "Signing Outside the Client", + "anchor": "signing-outside-the-client" }, { - "depth": 2, - "title": "Test Networks", - "anchor": "test-networks" + "depth": 3, + "title": "Secure-Validator Mode", + "anchor": "secure-validator-mode" }, { "depth": 3, - "title": "Westend", - "anchor": "westend" + "title": "Linux Best Practices", + "anchor": "linux-best-practices" }, { "depth": 3, - "title": "Paseo", - "anchor": "paseo" + "title": "Validator Best Practices", + "anchor": "validator-best-practices" }, { "depth": 2, @@ -1711,25 +1492,24 @@ } ], "stats": { - "chars": 6097, - "words": 664, - "headings": 8, - "estimated_token_count_total": 1520 + "chars": 26673, + "words": 3357, + "headings": 18, + "estimated_token_count_total": 5866 }, - "hash": "sha256:ed09ef7a6abe21204006186fd5791ada7597688fad67e30244dc449c51330309", + "hash": "sha256:81eb0fe77f05155f1ec0511cd066120fc9994961e9d91e21b6666377e65b4586", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-customize-parachain-overview", - "title": "Overview of FRAME", - "slug": "develop-parachains-customize-parachain-overview", + "id": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", + "title": "Pause Validating", + "slug": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", "categories": [ - "Basics", - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain-overview.md", - "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/overview/", - "preview": "The runtime is the heart of any Polkadot SDK-based blockchain, handling the essential logic that governs state changes and transaction processing. With Polkadot SDK’s [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_bank}, developers gain access to a powerful suite of tools for building custom blockchain runtimes. FRAME offers a modular architecture, featuring reusable pallets and su", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-pause-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/", + "preview": "If you need to temporarily stop participating in Polkadot staking activities without fully unbonding your funds, chilling your account allows you to do so efficiently. Chilling removes your node from active validation or nomination in the next era while keeping your funds bonded, making it ideal for planned downtimes or temporary pauses.", "outline": [ { "depth": 2, @@ -1738,95 +1518,49 @@ }, { "depth": 2, - "title": "FRAME Runtime Architecture", - "anchor": "frame-runtime-architecture" - }, - { - "depth": 3, - "title": "Pallets", - "anchor": "pallets" - }, - { - "depth": 3, - "title": "Support Libraries", - "anchor": "support-libraries" + "title": "Chilling Your Node", + "anchor": "chilling-your-node" }, { "depth": 2, - "title": "Compose a Runtime with Pallets", - "anchor": "compose-a-runtime-with-pallets" + "title": "Staking Election Timing Considerations", + "anchor": "staking-election-timing-considerations" }, { "depth": 2, - "title": "Starting from Templates", - "anchor": "starting-from-templates" - }, - { - "depth": 3, - "title": "Solochain Templates", - "anchor": "solochain-templates" - }, - { - "depth": 3, - "title": "Parachain Templates", - "anchor": "parachain-templates" + "title": "Chilling as a Nominator", + "anchor": "chilling-as-a-nominator" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 9427, - "words": 1267, - "headings": 9, - "estimated_token_count_total": 2019 - }, - "hash": "sha256:d03ea172f2af9f4648e730d60033a80c2c1e64efa9241fed0c1ba40a5f846ae5", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-customize-parachain", - "title": "Customize Your Parachain", - "slug": "develop-parachains-customize-parachain", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-customize-parachain.md", - "html_url": "https://docs.polkadot.com/develop/parachains/customize-parachain/", - "preview": "Learn how to build a custom parachain with Polkadot SDK's FRAME framework, which includes pallet development, testing, smart contracts, and runtime customization. Pallets are modular components within the FRAME ecosystem that contain specific blockchain functionalities. This modularity grants developers increased flexibility and control around which behaviors to include in the core logic of their parachain.", - "outline": [ - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Chilling as a Validator", + "anchor": "chilling-as-a-validator" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Chill Other", + "anchor": "chill-other" } ], "stats": { - "chars": 1899, - "words": 259, - "headings": 2, - "estimated_token_count_total": 335 + "chars": 4439, + "words": 679, + "headings": 6, + "estimated_token_count_total": 861 }, - "hash": "sha256:9a08b66442c564c7116c686d8914b74ad617326f450d0894b05e753462f69aac", + "hash": "sha256:1af153570ce57bd5b52d08493a300996765686f2a6d04519a2e0aa91191612c1", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-deployment-build-deterministic-runtime", - "title": "Build a deterministic runtime", - "slug": "develop-parachains-deployment-build-deterministic-runtime", + "id": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", + "title": "Upgrade a Validator Node", + "slug": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-build-deterministic-runtime.md", - "html_url": "https://docs.polkadot.com/develop/parachains/deployment/build-deterministic-runtime/", - "preview": "By default, the Rust compiler produces optimized Wasm binaries. These binaries are suitable for working in an isolated environment, such as local development. However, the Wasm binaries the compiler builds by default aren't guaranteed to be deterministically reproducible. Each time the compiler generates the Wasm runtime, it might produce a slightly different Wasm byte code. This is problematic in a blockchain network where all nodes must use exactly the same raw chain specification file.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/upgrade-your-node/", + "preview": "Upgrading a Polkadot validator node is essential for staying current with network updates and maintaining optimal performance. This guide covers routine and extended maintenance scenarios, including software upgrades and major server changes. Following these steps, you can manage session keys and transition smoothly between servers without risking downtime, slashing, or network disruptions. The process requires strategic planning, especially if you need to perform long-lead maintenance, ensuring", "outline": [ { "depth": 2, @@ -1840,59 +1574,49 @@ }, { "depth": 2, - "title": "Tooling for Wasm Runtime", - "anchor": "tooling-for-wasm-runtime" - }, - { - "depth": 2, - "title": "Working with the Docker Container", - "anchor": "working-with-the-docker-container" - }, - { - "depth": 2, - "title": "Prepare the Environment", - "anchor": "prepare-the-environment" + "title": "Session Keys", + "anchor": "session-keys" }, { "depth": 2, - "title": "Start a Deterministic Build", - "anchor": "start-a-deterministic-build" + "title": "Keystore", + "anchor": "keystore" }, { "depth": 2, - "title": "Use srtool in GitHub Actions", - "anchor": "use-srtool-in-github-actions" + "title": "Upgrade Using Backup Validator", + "anchor": "upgrade-using-backup-validator" }, { - "depth": 2, - "title": "Use the srtool Image via Docker Hub", - "anchor": "use-the-srtool-image-via-docker-hub" + "depth": 3, + "title": "Session `N`", + "anchor": "session-n" }, { "depth": 3, - "title": "Naming Convention for Images", - "anchor": "naming-convention-for-images" + "title": "Session `N+3`", + "anchor": "session-n3" } ], "stats": { - "chars": 8470, - "words": 1227, - "headings": 9, - "estimated_token_count_total": 1944 + "chars": 5650, + "words": 851, + "headings": 7, + "estimated_token_count_total": 1185 }, - "hash": "sha256:4fc8cab40e982e860b64d9aede1058fe7fa82ec321ac215b919db00c4df0a9c0", + "hash": "sha256:888230b128d8c648c4f06a18d3b1d1b06dd1bf22a0de4add1f28210ffccb2549", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-deployment-coretime-renewal", - "title": "Coretime Renewal", - "slug": "develop-parachains-deployment-coretime-renewal", + "id": "nodes-and-validators-run-a-validator-requirements", + "title": "Validator Requirements", + "slug": "nodes-and-validators-run-a-validator-requirements", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-coretime-renewal.md", - "html_url": "https://docs.polkadot.com/develop/parachains/deployment/coretime-renewal/", - "preview": "Coretime can be purchased in bulk for a period of 28 days, providing access to Polkadot's shared security and interoperability for Polkadot parachains. The bulk purchase of coretime includes a rent-control mechanism that keeps future purchases within a predictable price range of the initial purchase. This allows cores to be renewed at a known price without competing against other participants in the open market.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-requirements.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/requirements/", + "preview": "Running a validator in the Polkadot ecosystem is essential for maintaining network security and decentralization. Validators are responsible for validating transactions and adding new blocks to the chain, ensuring the system operates smoothly. In return for their services, validators earn rewards. However, the role comes with inherent risks, such as slashing penalties for misbehavior or technical failures. If you’re new to validation, starting on Kusama provides a lower-stakes environment to gai", "outline": [ { "depth": 2, @@ -1901,69 +1625,44 @@ }, { "depth": 2, - "title": "Bulk Sale Phases", - "anchor": "bulk-sale-phases" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Renewal Timing", - "anchor": "renewal-timing" + "title": "Minimum Hardware Requirements", + "anchor": "minimum-hardware-requirements" }, { "depth": 2, - "title": "Manual Renewal", - "anchor": "manual-renewal" + "title": "VPS Provider List", + "anchor": "vps-provider-list" }, { "depth": 2, - "title": "Auto-Renewal", - "anchor": "auto-renewal" - }, - { - "depth": 3, - "title": "Set Up an HRMP Channel", - "anchor": "set-up-an-hrmp-channel" - }, - { - "depth": 3, - "title": "Fund Sovereign Account", - "anchor": "fund-sovereign-account" - }, - { - "depth": 3, - "title": "Auto-Renewal Configuration Extrinsics", - "anchor": "auto-renewal-configuration-extrinsics" - }, - { - "depth": 3, - "title": "Construct the Enable Auto-Renewal Extrinsic", - "anchor": "construct-the-enable-auto-renewal-extrinsic" - }, - { - "depth": 3, - "title": "Submit the XCM from Your Parachain", - "anchor": "submit-the-xcm-from-your-parachain" + "title": "Minimum Bond Requirement", + "anchor": "minimum-bond-requirement" } ], "stats": { - "chars": 13912, - "words": 1894, - "headings": 10, - "estimated_token_count_total": 3068 + "chars": 6842, + "words": 944, + "headings": 5, + "estimated_token_count_total": 1485 }, - "hash": "sha256:9918593a46c12a1756552ddfaf7421ad6262600735b6f1fec030911420fe1736", + "hash": "sha256:46435b97c37ef6798d2c75c69df31c5e5f07e04b218c370ec5af6b1838d43aac", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-deployment-generate-chain-specs", - "title": "Generate Chain Specs", - "slug": "develop-parachains-deployment-generate-chain-specs", + "id": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", + "title": "Offenses and Slashes", + "slug": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-generate-chain-specs.md", - "html_url": "https://docs.polkadot.com/develop/parachains/deployment/generate-chain-specs/", - "preview": "A chain specification collects information that describes a Polkadot SDK-based network. A chain specification is a crucial parameter when starting a node, providing the genesis configurations, bootnodes, and other parameters relating to that particular network. It identifies the network a blockchain node connects to, the other nodes it initially communicates with, and the initial state that nodes must agree on to produce blocks.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/offenses-and-slashes/", + "preview": "In Polkadot's Nominated Proof of Stake (NPoS) system, validator misconduct is deterred through a combination of slashing, disabling, and reputation penalties. Validators and nominators who stake tokens face consequences for validator misbehavior, which range from token slashes to restrictions on network participation.", "outline": [ { "depth": 2, @@ -1972,79 +1671,64 @@ }, { "depth": 2, - "title": "Node Settings Customization", - "anchor": "node-settings-customization" - }, - { - "depth": 2, - "title": "Genesis Configuration Customization", - "anchor": "genesis-configuration-customization" + "title": "Offenses", + "anchor": "offenses" }, { - "depth": 2, - "title": "Declaring Storage Items for a Runtime", - "anchor": "declaring-storage-items-for-a-runtime" + "depth": 3, + "title": "Invalid Votes", + "anchor": "invalid-votes" }, { - "depth": 2, - "title": "Chain Specification JSON Format", - "anchor": "chain-specification-json-format" + "depth": 3, + "title": "Equivocations", + "anchor": "equivocations" }, { "depth": 2, - "title": "Creating a Custom Chain Specification", - "anchor": "creating-a-custom-chain-specification" + "title": "Penalties", + "anchor": "penalties" }, { "depth": 3, - "title": "Plain Chain Specifications", - "anchor": "plain-chain-specifications" + "title": "Slashing", + "anchor": "slashing" }, { "depth": 3, - "title": "Raw Chain Specifications", - "anchor": "raw-chain-specifications" - }, - { - "depth": 2, - "title": "Generate Custom Keys for Your Collator", - "anchor": "generate-custom-keys-for-your-collator" + "title": "Disabling", + "anchor": "disabling" }, { "depth": 3, - "title": "Add Invulnerables", - "anchor": "add-invulnerables" + "title": "Reputation Changes", + "anchor": "reputation-changes" }, { "depth": 3, - "title": "Add Session Keys", - "anchor": "add-session-keys" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Penalties by Offense", + "anchor": "penalties-by-offense" } ], "stats": { - "chars": 14573, - "words": 1931, - "headings": 12, - "estimated_token_count_total": 3025 + "chars": 15427, + "words": 2103, + "headings": 9, + "estimated_token_count_total": 3409 }, - "hash": "sha256:a60fe36a5ba6d1cafe12eab75300afd24a46d3ace1e791087adb7e3e538afcc3", + "hash": "sha256:abe6bedab04f463ec07f554977b8d6355a5d2fad9bcda01cbe58568152295daa", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-deployment-manage-coretime", - "title": "Manage Coretime", - "slug": "develop-parachains-deployment-manage-coretime", + "id": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", + "title": "Rewards Payout", + "slug": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", "categories": [ - "Parachains" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment-manage-coretime.md", - "html_url": "https://docs.polkadot.com/develop/parachains/deployment/manage-coretime/", - "preview": "Coretime management involves manipulating [bulk coretime](/parachains/launch-a-parachain/obtain-coretime/#bulk-coretime){target=\\_blank} regions to optimize resource allocation and usage. Regions represent allocated computational resources on cores and can be modified through various operations to meet different project requirements. This guide covers the essential operations for managing your coretime regions effectively.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-rewards.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/rewards/", + "preview": "Understanding how rewards are distributed to validators and nominators is essential for network participants. In Polkadot and Kusama, validators earn rewards based on their era points, which are accrued through actions like block production and parachain validation.", "outline": [ { "depth": 2, @@ -2053,136 +1737,140 @@ }, { "depth": 2, - "title": "Transfer", - "anchor": "transfer" + "title": "Era Points", + "anchor": "era-points" }, { "depth": 2, - "title": "Partition", - "anchor": "partition" + "title": "Reward Variance", + "anchor": "reward-variance" }, { "depth": 2, - "title": "Interlace", - "anchor": "interlace" + "title": "Payout Scheme", + "anchor": "payout-scheme" }, { "depth": 2, - "title": "Assign", - "anchor": "assign" + "title": "Running Multiple Validators", + "anchor": "running-multiple-validators" }, { "depth": 2, - "title": "Pool", - "anchor": "pool" + "title": "Nominators and Validator Payments", + "anchor": "nominators-and-validator-payments" } ], "stats": { - "chars": 5736, - "words": 841, + "chars": 10976, + "words": 1753, "headings": 6, - "estimated_token_count_total": 1289 + "estimated_token_count_total": 2588 }, - "hash": "sha256:39c58dbe2ddcd542d7074d08d72f1811318dc8a3130419025480fd5cbe9fc3e7", + "hash": "sha256:d5d6d72eb2cf10f624d84c65f2274f7df90acb5d071bf170bc8eae8d98a810a5", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-deployment", - "title": "Deployment", - "slug": "develop-parachains-deployment", + "id": "parachains-customize-runtime-add-existing-pallets", + "title": "Add an Existing Pallet to the Runtime", + "slug": "parachains-customize-runtime-add-existing-pallets", "categories": [ - "Uncategorized" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-deployment.md", - "html_url": "https://docs.polkadot.com/develop/parachains/deployment/", - "preview": "Learn how to prepare your blockchain for deployment using the Polkadot SDK, including building deterministic Wasm runtimes and generating chain specifications.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-existing-pallets.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-existing-pallets/", + "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a functional runtime that includes default [FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} development modules ([pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}) to help you get started building a custo", "outline": [ { "depth": 2, - "title": "Deployment Process", - "anchor": "deployment-process" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Check Prerequisites", + "anchor": "check-prerequisites" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 4818, - "words": 659, - "headings": 3, - "estimated_token_count_total": 966 - }, - "hash": "sha256:b25618dc598f4f946da06f854211645768214e0b51d06b684b0cab668b66124c", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-maintenance-configure-asynchronous-backing", - "title": "Configure Asynchronous Backing", - "slug": "develop-parachains-maintenance-configure-asynchronous-backing", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-maintenance-configure-asynchronous-backing.md", - "html_url": "https://docs.polkadot.com/develop/parachains/maintenance/configure-asynchronous-backing/", - "preview": "This guide applies to parachain projects based on Cumulus that started in 2023 or earlier, where the backing process was synchronous, allowing parablocks to be built only on the latest relay chain block. In contrast, async backing will enable collators to build parablocks on older relay chain blocks and create pipelines of multiple pending parablocks. This parallel block generation increases efficiency and throughput.", - "outline": [ + "title": "Add an Existing Polkadot SDK Pallet to Your Runtime", + "anchor": "add-an-existing-polkadot-sdk-pallet-to-your-runtime" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Add an Existing Pallet as a Dependency", + "anchor": "add-an-existing-pallet-as-a-dependency" }, { - "depth": 2, - "title": "Prerequisite", - "anchor": "prerequisite" + "depth": 3, + "title": "Enable Standard Library Features", + "anchor": "enable-standard-library-features" }, { - "depth": 2, - "title": "Phase 1 - Update Parachain Runtime", - "anchor": "phase-1-update-parachain-runtime" + "depth": 3, + "title": "Review the Config Trait", + "anchor": "review-the-config-trait" }, { - "depth": 2, - "title": "Phase 2 - Update Parachain Nodes", - "anchor": "phase-2-update-parachain-nodes" + "depth": 3, + "title": "Implement the Config Trait", + "anchor": "implement-the-config-trait" + }, + { + "depth": 3, + "title": "Add to Runtime Construct", + "anchor": "add-to-runtime-construct" + }, + { + "depth": 3, + "title": "Verify the Runtime Compiles", + "anchor": "verify-the-runtime-compiles" }, { "depth": 2, - "title": "Phase 3 - Activate Async Backing", - "anchor": "phase-3-activate-async-backing" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" + }, + { + "depth": 3, + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" + }, + { + "depth": 3, + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" + }, + { + "depth": 3, + "title": "Interact with the Pallet", + "anchor": "interact-with-the-pallet" }, { "depth": 2, - "title": "Timing by Block Number", - "anchor": "timing-by-block-number" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 20813, - "words": 2382, - "headings": 6, - "estimated_token_count_total": 4719 + "chars": 11924, + "words": 1585, + "headings": 14, + "estimated_token_count_total": 2724 }, - "hash": "sha256:bfad885d8053d052c55dbffc3c09e6196586795c3a1d07ab6ad58f9006ec3345", + "hash": "sha256:93d123cbaaccc2515b4a70be8e1327b4f75b1051d16c5e3daf5a2035af7b7ca3", "token_estimator": "heuristic-v1" }, { - "id": "develop-parachains-maintenance-runtime-metrics-monitoring", - "title": "Runtime Metrics and Monitoring", - "slug": "develop-parachains-maintenance-runtime-metrics-monitoring", + "id": "parachains-customize-runtime-add-pallet-instances", + "title": "Add Multiple Pallet Instances", + "slug": "parachains-customize-runtime-add-pallet-instances", "categories": [ "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-maintenance-runtime-metrics-monitoring.md", - "html_url": "https://docs.polkadot.com/develop/parachains/maintenance/runtime-metrics-monitoring/", - "preview": "Maintaining a stable, secure, and efficient network requires continuous monitoring. Polkadot SDK-based nodes are equipped with built-in telemetry components that automatically collect and transmit detailed data about node performance in real-time. This telemetry system is a core feature of the Substrate framework, allowing for easy monitoring of network health without complex setup.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-pallet-instances.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-pallet-instances/", + "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a solid foundation for building custom parachains. While most pallets are typically included as single instances within a runtime, some scenarios benefit from running multiple instances of the same pallet with different configurations. This approach lets you reuse pallet logic without reimplementing it, enabling diverse functionality from a single codebase.", "outline": [ { "depth": 2, @@ -2191,894 +1879,625 @@ }, { "depth": 2, - "title": "Runtime Metrics", - "anchor": "runtime-metrics" + "title": "Check Prerequisites", + "anchor": "check-prerequisites" }, { "depth": 2, - "title": "Visual Monitoring", - "anchor": "visual-monitoring" + "title": "Understanding Instantiable Pallets", + "anchor": "understanding-instantiable-pallets" }, { - "depth": 2, - "title": "Displaying Network-Wide Statistics", - "anchor": "displaying-network-wide-statistics" + "depth": 3, + "title": "Identifying an Instantiable Pallet", + "anchor": "identifying-an-instantiable-pallet" + }, + { + "depth": 3, + "title": "How Instance Generics Work", + "anchor": "how-instance-generics-work" }, { "depth": 2, - "title": "Customizing Monitoring Tools", - "anchor": "customizing-monitoring-tools" + "title": "Add Multiple Instances of a Pallet to Your Runtime", + "anchor": "add-multiple-instances-of-a-pallet-to-your-runtime" }, { "depth": 3, - "title": "On-Chain Activity", - "anchor": "on-chain-activity" + "title": "Add the Pallet as a Dependency", + "anchor": "add-the-pallet-as-a-dependency" }, { - "depth": 2, - "title": "Monitoring Tools", - "anchor": "monitoring-tools" + "depth": 3, + "title": "Enable Standard Library Features", + "anchor": "enable-standard-library-features" }, { "depth": 3, - "title": "Change the Telemetry Server", - "anchor": "change-the-telemetry-server" - } - ], - "stats": { - "chars": 8458, - "words": 1202, - "headings": 8, - "estimated_token_count_total": 1819 - }, - "hash": "sha256:b0c1535fa8e969a9bdeee426a5a35a42b4649121fb8ce6fd2b15fdeba35b5d5f", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-maintenance", - "title": "Maintenance", - "slug": "develop-parachains-maintenance", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-maintenance.md", - "html_url": "https://docs.polkadot.com/develop/parachains/maintenance/", - "preview": "Learn how to maintain Polkadot SDK-based networks, focusing on runtime monitoring, upgrades, and storage migrations for optimal performance. Proper maintenance ensures your blockchain remains secure, efficient, and adaptable to changing needs. These sections will guide you through monitoring your network, using runtime versioning, and performing forkless upgrades to keep your blockchain secure and up-to-date without downtime.", - "outline": [ + "title": "Review the Config Trait", + "anchor": "review-the-config-trait" + }, { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "depth": 3, + "title": "Define Pallet Parameters", + "anchor": "define-pallet-parameters" }, { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1372, - "words": 174, - "headings": 2, - "estimated_token_count_total": 236 - }, - "hash": "sha256:3b0a9e8037c7634c33ac6674170bd763599fca914855d9d2fbf490d359140130", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains-testing", - "title": "Testing Your Polkadot SDK-Based Blockchain", - "slug": "develop-parachains-testing", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains-testing.md", - "html_url": "https://docs.polkadot.com/develop/parachains/testing/", - "preview": "Explore comprehensive testing strategies for Polkadot SDK-based blockchains, from setting up test environments to verifying runtime and pallet interactions. Testing is essential to feeling confident your network will behave the way you intend upon deployment.", - "outline": [ + "depth": 3, + "title": "Create Instance Type Definitions", + "anchor": "create-instance-type-definitions" + }, { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "depth": 3, + "title": "Implement Config Trait for First Instance", + "anchor": "implement-config-trait-for-first-instance" }, { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1243, - "words": 157, - "headings": 2, - "estimated_token_count_total": 211 - }, - "hash": "sha256:0ce1fe38de00827a0735b9fa8076492205c2450c61da9fbd1937d9f38cfe7825", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-parachains", - "title": "Parachains", - "slug": "develop-parachains", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-parachains.md", - "html_url": "https://docs.polkadot.com/develop/parachains/", - "preview": "This section provides a complete guide to working with the Polkadot SDK, from getting started to long-term network maintenance. Discover how to create custom blockchains, test and deploy your parachains, and ensure their continued performance and reliability.", - "outline": [ + "depth": 3, + "title": "Implement Config Trait for Second Instance", + "anchor": "implement-config-trait-for-second-instance" + }, { - "depth": 2, - "title": "Building Parachains with the Polkadot SDK", - "anchor": "building-parachains-with-the-polkadot-sdk" + "depth": 3, + "title": "Add Instances to Runtime Construct", + "anchor": "add-instances-to-runtime-construct" }, { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 1994, - "words": 264, - "headings": 2, - "estimated_token_count_total": 330 - }, - "hash": "sha256:75a6fa2f21b67009be62e07bab01655a10b2c35a5292dc1f7ca57df846d709f3", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-smart-contracts-connect-to-kusama", - "title": "Connect to Kusama", - "slug": "develop-smart-contracts-connect-to-kusama", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-connect-to-kusama.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/connect-to-kusama/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", - "outline": [ + "depth": 3, + "title": "Verify the Runtime Compiles", + "anchor": "verify-the-runtime-compiles" + }, { "depth": 2, - "title": "Networks Details", - "anchor": "networks-details" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { - "depth": 2, - "title": "Important Deployment Considerations", - "anchor": "important-deployment-considerations" + "depth": 3, + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 3601, - "words": 476, - "headings": 3, - "estimated_token_count_total": 514 - }, - "hash": "sha256:e8ffeaa3a17e20437a59f2c95a63821eb75bf3c33001e748c23958b2b99ac3c2", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-smart-contracts-dev-environments", - "title": "Dev Environments", - "slug": "develop-smart-contracts-dev-environments", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-dev-environments.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/dev-environments/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Explore the tools and frameworks available for building and testing smart contracts on the Polkadot network. These environments streamline the development process, from writing and compiling to testing and deploying smart contracts. The guides in this section will help you evaluate each tool's strengths, making it easier to choose t", - "outline": [ + "depth": 3, + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" + }, { - "depth": 2, - "title": "What to Consider", - "anchor": "what-to-consider" + "depth": 3, + "title": "Interact with Both Pallet Instances", + "anchor": "interact-with-both-pallet-instances" + }, + { + "depth": 3, + "title": "Test Instance Independence", + "anchor": "test-instance-independence" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 1601, - "words": 154, - "headings": 2, - "estimated_token_count_total": 323 + "chars": 17923, + "words": 2203, + "headings": 21, + "estimated_token_count_total": 3811 }, - "hash": "sha256:5c3a10769e30b4da62e6c188e99310354e6e9af4595c7920c2977a54b8e1853c", + "hash": "sha256:d83e574726c524fa017236eb5e3b8a0676d598be4da1ce4fe25a60141baeee49", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-faqs", - "title": "Polkadot Hub Smart Contract FAQs", - "slug": "develop-smart-contracts-faqs", + "id": "parachains-customize-runtime-add-smart-contract-functionality", + "title": "Add Smart Contract Functionality", + "slug": "parachains-customize-runtime-add-smart-contract-functionality", "categories": [ - "Smart Contracts" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-faqs.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/faqs/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. !!! note For a list of known incompatibilities, please refer to the [Solidity and Yul IR translation incompatibilities](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#solidity-and-yul-ir-translation-incompatibilities){target=\\_blank} section.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-smart-contract-functionality/", + "preview": "When building your custom blockchain with the Polkadot SDK, you can add smart contract capabilities through specialized pallets. These pallets enable users to deploy and execute smart contracts, enhancing your chain's programmability and allowing developers to build decentralized applications on your network.", "outline": [ { "depth": 2, - "title": "General Questions", - "anchor": "general-questions" + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "What are the different types of smart contracts I can build on Polkadot?", - "anchor": "what-are-the-different-types-of-smart-contracts-i-can-build-on-polkadot" + "depth": 2, + "title": "pallet-revive", + "anchor": "pallet-revive" }, { "depth": 3, - "title": "Should I build a smart contract or a parachain?", - "anchor": "should-i-build-a-smart-contract-or-a-parachain" + "title": "Core Components", + "anchor": "core-components" }, { "depth": 3, - "title": "What's the difference between Polkadot Hub smart contracts and other EVM chains?", - "anchor": "whats-the-difference-between-polkadot-hub-smart-contracts-and-other-evm-chains" - }, - { - "depth": 2, - "title": "Development Environment", - "anchor": "development-environment" + "title": "Supported Languages and Compilers", + "anchor": "supported-languages-and-compilers" }, { "depth": 3, - "title": "Can I use my existing Ethereum development tools?", - "anchor": "can-i-use-my-existing-ethereum-development-tools" + "title": "How It Works", + "anchor": "how-it-works" }, { "depth": 3, - "title": "How do I set up local development?", - "anchor": "how-do-i-set-up-local-development" + "title": "Key Benefits", + "anchor": "key-benefits" }, { "depth": 3, - "title": "What networks are available for testing and deployment?", - "anchor": "what-networks-are-available-for-testing-and-deployment" + "title": "Implementation Examples", + "anchor": "implementation-examples" }, { "depth": 2, - "title": "Technical Implementation", - "anchor": "technical-implementation" + "title": "Frontier", + "anchor": "frontier" }, { "depth": 3, - "title": "How do Ethereum addresses work on Polkadot?", - "anchor": "how-do-ethereum-addresses-work-on-polkadot" + "title": "Integration Options", + "anchor": "integration-options" }, { "depth": 3, - "title": "What are the key differences in the gas model?", - "anchor": "what-are-the-key-differences-in-the-gas-model" + "title": "EVM Execution Only", + "anchor": "evm-execution-only" }, { "depth": 3, - "title": "How does contract deployment work?", - "anchor": "how-does-contract-deployment-work" + "title": "Full Ethereum Compatibility", + "anchor": "full-ethereum-compatibility" }, { "depth": 3, - "title": "Which Solidity features are not supported?", - "anchor": "which-solidity-features-are-not-supported" + "title": "Key Benefits", + "anchor": "key-benefits-2" }, { "depth": 3, - "title": "How do I handle the existential deposit requirement?", - "anchor": "how-do-i-handle-the-existential-deposit-requirement" + "title": "Implementation Examples", + "anchor": "implementation-examples-2" }, { "depth": 2, - "title": "Migration and Compatibility", - "anchor": "migration-and-compatibility" + "title": "pallet-contracts (Legacy)", + "anchor": "pallet-contracts-legacy" }, { "depth": 3, - "title": "Can I migrate my existing Ethereum contracts?", - "anchor": "can-i-migrate-my-existing-ethereum-contracts" + "title": "Implementation Example", + "anchor": "implementation-example" }, { "depth": 2, - "title": "Troubleshooting", - "anchor": "troubleshooting" - }, - { - "depth": 3, - "title": "Why are my gas calculations different?", - "anchor": "why-are-my-gas-calculations-different" - }, - { - "depth": 3, - "title": "I deployed a contract with MetaMask, and got a `code size` error - why?", - "anchor": "i-deployed-a-contract-with-metamask-and-got-a-code-size-error-why" - }, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 6655, + "words": 833, + "headings": 16, + "estimated_token_count_total": 1631 + }, + "hash": "sha256:6297bb5e0809fdd0585d6170054599f7ab4a3ce7c687ad03ae43092057c493b7", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", + "title": "Add Pallets to the Runtime", + "slug": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", + "categories": [ + "Basics", + "Parachains" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-add-pallet-to-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/", + "preview": "In previous tutorials, you learned how to [create a custom pallet](/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/){target=\\_blank} and [test it](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/){target=\\_blank}. The next step is to include this pallet in your runtime, integrating it into the core logic of your blockchain.", + "outline": [ { - "depth": 3, - "title": "I found a bug, where can I log it?", - "anchor": "i-found-a-bug-where-can-i-log-it" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Known Issues", - "anchor": "known-issues" + "title": "Add the Pallets as Dependencies", + "anchor": "add-the-pallets-as-dependencies" }, { "depth": 3, - "title": "Runtime Behavior", - "anchor": "runtime-behavior" + "title": "Update the Runtime Configuration", + "anchor": "update-the-runtime-configuration" }, { - "depth": 3, - "title": "Development Tools", - "anchor": "development-tools" + "depth": 2, + "title": "Recompile the Runtime", + "anchor": "recompile-the-runtime" }, { - "depth": 3, - "title": "Contract Patterns", - "anchor": "contract-patterns" + "depth": 2, + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { - "depth": 3, - "title": "Compilation", - "anchor": "compilation" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 7480, - "words": 984, - "headings": 25, - "estimated_token_count_total": 1618 + "chars": 13091, + "words": 1522, + "headings": 6, + "estimated_token_count_total": 3091 }, - "hash": "sha256:5cc63ff0a377ef0ec96a064748e13b88bc852bd1862c6e344066855a7fe93b19", + "hash": "sha256:87add0ae178e4970601a27efccadb58eff1375d19819201034ba2829914f1cd5", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts-libraries", - "title": "Libraries", - "slug": "develop-smart-contracts-libraries", + "id": "parachains-customize-runtime-pallet-development-benchmark-pallet", + "title": "Benchmark Your Pallet", + "slug": "parachains-customize-runtime-pallet-development-benchmark-pallet", "categories": [ - "Uncategorized" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-libraries.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/libraries/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Explore the key libraries for interacting with smart contracts on Polkadot-based networks. These libraries simplify contract calls, event listening, and transaction handling.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/benchmark-pallet/", + "preview": "Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.", "outline": [ { "depth": 2, - "title": "Library Comparison", - "anchor": "library-comparison" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 2056, - "words": 203, - "headings": 2, - "estimated_token_count_total": 415 - }, - "hash": "sha256:23137f6c74412fd98c0b6aeee3ff59938e44b817ec42974c453f9b0f66e36513", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-smart-contracts-precompiles-interact-with-precompiles", - "title": "Interact with Precompiles", - "slug": "develop-smart-contracts-precompiles-interact-with-precompiles", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts-precompiles-interact-with-precompiles.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/precompiles/interact-with-precompiles/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ + "title": "Prerequisites", + "anchor": "prerequisites" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Create the Benchmarking Module", + "anchor": "create-the-benchmarking-module" }, { "depth": 2, - "title": "Basic Precompile Interaction Pattern", - "anchor": "basic-precompile-interaction-pattern" + "title": "Define the Weight Trait", + "anchor": "define-the-weight-trait" + }, + { + "depth": 2, + "title": "Add WeightInfo to Config", + "anchor": "add-weightinfo-to-config" + }, + { + "depth": 2, + "title": "Update Extrinsic Weight Annotations", + "anchor": "update-extrinsic-weight-annotations" }, { "depth": 2, - "title": "ECRecover (0x01)", - "anchor": "ecrecover-0x01" + "title": "Include the Benchmarking Module", + "anchor": "include-the-benchmarking-module" }, { "depth": 2, - "title": "SHA-256 (0x02)", - "anchor": "sha-256-0x02" + "title": "Configure Pallet Dependencies", + "anchor": "configure-pallet-dependencies" }, { "depth": 2, - "title": "RIPEMD-160 (0x03)", - "anchor": "ripemd-160-0x03" + "title": "Update Mock Runtime", + "anchor": "update-mock-runtime" }, { "depth": 2, - "title": "Identity (Data Copy) (0x04)", - "anchor": "identity-data-copy-0x04" + "title": "Configure Runtime Benchmarking", + "anchor": "configure-runtime-benchmarking" }, { "depth": 2, - "title": "Modular Exponentiation (0x05)", - "anchor": "modular-exponentiation-0x05" + "title": "Test Benchmark Compilation", + "anchor": "test-benchmark-compilation" }, { "depth": 2, - "title": "BN128 Addition (0x06)", - "anchor": "bn128-addition-0x06" + "title": "Build the Runtime with Benchmarks", + "anchor": "build-the-runtime-with-benchmarks" }, { "depth": 2, - "title": "BN128 Scalar Multiplication (0x07)", - "anchor": "bn128-scalar-multiplication-0x07" + "title": "Install the Benchmarking Tool", + "anchor": "install-the-benchmarking-tool" }, { "depth": 2, - "title": "BN128 Pairing Check (0x08)", - "anchor": "bn128-pairing-check-0x08" + "title": "Download the Weight Template", + "anchor": "download-the-weight-template" }, { "depth": 2, - "title": "Blake2F (0x09)", - "anchor": "blake2f-0x09" + "title": "Execute Benchmarks", + "anchor": "execute-benchmarks" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Use Generated Weights", + "anchor": "use-generated-weights" + }, + { + "depth": 2, + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" + }, + { + "depth": 2, + "title": "Related Resources", + "anchor": "related-resources" } ], "stats": { - "chars": 18054, - "words": 2190, - "headings": 12, - "estimated_token_count_total": 3847 + "chars": 22752, + "words": 2813, + "headings": 18, + "estimated_token_count_total": 5191 }, - "hash": "sha256:4b705b8dbe9b0ad8d19a897d91f3c64dbc4541297dadacbea2a31b4778e50a46", + "hash": "sha256:c1b53ecbfc3dea02097104c7a4c652e61ccc42ad56325a9c80684850a198fbdd", "token_estimator": "heuristic-v1" }, { - "id": "develop-smart-contracts", - "title": "Smart Contracts", - "slug": "develop-smart-contracts", + "id": "parachains-customize-runtime-pallet-development-create-a-pallet", + "title": "Create a Custom Pallet", + "slug": "parachains-customize-runtime-pallet-development-create-a-pallet", "categories": [ - "Uncategorized" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-smart-contracts.md", - "html_url": "https://docs.polkadot.com/develop/smart-contracts/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Polkadot allows scalable execution of smart contracts, offering cross-chain compatibility and lower fees than legacy L1 platforms. Polkadot provides developers with flexibility in building smart contracts, supporting both Solidity contracts executed by the [PolkaVM](/smart-contracts/for-eth-devs/#polkavm){target=\\_blank} (a Polkadot", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/create-a-pallet/", + "preview": "[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functional", "outline": [ { "depth": 2, - "title": "Smart Contract Development Process", - "anchor": "smart-contract-development-process" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1867, - "words": 247, - "headings": 2, - "estimated_token_count_total": 189 - }, - "hash": "sha256:4b56a119cbc63d87de98554cf4019e48ddb4f7cee11a51553ea234f91d78f8b8", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-api-libraries", - "title": "API Libraries", - "slug": "develop-toolkit-api-libraries", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-api-libraries.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/api-libraries/", - "preview": "Explore the powerful API libraries designed for interacting with the Polkadot network. These libraries offer developers versatile tools to build, query, and manage blockchain interactions. Whether you’re working with JavaScript, TypeScript, Python, or RESTful services, they provide the flexibility to efficiently interact with and retrieve data from Polkadot-based chains.", - "outline": [ + "title": "Prerequisites", + "anchor": "prerequisites" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Core Pallet Components", + "anchor": "core-pallet-components" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1082, - "words": 139, - "headings": 2, - "estimated_token_count_total": 187 - }, - "hash": "sha256:746788d1068fe3eaafc34eb461566d1682c27fcad7d448e65810b9662b45dd85", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-integrations-storage", - "title": "Storage", - "slug": "develop-toolkit-integrations-storage", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-storage.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/storage/", - "preview": "Polkadot offers developers a range of decentralized storage solutions to manage dApp data, host front ends, and store large files in a censorship-resistant and resilient manner. These integrations are essential for building fully decentralized applications, ensuring that all components of your dApp, from the front end to the data, are not reliant on centralized servers.", - "outline": [ + "title": "Create the Pallet Project", + "anchor": "create-the-pallet-project" + }, { "depth": 2, - "title": "Key Storage Solutions", - "anchor": "key-storage-solutions" + "title": "Configure Dependencies", + "anchor": "configure-dependencies" }, { "depth": 2, - "title": "Crust Network", - "anchor": "crust-network" + "title": "Initialize the Pallet Structure", + "anchor": "initialize-the-pallet-structure" }, { - "depth": 3, - "title": "Key Features of Crust", - "anchor": "key-features-of-crust" + "depth": 2, + "title": "Configure the Pallet", + "anchor": "configure-the-pallet" }, { - "depth": 3, - "title": "Use Cases", - "anchor": "use-cases" + "depth": 2, + "title": "Define Events", + "anchor": "define-events" }, { "depth": 2, - "title": "IPFS", - "anchor": "ipfs" + "title": "Define Errors", + "anchor": "define-errors" }, { - "depth": 3, - "title": "Using IPFS with Polkadot", - "anchor": "using-ipfs-with-polkadot" + "depth": 2, + "title": "Add Storage Items", + "anchor": "add-storage-items" }, { "depth": 2, - "title": "Other Solutions", - "anchor": "other-solutions" - } - ], - "stats": { - "chars": 4369, - "words": 642, - "headings": 7, - "estimated_token_count_total": 847 - }, - "hash": "sha256:a206dd86fc3d80aed22384000839ca0c9c75c69ad461abd9810d96c03cf6a3bd", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-integrations-transaction-construction", - "title": "Transaction Construction", - "slug": "develop-toolkit-integrations-transaction-construction", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations-transaction-construction.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/transaction-construction/", - "preview": "This page will discuss the transaction format in Polkadot and how to create, sign, and broadcast transactions, as well as highlight some of the commands and tools available for integrators.", - "outline": [ + "title": "Configure Genesis State", + "anchor": "configure-genesis-state" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Implement Dispatchable Functions", + "anchor": "implement-dispatchable-functions" + }, + { + "depth": 3, + "title": "Dispatchable Function Details", + "anchor": "dispatchable-function-details" + }, + { + "depth": 2, + "title": "Verify Pallet Compilation", + "anchor": "verify-pallet-compilation" }, { "depth": 2, - "title": "Transaction Format", - "anchor": "transaction-format" + "title": "Add the Pallet to Your Runtime", + "anchor": "add-the-pallet-to-your-runtime" }, { "depth": 3, - "title": "Mode and Metadata Hash", - "anchor": "mode-and-metadata-hash" + "title": "Add Runtime Dependency", + "anchor": "add-runtime-dependency" }, { "depth": 3, - "title": "Serialized Transactions and Metadata", - "anchor": "serialized-transactions-and-metadata" + "title": "Implement the Config Trait", + "anchor": "implement-the-config-trait" }, { "depth": 3, - "title": "Transaction Flow", - "anchor": "transaction-flow" + "title": "Add to Runtime Construct", + "anchor": "add-to-runtime-construct" }, { - "depth": 2, - "title": "Polkadot-JS Tools", - "anchor": "polkadot-js-tools" + "depth": 3, + "title": "Configure Genesis for Your Runtime", + "anchor": "configure-genesis-for-your-runtime" }, { "depth": 3, - "title": "Creating a Transaction, Signing, and Submitting", - "anchor": "creating-a-transaction-signing-and-submitting" + "title": "Verify Runtime Compilation", + "anchor": "verify-runtime-compilation" }, { "depth": 2, - "title": "Txwrapper", - "anchor": "txwrapper" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { "depth": 3, - "title": "Creating a Transaction, Signing, and Submitting", - "anchor": "creating-a-transaction-signing-and-submitting-2" + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" }, { - "depth": 2, - "title": "Additional Libraries for Submitting a Transaction", - "anchor": "additional-libraries-for-submitting-a-transaction" - } - ], - "stats": { - "chars": 27671, - "words": 2949, - "headings": 10, - "estimated_token_count_total": 6280 - }, - "hash": "sha256:9b03477d13a285fced6bf845c3827084f790a626989dc2c09ef9ff53643045f4", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-integrations", - "title": "Integrations", - "slug": "develop-toolkit-integrations", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-integrations.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/integrations/", - "preview": "Polkadot offers a wide range of integrations that allow developers to enhance their decentralized applications (dApps) and leverage the full capabilities of the ecosystem. Whether you’re looking to extend your application’s functionality, integrate with other chains, or access specialized services, these integrations provide the tools and resources you need to build efficiently and effectively. Explore the available options to find the solutions that best suit your development needs.", - "outline": [ + "depth": 3, + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" + }, { "depth": 2, - "title": "Key Integration Solutions", - "anchor": "key-integration-solutions" + "title": "Interact with Your Pallet", + "anchor": "interact-with-your-pallet" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 988, - "words": 135, - "headings": 2, - "estimated_token_count_total": 92 - }, - "hash": "sha256:0de8c1655a1524784010b6cec5fa522b2f764e32f18913f0d262283e0ec0779e", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-interoperability", - "title": "Interoperability", - "slug": "develop-toolkit-interoperability", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-interoperability.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/interoperability/", - "preview": "Polkadot's XCM tooling ecosystem redefines the boundaries of cross-chain communication and asset movement. With unparalleled flexibility and scalability, these advanced tools empower developers to build decentralized applications that connect parachains, relay chains, and external networks. By bridging siloed blockchains, Polkadot paves the way for a unified, interoperable ecosystem that accelerates innovation and collaboration.", - "outline": [ + "title": "Key Takeaways", + "anchor": "key-takeaways" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 1010, - "words": 128, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 26958, + "words": 3085, + "headings": 26, + "estimated_token_count_total": 6194 }, - "hash": "sha256:c72d7d30a019fe1db8ab3993f91dfd4f1bdb4a932aaa685d3baaa0578091d5ce", + "hash": "sha256:dad68ea59fd05fd60dc8890c4cf5615243c7ea879830b0dcf3a5e5e53c3ccec7", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-parachains-e2e-testing", - "title": "E2E Testing on Polkadot SDK Chains", - "slug": "develop-toolkit-parachains-e2e-testing", + "id": "parachains-customize-runtime-pallet-development-mock-runtime", + "title": "Mock Your Runtime", + "slug": "parachains-customize-runtime-pallet-development-mock-runtime", "categories": [ - "Uncategorized" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-e2e-testing.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/e2e-testing/", - "preview": ":::INSERT_IN_THIS_SECTION:::", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/", + "preview": "Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node.", "outline": [ { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 64, - "words": 6, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:cc49fdcc63a43247d80de2f309b9c7501d3054782746d80c003d95f3c43da90d", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-fork-chains-chopsticks", - "title": "Chopsticks", - "slug": "develop-toolkit-parachains-fork-chains-chopsticks", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-fork-chains-chopsticks.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/fork-chains/chopsticks/", - "preview": "Chopsticks is a powerful tool that lets you create local copies of running Polkadot SDK-based networks. By forking live chains locally, you can safely test features, analyze network behavior, and simulate complex scenarios without affecting production networks.", - "outline": [ + "title": "Introduction", + "anchor": "introduction" + }, { "depth": 2, - "title": "What Can I Do with Chopsticks?", - "anchor": "what-can-i-do-with-chopsticks" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Understand Mock Runtimes", + "anchor": "understand-mock-runtimes" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1495, - "words": 201, - "headings": 3, - "estimated_token_count_total": 291 - }, - "hash": "sha256:b568596033cdf68e60d72bcb7ee62a794def2bd3ff5b3317ef15895f58a12c57", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-fork-chains", - "title": "Fork Chains for Testing", - "slug": "develop-toolkit-parachains-fork-chains", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-fork-chains.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/fork-chains/", - "preview": "Explore tools for forking live blockchain networks. These tools enable you to replicate real-world conditions in a local environment for accurate testing and debugging. They also allow you to analyze network behavior, test new features, and simulate complex scenarios in a controlled environment without affecting production systems.", - "outline": [ + "title": "Create the Mock Runtime Module", + "anchor": "create-the-mock-runtime-module" + }, { "depth": 2, - "title": "Why Fork a Live Chain?", - "anchor": "why-fork-a-live-chain" + "title": "Set Up Basic Mock", + "anchor": "set-up-basic-mock" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Implement Essential Configuration", + "anchor": "implement-essential-configuration" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1269, - "words": 173, - "headings": 3, - "estimated_token_count_total": 183 - }, - "hash": "sha256:d29a845b00b24e03f9877a5331c33619918decf453657969115d5ec18033ba28", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-quickstart-pop-cli", - "title": "Quickstart Parachain Development with Pop CLI", - "slug": "develop-toolkit-parachains-quickstart-pop-cli", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-quickstart-pop-cli.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/quickstart/pop-cli/", - "preview": "[Pop CLI](https://onpop.io/cli/){target=\\_blank} is a powerful command-line tool designed explicitly for rapid parachain development within the Polkadot ecosystem. It addresses essential developer needs by providing streamlined commands to set up development environments, scaffold parachain templates, and manage local blockchain networks.", - "outline": [ + "title": "Implement Your Pallet's Configuration", + "anchor": "implement-your-pallets-configuration" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Configure Genesis Storage", + "anchor": "configure-genesis-storage" }, { "depth": 3, - "title": "Install Pop CLI", - "anchor": "install-pop-cli" + "title": "Basic Test Environment", + "anchor": "basic-test-environment" }, { "depth": 3, - "title": "Set Up Your Development Environment", - "anchor": "set-up-your-development-environment" + "title": "Custom Genesis Configurations", + "anchor": "custom-genesis-configurations" }, { - "depth": 3, - "title": "Initialize a Project", - "anchor": "initialize-a-project" + "depth": 2, + "title": "Verify Mock Compilation", + "anchor": "verify-mock-compilation" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4236, - "words": 610, - "headings": 5, - "estimated_token_count_total": 999 - }, - "hash": "sha256:6d6c66430a7302f29113924c5208e64d7c244497e50c61ab2f45c4b5141620e4", - "token_estimator": "heuristic-v1" - }, - { - "id": "develop-toolkit-parachains-quickstart", - "title": "Quickstart Parachain Development", - "slug": "develop-toolkit-parachains-quickstart", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-quickstart.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/quickstart/", - "preview": ":::INSERT_IN_THIS_SECTION:::", - "outline": [ + "title": "Key Takeaways", + "anchor": "key-takeaways" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 85, - "words": 7, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 11766, + "words": 1369, + "headings": 13, + "estimated_token_count_total": 2514 }, - "hash": "sha256:91de375b7f822ed56b5e6b4d609d0d36e806d3f77041b4e180b6679b10a3e1c8", + "hash": "sha256:dd784a5d2daebb9a885fe09f6a967e6c84958d96ddb38d8366eabe9d860fa539", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-parachains-remote-proxies", - "title": "Remote Proxies", - "slug": "develop-toolkit-parachains-remote-proxies", + "id": "parachains-customize-runtime-pallet-development-pallet-testing", + "title": "Unit Test Pallets", + "slug": "parachains-customize-runtime-pallet-development-pallet-testing", "categories": [ - "Uncategorized" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-remote-proxies.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/remote-proxies/", - "preview": "!!!warning \"Kusama Implementation Only\" Remote proxies are currently only available on Kusama and its parachains (such as Kusama Asset Hub). This feature is not yet deployed on Polkadot MainNet. The examples and implementations described in this guide are specific to the Kusama ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/", + "preview": "Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.", "outline": [ { "depth": 2, @@ -3087,59 +2506,55 @@ }, { "depth": 2, - "title": "Remote Proxy Architecture", - "anchor": "remote-proxy-architecture" + "title": "Writing Unit Tests", + "anchor": "writing-unit-tests" }, { - "depth": 2, - "title": "Implementation Workflow", - "anchor": "implementation-workflow" - }, - { - "depth": 2, - "title": "Practical Implementation", - "anchor": "practical-implementation" + "depth": 3, + "title": "Test Initialization", + "anchor": "test-initialization" }, { "depth": 3, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Function Call Testing", + "anchor": "function-call-testing" }, { "depth": 3, - "title": "Installation and Setup", - "anchor": "installation-and-setup" + "title": "Storage Testing", + "anchor": "storage-testing" }, { "depth": 3, - "title": "Implementation Example", - "anchor": "implementation-example" + "title": "Event Testing", + "anchor": "event-testing" }, { "depth": 2, - "title": "Resources", - "anchor": "resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 9063, - "words": 1113, - "headings": 8, - "estimated_token_count_total": 1863 + "chars": 6895, + "words": 912, + "headings": 7, + "estimated_token_count_total": 1563 }, - "hash": "sha256:7086406b31e7aa9089b221ffaa548ee5540a3d147ec1e93136f481c883f2e434", + "hash": "sha256:041ccd82f0c1ddfb93be05feb6cf9d7d4a7e37af6caa8fa8fdab5d5538017122", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-parachains-rpc-calls", - "title": "RPC Calls to Polkadot SDK chains.", - "slug": "develop-toolkit-parachains-rpc-calls", + "id": "parachains-customize-runtime", + "title": "Overview of FRAME", + "slug": "parachains-customize-runtime", "categories": [ - "Uncategorized" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-rpc-calls.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/rpc-calls/", - "preview": "[Remote Procedure Call](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\\_blank} (RPC) interfaces are the primary way to interact programmatically with Polkadot SDK-based parachains and relay chains. RPC calls allow you to query chain state, submit transactions, and monitor network health from external applications or scripts.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/", + "preview": "A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a run", "outline": [ { "depth": 2, @@ -3148,275 +2563,364 @@ }, { "depth": 2, - "title": "How Do RPC Calls Work?", - "anchor": "how-do-rpc-calls-work" + "title": "Understanding Your Runtime", + "anchor": "understanding-your-runtime" }, { "depth": 2, - "title": "Making RPC Calls with Curl", - "anchor": "making-rpc-calls-with-curl" + "title": "Runtime Architecture", + "anchor": "runtime-architecture" }, { "depth": 2, - "title": "Essential RPC Methods", - "anchor": "essential-rpc-methods" - }, - { - "depth": 3, - "title": "system_health", - "anchor": "system_health" - }, - { - "depth": 3, - "title": "chain_getBlock", - "anchor": "chain_getblock" - }, - { - "depth": 3, - "title": "state_getStorage", - "anchor": "state_getstorage" + "title": "Building Blocks: Pallets", + "anchor": "building-blocks-pallets" }, { "depth": 3, - "title": "author_submitExtrinsic", - "anchor": "author_submitextrinsic" + "title": "Pre-Built Pallets vs. Custom Pallets", + "anchor": "pre-built-pallets-vs-custom-pallets" }, { "depth": 3, - "title": "state_getMetadata", - "anchor": "state_getmetadata" + "title": "Pallet Structure", + "anchor": "pallet-structure" }, { "depth": 2, - "title": "Check Available RPC Calls", - "anchor": "check-available-rpc-calls" - }, - { - "depth": 3, - "title": "Using curl", - "anchor": "using-curl" + "title": "How Runtime Customization Works", + "anchor": "how-runtime-customization-works" }, { - "depth": 3, - "title": "Using Polkadot.js Apps", - "anchor": "using-polkadotjs-apps" + "depth": 2, + "title": "Starting Templates", + "anchor": "starting-templates" }, { "depth": 2, - "title": "Resources", - "anchor": "resources" + "title": "Key Customization Scenarios", + "anchor": "key-customization-scenarios" } ], "stats": { - "chars": 6496, - "words": 909, - "headings": 13, - "estimated_token_count_total": 1870 + "chars": 8237, + "words": 1101, + "headings": 9, + "estimated_token_count_total": 1828 }, - "hash": "sha256:3b766e00e55a224201bc6744386a6dabc7da54ed9199b16abab3b94cff449eca", + "hash": "sha256:28501589d5290f932b55cd3319f6a3fd78d7297ba42810da5ad2784a297224fd", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-parachains-spawn-chains-zombienet-write-tests", - "title": "Write Tests", - "slug": "develop-toolkit-parachains-spawn-chains-zombienet-write-tests", + "id": "parachains-get-started", + "title": "Get Started with Parachain Development", + "slug": "parachains-get-started", "categories": [ - "Parachains", - "Tooling" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet-write-tests.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/", - "preview": "Testing is a critical step in blockchain development, ensuring reliability, performance, and security. Zombienet simplifies this process with its intuitive Domain Specific Language (DSL), enabling developers to write natural-language test scripts tailored to their network needs.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md", + "html_url": "https://docs.polkadot.com/parachains/get-started/", + "preview": "The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Quick Start Guides", + "anchor": "quick-start-guides" }, { "depth": 2, - "title": "Testing DSL", - "anchor": "testing-dsl" + "title": "Launch a Simple Parachain", + "anchor": "launch-a-simple-parachain" }, { "depth": 2, - "title": "The Test File", - "anchor": "the-test-file" + "title": "Customize Your Runtime", + "anchor": "customize-your-runtime" }, { "depth": 3, - "title": "Name", - "anchor": "name" + "title": "Pallet Development", + "anchor": "pallet-development" }, { - "depth": 3, - "title": "Assertions", - "anchor": "assertions" + "depth": 2, + "title": "Testing", + "anchor": "testing" }, { - "depth": 3, - "title": "Commands", - "anchor": "commands" + "depth": 2, + "title": "Runtime Upgrades and Maintenance", + "anchor": "runtime-upgrades-and-maintenance" + }, + { + "depth": 2, + "title": "Interoperability", + "anchor": "interoperability" }, { "depth": 2, - "title": "Running a Test", - "anchor": "running-a-test" + "title": "Integrations", + "anchor": "integrations" }, { "depth": 2, - "title": "Example Test Files", - "anchor": "example-test-files" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 11297, - "words": 1491, - "headings": 8, - "estimated_token_count_total": 2661 + "chars": 7941, + "words": 631, + "headings": 9, + "estimated_token_count_total": 2292 }, - "hash": "sha256:04e85c4cddb58252f8253d78a3924bb56952dac2a3e9a057704a91a0d1f21d75", + "hash": "sha256:759ed27cf3d473445e33141089b652082c42a2c59eb822d6b506146fd9555e13", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-parachains-spawn-chains-zombienet", - "title": "Zombienet", - "slug": "develop-toolkit-parachains-spawn-chains-zombienet", + "id": "parachains-install-polkadot-sdk", + "title": "Install Polkadot SDK", + "slug": "parachains-install-polkadot-sdk", "categories": [ - "Uncategorized" + "Basics", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/zombienet/", - "preview": "Zombienet is a testing framework that lets you quickly spin up ephemeral blockchain networks for development and testing. With support for multiple deployment targets, such as Kubernetes, Podman, and native environments, Zombienet makes it easy to validate your blockchain implementation in a controlled environment.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md", + "html_url": "https://docs.polkadot.com/parachains/install-polkadot-sdk/", + "preview": "This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts:", "outline": [ { "depth": 2, - "title": "What Can I Do with Zombienet?", - "anchor": "what-can-i-do-with-zombienet" + "title": "Install Dependencies: macOS", + "anchor": "install-dependencies-macos" + }, + { + "depth": 3, + "title": "Before You Begin {: #before-you-begin-mac-os }", + "anchor": "before-you-begin-before-you-begin-mac-os" + }, + { + "depth": 3, + "title": "Install Homebrew", + "anchor": "install-homebrew" + }, + { + "depth": 3, + "title": "Support for Apple Silicon", + "anchor": "support-for-apple-silicon" + }, + { + "depth": 3, + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-mac-os" + }, + { + "depth": 2, + "title": "Install Dependencies: Linux", + "anchor": "install-dependencies-linux" + }, + { + "depth": 3, + "title": "Before You Begin {: #before-you-begin-linux }", + "anchor": "before-you-begin-before-you-begin-linux" + }, + { + "depth": 3, + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-linux }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-linux" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Install Dependencies: Windows (WSL)", + "anchor": "install-dependencies-windows-wsl" + }, + { + "depth": 3, + "title": "Before You Begin {: #before-you-begin-windows-wls }", + "anchor": "before-you-begin-before-you-begin-windows-wls" + }, + { + "depth": 3, + "title": "Set Up Windows Subsystem for Linux", + "anchor": "set-up-windows-subsystem-for-linux" + }, + { + "depth": 3, + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-windows-wls" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Build the Polkadot SDK", + "anchor": "build-the-polkadot-sdk" + }, + { + "depth": 3, + "title": "Clone the Polkadot SDK", + "anchor": "clone-the-polkadot-sdk" + }, + { + "depth": 3, + "title": "Compile the Polkadot SDK", + "anchor": "compile-the-polkadot-sdk" + }, + { + "depth": 3, + "title": "Verify the Build", + "anchor": "verify-the-build" + }, + { + "depth": 2, + "title": "Optional: Run the Kitchensink Node", + "anchor": "optional-run-the-kitchensink-node" + }, + { + "depth": 3, + "title": "Run the Kitchensink Node in Development Mode", + "anchor": "run-the-kitchensink-node-in-development-mode" + }, + { + "depth": 3, + "title": "Interact with the Kitchensink Node", + "anchor": "interact-with-the-kitchensink-node" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 1237, - "words": 164, - "headings": 3, - "estimated_token_count_total": 193 + "chars": 16051, + "words": 2312, + "headings": 20, + "estimated_token_count_total": 3345 }, - "hash": "sha256:1355969b6b0e723b42815b960c15eb128e4d936d0d707cd66e43820cff765ee3", + "hash": "sha256:a52c05b623f3780f14be3a5f36b3d79a6c1965c2fbfd6864b512a9a70c47cd60", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-parachains-spawn-chains", - "title": "Spawn Networks for Testing", - "slug": "develop-toolkit-parachains-spawn-chains", + "id": "parachains-integrations-indexers", + "title": "Indexers", + "slug": "parachains-integrations-indexers", "categories": [ - "Uncategorized" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/spawn-chains/", - "preview": "Testing blockchain networks in a controlled environment is essential for development and validation. The Polkadot ecosystem provides specialized tools that enable you to spawn test networks, helping you verify functionality and catch issues before deploying to production.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/indexers/", + "preview": "Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges:", "outline": [ { "depth": 2, - "title": "Why Spawn a Network?", - "anchor": "why-spawn-a-network" + "title": "The Challenge of Blockchain Data Access", + "anchor": "the-challenge-of-blockchain-data-access" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "What is a Blockchain Indexer?", + "anchor": "what-is-a-blockchain-indexer" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Indexer Implementations", + "anchor": "indexer-implementations" } ], "stats": { - "chars": 1180, - "words": 155, + "chars": 2230, + "words": 302, "headings": 3, - "estimated_token_count_total": 171 + "estimated_token_count_total": 428 }, - "hash": "sha256:f11bfd20cb9a0932ce263b2dd763729320261bb25e1fa0039a45ccc609541391", + "hash": "sha256:cfcc76bb24779c9b613f2c046b6f99a0f2529c25fd82287d804f6b945b936227", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit-parachains", - "title": "Parachains", - "slug": "develop-toolkit-parachains", + "id": "parachains-integrations-oracles", + "title": "Oracles", + "slug": "parachains-integrations-oracles", "categories": [ - "Uncategorized" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/parachains/", - "preview": "Within the Polkadot ecosystem, you'll find a robust set of development tools that empower developers to build, test, and deploy blockchain applications efficiently. Whether you're designing a custom parachain, testing new features, or validating network configurations, these tools streamline the development process and ensure your blockchain setup is secure and optimized.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/oracles/", + "preview": "Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the \"blockchain oracle problem.\" Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain.", "outline": [ { "depth": 2, - "title": "Quick Links", - "anchor": "quick-links" + "title": "What is a Blockchain Oracle?", + "anchor": "what-is-a-blockchain-oracle" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } + "title": "Oracle Implementations", + "anchor": "oracle-implementations" + } ], "stats": { - "chars": 986, - "words": 136, + "chars": 1343, + "words": 181, "headings": 2, - "estimated_token_count_total": 106 + "estimated_token_count_total": 245 }, - "hash": "sha256:88dda8aeab06294ccb773d8732d4791b052351ed0b1307d62019a637c9be341a", + "hash": "sha256:6d8e01281a5895fd2bc4438b24c170c72a496de0b838626a53e87685aea4aa25", "token_estimator": "heuristic-v1" }, { - "id": "develop-toolkit", - "title": "Toolkit", - "slug": "develop-toolkit", + "id": "parachains-integrations-wallets", + "title": "Wallets", + "slug": "parachains-integrations-wallets", "categories": [ - "Uncategorized" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit.md", - "html_url": "https://docs.polkadot.com/develop/toolkit/", - "preview": "Explore Polkadot's core development toolkit, designed to support a variety of developers and use cases within the ecosystem. Whether you're building blockchain infrastructure, developing cross-chain applications, or integrating with external services, this section offers essential tools and resources to help you succeed.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/wallets/", + "preview": "A wallet serves as your gateway to interacting with blockchain networks. Rather than storing funds, wallets secure your private keys, controlling access to your blockchain assets. Your private key provides complete control over all permitted transactions on your blockchain account, making it essential to keep it secure.", "outline": [ { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "What is a Blockchain Wallet?", + "anchor": "what-is-a-blockchain-wallet" + }, + { + "depth": 2, + "title": "Hot Wallets", + "anchor": "hot-wallets" + }, + { + "depth": 2, + "title": "Cold Wallets", + "anchor": "cold-wallets" + }, + { + "depth": 2, + "title": "Wallet Tools", + "anchor": "wallet-tools" } ], "stats": { - "chars": 902, - "words": 113, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 3588, + "words": 489, + "headings": 4, + "estimated_token_count_total": 786 }, - "hash": "sha256:20c667a337791538e3997f1f449bf69b248ccc4cc806e22615075f24fd3f0202", + "hash": "sha256:1c65342056983806d639fb8393fdfbdf2ef644ffd41ed749947a16fb3839753d", "token_estimator": "heuristic-v1" }, { - "id": "develop", - "title": "Develop", - "slug": "develop", + "id": "parachains-interoperability-channels-between-parachains", + "title": "Opening HRMP Channels Between Parachains", + "slug": "parachains-interoperability-channels-between-parachains", "categories": [ - "Uncategorized" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop.md", - "html_url": "https://docs.polkadot.com/develop/", - "preview": "This guide is a starting point for developers who wish to build in the Polkadot ecosystem. To get the most from this section:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/", + "preview": "For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required:", "outline": [ { "depth": 2, @@ -3425,314 +2929,243 @@ }, { "depth": 2, - "title": "Development Pathways", - "anchor": "development-pathways" + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Procedure to Initiate an HRMP Channel", + "anchor": "procedure-to-initiate-an-hrmp-channel" }, { "depth": 3, - "title": "Parachain Developers", - "anchor": "parachain-developers" + "title": "Fund Sender Sovereign Account", + "anchor": "fund-sender-sovereign-account" }, { "depth": 3, - "title": "Smart Contract Developers", - "anchor": "smart-contract-developers" + "title": "Create Channel Opening Extrinsic", + "anchor": "create-channel-opening-extrinsic" }, { "depth": 3, - "title": "Application Developers", - "anchor": "application-developers" + "title": "Craft and Submit the XCM Message from the Sender", + "anchor": "craft-and-submit-the-xcm-message-from-the-sender" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 6923, - "words": 882, - "headings": 6, - "estimated_token_count_total": 1843 - }, - "hash": "sha256:1784f7b9e0552ab893c9d7d252299d53e36b6f57ef57c49cd5e36805399675ab", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support-ai-ready-docs", - "title": "AI Ready Docs", - "slug": "get-support-ai-ready-docs", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-ai-ready-docs.md", - "html_url": "https://docs.polkadot.com/get-support/ai-ready-docs/", - "preview": "Polkadot provides files to make documentation content available in a structure optimized for use with large language models (LLMs) and AI tools. These resources help build AI assistants, power code search, or enable custom tooling trained on Polkadot’s documentation.", - "outline": [ + "title": "Procedure to Accept an HRMP Channel", + "anchor": "procedure-to-accept-an-hrmp-channel" + }, { - "depth": 2, - "title": "How to Use These Files", - "anchor": "how-to-use-these-files" + "depth": 3, + "title": "Fund Receiver Sovereign Account", + "anchor": "fund-receiver-sovereign-account" }, { - "depth": 2, - "title": "Download LLM Files", - "anchor": "download-llm-files" + "depth": 3, + "title": "Create Channel Accepting Extrinsic", + "anchor": "create-channel-accepting-extrinsic" + }, + { + "depth": 3, + "title": "Craft and Submit the XCM Message from the Receiver", + "anchor": "craft-and-submit-the-xcm-message-from-the-receiver" } ], "stats": { - "chars": 7998, - "words": 825, - "headings": 2, - "estimated_token_count_total": 2232 + "chars": 10934, + "words": 1549, + "headings": 10, + "estimated_token_count_total": 2285 }, - "hash": "sha256:5a8da69a5cea8bd598ee4d102b9abed5d1a29153802a567e22bb4ee720410b32", + "hash": "sha256:b8de1228b9976765accd18ff724038bed6f2449367f500bc3177ab2a053abe63", "token_estimator": "heuristic-v1" }, { - "id": "get-support-explore-resources", - "title": "Subscribe to Updates", - "slug": "get-support-explore-resources", + "id": "parachains-interoperability-channels-with-system-parachains", + "title": "Opening HRMP Channels with System Parachains", + "slug": "parachains-interoperability-channels-with-system-parachains", "categories": [ - "Uncategorized" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md", - "html_url": "https://docs.polkadot.com/get-support/explore-resources/", - "preview": "Looking for answers beyond the documentation? These platforms are full of useful content and experienced developers sharing insights.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/", + "preview": "While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach.", "outline": [ { "depth": 2, - "title": "🧠 Stack Exchange", - "anchor": "stack-exchange" - }, - { - "depth": 2, - "title": "🧵 Reddit: r/Polkadot", - "anchor": "reddit-rpolkadot" - }, - { - "depth": 2, - "title": "💬 Discord (Community Threads Only)", - "anchor": "discord-community-threads-only" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "🎥 YouTube: @PolkadotNetwork", - "anchor": "youtube-polkadotnetwork" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Community-Led Platforms and Ecosystem Updates", - "anchor": "community-led-platforms-and-ecosystem-updates" - }, - { - "depth": 3, - "title": "🔷 X (Twitter): Official Accounts", - "anchor": "x-twitter-official-accounts" - }, - { - "depth": 3, - "title": "🔁 X (Twitter): Community Accounts", - "anchor": "x-twitter-community-accounts" + "title": "Procedure to Establish an HRMP Channel", + "anchor": "procedure-to-establish-an-hrmp-channel" }, { "depth": 3, - "title": "🗣️ Polkadot Forum", - "anchor": "polkadot-forum" + "title": "Fund Parachain Sovereign Account", + "anchor": "fund-parachain-sovereign-account" }, { "depth": 3, - "title": "🧑‍⚖️ Polkassembly: OpenGov", - "anchor": "polkassembly-opengov" + "title": "Create Establish Channel with System Extrinsic", + "anchor": "create-establish-channel-with-system-extrinsic" }, { "depth": 3, - "title": "📸 Instagram", - "anchor": "instagram" + "title": "Craft and Submit the XCM Message", + "anchor": "craft-and-submit-the-xcm-message" } ], "stats": { - "chars": 2426, - "words": 295, - "headings": 10, - "estimated_token_count_total": 579 + "chars": 7203, + "words": 889, + "headings": 6, + "estimated_token_count_total": 1427 }, - "hash": "sha256:4c33d0ec5026128b3bfdb1dfc1f4b29487404eaa8043071d536e8638356c6e1f", + "hash": "sha256:b501d99c464fb049d46676827b6a325a195c90617becc4a7db305441c115350a", "token_estimator": "heuristic-v1" }, { - "id": "get-support-get-in-touch", - "title": "Get in Touch", - "slug": "get-support-get-in-touch", + "id": "parachains-interoperability-get-started", + "title": "Introduction to XCM", + "slug": "parachains-interoperability-get-started", "categories": [ - "Uncategorized" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-get-in-touch.md", - "html_url": "https://docs.polkadot.com/get-support/get-in-touch/", - "preview": "Use one of the channels below to get live technical support or ask questions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/get-started/", + "preview": "Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.", "outline": [ { "depth": 2, - "title": "Need Help Fast?", - "anchor": "need-help-fast" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "📱 Telegram: Polkadot Developer Support", - "anchor": "telegram-polkadot-developer-support" + "title": "Messaging Format", + "anchor": "messaging-format" }, { "depth": 2, - "title": "🔌 Discord: Polkadot Official Server", - "anchor": "discord-polkadot-official-server" + "title": "The Four Principles of XCM", + "anchor": "the-four-principles-of-xcm" }, { "depth": 2, - "title": "🧬 Matrix: Polkadot Developer Support", - "anchor": "matrix-polkadot-developer-support" + "title": "The XCM Tech Stack", + "anchor": "the-xcm-tech-stack" + }, + { + "depth": 2, + "title": "Core Functionalities of XCM", + "anchor": "core-functionalities-of-xcm" + }, + { + "depth": 2, + "title": "XCM Example", + "anchor": "xcm-example" + }, + { + "depth": 2, + "title": "Overview", + "anchor": "overview" } ], "stats": { - "chars": 1949, - "words": 258, - "headings": 4, - "estimated_token_count_total": 557 + "chars": 7450, + "words": 974, + "headings": 7, + "estimated_token_count_total": 1501 }, - "hash": "sha256:993e93b05c8fbdfc2f7510c61ac86bc4c2ff0f03e573695b2f260933c8b62f78", + "hash": "sha256:3b26606dd5310c4b8ade5d05270ebf1e06f59afcda4ca2b985e07948215a197e", "token_estimator": "heuristic-v1" }, { - "id": "get-support", - "title": "Support", - "slug": "get-support", + "id": "parachains-launch-a-parachain-deploy-to-polkadot", + "title": "Deploy on Polkadot", + "slug": "parachains-launch-a-parachain-deploy-to-polkadot", "categories": [ - "Uncategorized" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support.md", - "html_url": "https://docs.polkadot.com/get-support/", - "preview": "Use one of the channels below to get live technical support or ask questions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-deploy-to-polkadot.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/deploy-to-polkadot/", + "preview": "Previously, you learned how to [choose and set up a parachain template](/parachains/launch-a-parachain/choose-a-template/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to the Polkadot TestNet. Deploying to a TestNet is a crucial step for validating your parachain's functionality and preparing it for eventual MainNet deployment.", "outline": [ { "depth": 2, - "title": "Need More than Just Documentation?", - "anchor": "need-more-than-just-documentation" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "What You Can Do Here", - "anchor": "what-you-can-do-here" + "title": "Get Started with an Account and Tokens", + "anchor": "get-started-with-an-account-and-tokens" }, { "depth": 2, - "title": "Help Us Improve", - "anchor": "help-us-improve" - } - ], - "stats": { - "chars": 1658, - "words": 244, - "headings": 3, - "estimated_token_count_total": 280 - }, - "hash": "sha256:5bdc575ac798a971867a15651c2b4d5139bf0b1fe6854d1865deff280ae6d7f6", - "token_estimator": "heuristic-v1" - }, - { - "id": "index", - "title": "Polkadot Developer Docs", - "slug": "index", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/index.md", - "html_url": "https://docs.polkadot.com/index/", - "preview": "Explore everything you need to start building on top of Polkadot, a protocol that provides parachains with shared security and interoperability using XCM.", - "outline": [], - "stats": { - "chars": 0, - "words": 0, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-node-bootnode", - "title": "Set Up a Bootnode", - "slug": "nodes-and-validators-run-a-node-bootnode", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-bootnode.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/bootnode/", - "preview": "Bootnodes are essential for helping blockchain nodes discover peers and join the network. When a node starts, it needs to find other nodes, and bootnodes provide an initial point of contact. Once connected, a node can expand its peer connections and play its role in the network, like participating as a validator.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Reserve a Parachain Identifier", + "anchor": "reserve-a-parachain-identifier" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Generate Custom Keys for Your Collators", + "anchor": "generate-custom-keys-for-your-collators" }, { "depth": 2, - "title": "Accessing the Bootnode", - "anchor": "accessing-the-bootnode" + "title": "Generate the Chain Specification", + "anchor": "generate-the-chain-specification" }, { "depth": 2, - "title": "Node Key", - "anchor": "node-key" + "title": "Export Required Files", + "anchor": "export-required-files" }, { "depth": 2, - "title": "Running the Bootnode", - "anchor": "running-the-bootnode" + "title": "Register a Parathread", + "anchor": "register-a-parathread" }, { "depth": 2, - "title": "Testing Bootnode Connection", - "anchor": "testing-bootnode-connection" - }, - { - "depth": 3, - "title": "P2P", - "anchor": "p2p" - }, - { - "depth": 3, - "title": "P2P/WS", - "anchor": "p2pws" + "title": "Start the Collator Node", + "anchor": "start-the-collator-node" }, { - "depth": 3, - "title": "P2P/WSS", - "anchor": "p2pwss" + "depth": 2, + "title": "Producing Blocks", + "anchor": "producing-blocks" } ], "stats": { - "chars": 4538, - "words": 647, + "chars": 20252, + "words": 2357, "headings": 9, - "estimated_token_count_total": 1044 + "estimated_token_count_total": 4129 }, - "hash": "sha256:d84a5af1a0237a911d25a68c077f508ebbce608f673ef4f9055e8e434daa96b9", + "hash": "sha256:7309d3487c653951bf264013eb3402a72a1cbb5e0b6f89ae4e678f239cd63b80", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-node-full-node", - "title": "Set Up a Node", - "slug": "nodes-and-validators-run-a-node-full-node", + "id": "parachains-launch-a-parachain-obtain-coretime", + "title": "Obtain Coretime", + "slug": "parachains-launch-a-parachain-obtain-coretime", "categories": [ - "Infrastructure" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-full-node.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/full-node/", - "preview": "Running a node on Polkadot provides direct interaction with the network, enhanced privacy, and full control over RPC requests, transactions, and data queries. As the backbone of the network, nodes ensure decentralized data propagation, transaction validation, and seamless communication across the ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/", + "preview": "After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime.", "outline": [ { "depth": 2, @@ -3741,64 +3174,80 @@ }, { "depth": 2, - "title": "Set Up a Node", - "anchor": "set-up-a-node" - }, - { - "depth": 3, "title": "Prerequisites", "anchor": "prerequisites" }, + { + "depth": 2, + "title": "Order On-Demand Coretime", + "anchor": "order-on-demand-coretime" + }, { "depth": 3, - "title": "Install and Build the Polkadot Binary", - "anchor": "install-and-build-the-polkadot-binary" + "title": "On-Demand Extrinsics", + "anchor": "on-demand-extrinsics" }, { "depth": 3, - "title": "Use Docker", - "anchor": "use-docker" + "title": "Place an On-Demand Order", + "anchor": "place-an-on-demand-order" }, { "depth": 2, - "title": "Configure and Run Your Node", - "anchor": "configure-and-run-your-node" + "title": "Purchase Bulk Coretime", + "anchor": "purchase-bulk-coretime" }, { "depth": 3, - "title": "RPC Configurations", - "anchor": "rpc-configurations" + "title": "Connect Your Wallet to RegionX", + "anchor": "connect-your-wallet-to-regionx" }, { - "depth": 2, - "title": "Sync Your Node", - "anchor": "sync-your-node" + "depth": 3, + "title": "Obtain Coretime Chain Funds", + "anchor": "obtain-coretime-chain-funds" }, { "depth": 3, - "title": "Connect to Your Node", - "anchor": "connect-to-your-node" + "title": "Purchase a Core", + "anchor": "purchase-a-core" + }, + { + "depth": 3, + "title": "Verify Your Purchase", + "anchor": "verify-your-purchase" + }, + { + "depth": 3, + "title": "Assign Your Parachain to the Core", + "anchor": "assign-your-parachain-to-the-core" + }, + { + "depth": 2, + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 15944, - "words": 2481, - "headings": 9, - "estimated_token_count_total": 4196 + "chars": 9049, + "words": 1345, + "headings": 12, + "estimated_token_count_total": 2103 }, - "hash": "sha256:b83e3f77bd30ac8c8fb00a193bbec33cd641d94f1a37ac611dea32326c3d77b0", + "hash": "sha256:15154f211753665d9af70dc81d15ceb3f0954e3febf9282c68c0074881d620c6", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-node-secure-wss", - "title": "Set Up Secure WebSocket", - "slug": "nodes-and-validators-run-a-node-secure-wss", + "id": "parachains-launch-a-parachain-set-up-the-parachain-template", + "title": "Set Up the Polkadot SDK Parachain Template", + "slug": "parachains-launch-a-parachain-set-up-the-parachain-template", "categories": [ - "Infrastructure" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-secure-wss.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/secure-wss/", - "preview": "Ensuring secure WebSocket communication is crucial for maintaining the integrity and security of a Polkadot or Kusama node when interacting with remote clients. This guide walks you through setting up a secure WebSocket (WSS) connection for your node by leveraging SSL encryption with popular web server proxies like nginx or Apache.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/", + "preview": "The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs.", "outline": [ { "depth": 2, @@ -3807,54 +3256,74 @@ }, { "depth": 2, - "title": "Secure a WebSocket Port", - "anchor": "secure-a-websocket-port" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Obtain an SSL Certificate", - "anchor": "obtain-an-ssl-certificate" + "depth": 2, + "title": "Polkadot SDK Utility Tools", + "anchor": "polkadot-sdk-utility-tools" }, { "depth": 2, - "title": "Install a Proxy Server", - "anchor": "install-a-proxy-server" + "title": "Clone the Template", + "anchor": "clone-the-template" }, { - "depth": 3, - "title": "Use nginx", - "anchor": "use-nginx" + "depth": 2, + "title": "Explore the Project Structure", + "anchor": "explore-the-project-structure" }, { - "depth": 3, - "title": "Use Apache2", - "anchor": "use-apache2" + "depth": 2, + "title": "Compile the Runtime", + "anchor": "compile-the-runtime" }, { "depth": 2, - "title": "Connect to the Node", - "anchor": "connect-to-the-node" + "title": "Verify the Build", + "anchor": "verify-the-build" + }, + { + "depth": 2, + "title": "Run the Node Locally", + "anchor": "run-the-node-locally" + }, + { + "depth": 2, + "title": "Interact with the Node", + "anchor": "interact-with-the-node" + }, + { + "depth": 2, + "title": "Stop the Node", + "anchor": "stop-the-node" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 5568, - "words": 774, - "headings": 7, - "estimated_token_count_total": 1280 + "chars": 10588, + "words": 1510, + "headings": 11, + "estimated_token_count_total": 2375 }, - "hash": "sha256:992082e4ad87348b283f6c37ea886ae0e7bf016852b6470000876f3d169c65a4", + "hash": "sha256:380063fe7c00ae8bde05fa76688b8ae4902e6566147f1cfe0e0260ad1aa05aa6", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", - "title": "Validator Key Management", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", + "id": "parachains-runtime-maintenance-runtime-upgrades", + "title": "Runtime Upgrades", + "slug": "parachains-runtime-maintenance-runtime-upgrades", "categories": [ - "Infrastructure" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/", - "preview": "After setting up your node environment as shown in the [Setup](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/){target=\\_blank} section, you'll need to configure multiple keys for your validator to operate properly. This includes setting up session keys, which are essential for participating in the consensus process, and configuring a node key that maintains a stable network identity. This guide walks you through the key management process, showing you how to g", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/", + "preview": "One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.", "outline": [ { "depth": 2, @@ -3863,59 +3332,44 @@ }, { "depth": 2, - "title": "Set Session Keys", - "anchor": "set-session-keys" + "title": "How Runtime Upgrades Work", + "anchor": "how-runtime-upgrades-work" }, { "depth": 3, - "title": "Generate Session Keys", - "anchor": "generate-session-keys" + "title": "Runtime Versioning", + "anchor": "runtime-versioning" }, { "depth": 3, - "title": "Submit Transaction to Set Keys", - "anchor": "submit-transaction-to-set-keys" - }, - { - "depth": 3, - "title": "Verify Session Key Setup", - "anchor": "verify-session-key-setup" + "title": "Accessing the Runtime Version", + "anchor": "accessing-the-runtime-version" }, { "depth": 2, - "title": "Set the Node Key", - "anchor": "set-the-node-key" - }, - { - "depth": 3, - "title": "Generate the Node Key", - "anchor": "generate-the-node-key" - }, - { - "depth": 3, - "title": "Set Node Key", - "anchor": "set-node-key" + "title": "Storage Migrations", + "anchor": "storage-migrations" } ], "stats": { - "chars": 8227, - "words": 1183, - "headings": 8, - "estimated_token_count_total": 1840 + "chars": 5837, + "words": 811, + "headings": 5, + "estimated_token_count_total": 1161 }, - "hash": "sha256:0fb5a83835aab263c0b9aa886028c8aa8a2d6d0897d7b9fff4b5258835d30dfe", + "hash": "sha256:ec31270001a6cd9d0a8ecb7974ad161d5c1ef4d3023d5a6af9fbc5a6ca46cbca", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", - "title": "Set Up a Validator", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", + "id": "parachains-runtime-maintenance-storage-migrations", + "title": "Storage Migrations", + "slug": "parachains-runtime-maintenance-storage-migrations", "categories": [ - "Infrastructure" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/", - "preview": "Setting up a Polkadot validator node is essential for securing the network and earning staking rewards. This guide walks you through the technical steps to set up a validator, from installing the necessary software to managing keys and synchronizing your node with the chain.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/", + "preview": "Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime", "outline": [ { "depth": 2, @@ -3924,79 +3378,69 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Storage Migration Scenarios", + "anchor": "storage-migration-scenarios" }, { "depth": 2, - "title": "Initial Setup", - "anchor": "initial-setup" - }, - { - "depth": 3, - "title": "Install Network Time Protocol Client", - "anchor": "install-network-time-protocol-client" + "title": "Implement Storage Migrations", + "anchor": "implement-storage-migrations" }, { "depth": 3, - "title": "Verify Landlock is Activated", - "anchor": "verify-landlock-is-activated" - }, - { - "depth": 2, - "title": "Install the Polkadot Binaries", - "anchor": "install-the-polkadot-binaries" + "title": "Core Migration Function", + "anchor": "core-migration-function" }, { "depth": 3, - "title": "Install from Official Releases", - "anchor": "install-from-official-releases" + "title": "Migration Testing Hooks", + "anchor": "migration-testing-hooks" }, { "depth": 3, - "title": "Install with Package Managers", - "anchor": "install-with-package-managers" + "title": "Migration Structure", + "anchor": "migration-structure" }, { "depth": 3, - "title": "Install with Ansible", - "anchor": "install-with-ansible" + "title": "Migration Organization", + "anchor": "migration-organization" }, { "depth": 3, - "title": "Install with Docker", - "anchor": "install-with-docker" + "title": "Scheduling Migrations", + "anchor": "scheduling-migrations" }, { - "depth": 3, - "title": "Build from Sources", - "anchor": "build-from-sources" + "depth": 2, + "title": "Single-Block Migrations", + "anchor": "single-block-migrations" }, { "depth": 2, - "title": "Verify Installation", - "anchor": "verify-installation" + "title": "Multi Block Migrations", + "anchor": "multi-block-migrations" } ], "stats": { - "chars": 11921, - "words": 1678, - "headings": 12, - "estimated_token_count_total": 2592 + "chars": 18500, + "words": 2363, + "headings": 10, + "estimated_token_count_total": 4014 }, - "hash": "sha256:d2c1c91734bc8185057d8eeec6829ea91e0316f7ba884c5dc3922a5e5778815e", + "hash": "sha256:55dc252fdecf1590048ce8d009b822e90231442abe81e9593cf1635944a31336", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", - "title": "Start Validating", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", + "id": "parachains-runtime-maintenance-unlock-parachains", + "title": "Unlock a Parachain", + "slug": "parachains-runtime-maintenance-unlock-parachains", "categories": [ - "Infrastructure" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/start-validating/", - "preview": "After configuring your node keys as shown in the [Key Management](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/){target=\\_blank} section and ensuring your system is set up, you're ready to begin the validator setup process. This guide will walk you through choosing a network, synchronizing your node with the blockchain, bonding your DOT tokens, and starting your validator.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-unlock-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/unlock-parachains/", + "preview": "Parachain locks are a critical security mechanism in the Polkadot ecosystem designed to maintain decentralization during the parachain lifecycle. These locks prevent potential centralization risks that could emerge during the early stages of parachain operation.", "outline": [ { "depth": 2, @@ -4005,84 +3449,122 @@ }, { "depth": 2, - "title": "Choose a Network", - "anchor": "choose-a-network" + "title": "Check If the Parachain Is Locked", + "anchor": "check-if-the-parachain-is-locked" }, { "depth": 2, - "title": "Synchronize Chain Data", - "anchor": "synchronize-chain-data" + "title": "How to Unlock a Parachain", + "anchor": "how-to-unlock-a-parachain" }, { "depth": 3, - "title": "Database Snapshot Services", - "anchor": "database-snapshot-services" + "title": "Prepare the Unlock Call", + "anchor": "prepare-the-unlock-call" }, { - "depth": 2, - "title": "Bond DOT", - "anchor": "bond-dot" + "depth": 3, + "title": "Fund the Sovereign Account", + "anchor": "fund-the-sovereign-account" }, { "depth": 3, - "title": "Bonding DOT on Polkadot.js Apps", - "anchor": "bonding-dot-on-polkadotjs-apps" + "title": "Craft and Submit the XCM", + "anchor": "craft-and-submit-the-xcm" + } + ], + "stats": { + "chars": 9232, + "words": 1276, + "headings": 6, + "estimated_token_count_total": 2028 + }, + "hash": "sha256:e408d05199cc184fc6fe8bb212efb3c9aa6cb79258977e07566692176c912def", + "token_estimator": "heuristic-v1" + }, + { + "id": "parachains-testing-fork-a-parachain", + "title": "Get Started", + "slug": "parachains-testing-fork-a-parachain", + "categories": [ + "Parachains", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md", + "html_url": "https://docs.polkadot.com/parachains/testing/fork-a-parachain/", + "preview": "[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Validate", - "anchor": "validate" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Verify Sync via Telemetry", - "anchor": "verify-sync-via-telemetry" + "depth": 2, + "title": "Install Chopsticks", + "anchor": "install-chopsticks" }, { "depth": 3, - "title": "Activate using Polkadot.js Apps", - "anchor": "activate-using-polkadotjs-apps" + "title": "Global Installation", + "anchor": "global-installation" }, { "depth": 3, - "title": "Monitor Validation Status and Slots", - "anchor": "monitor-validation-status-and-slots" + "title": "Local Installation", + "anchor": "local-installation" }, { "depth": 2, - "title": "Run a Validator Using Systemd", - "anchor": "run-a-validator-using-systemd" + "title": "Configure Chopsticks", + "anchor": "configure-chopsticks" }, { "depth": 3, - "title": "Create the Systemd Service File", - "anchor": "create-the-systemd-service-file" + "title": "Configuration File", + "anchor": "configuration-file" }, { "depth": 3, - "title": "Run the Service", - "anchor": "run-the-service" + "title": "CLI Flags", + "anchor": "cli-flags" + }, + { + "depth": 2, + "title": "WebSocket Commands", + "anchor": "websocket-commands" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 15820, - "words": 2446, - "headings": 13, - "estimated_token_count_total": 3861 + "chars": 10894, + "words": 1330, + "headings": 10, + "estimated_token_count_total": 2614 }, - "hash": "sha256:c74cfa542fe7a5235b81120f0004576aea83e0d35458201689b68d87f2969749", + "hash": "sha256:4325cdd697814b8043db808da3dee86d3d9c6fc7dd523aae7fe8914d59d1b39c", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", - "title": "Stop Validating", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", + "id": "parachains-testing-run-a-parachain-network", + "title": "Get Started", + "slug": "parachains-testing-run-a-parachain-network", "categories": [ - "Infrastructure" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/", - "preview": "If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md", + "html_url": "https://docs.polkadot.com/parachains/testing/run-a-parachain-network/", + "preview": "Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.", "outline": [ { "depth": 2, @@ -4091,516 +3573,425 @@ }, { "depth": 2, - "title": "Pause Versus Stop", - "anchor": "pause-versus-stop" + "title": "Install Zombienet", + "anchor": "install-zombienet" }, { "depth": 2, - "title": "Chill Validator", - "anchor": "chill-validator" + "title": "Providers", + "anchor": "providers" }, { - "depth": 2, - "title": "Purge Validator Session Keys", - "anchor": "purge-validator-session-keys" + "depth": 3, + "title": "Kubernetes", + "anchor": "kubernetes" + }, + { + "depth": 3, + "title": "Podman", + "anchor": "podman" + }, + { + "depth": 3, + "title": "Local Provider", + "anchor": "local-provider" }, { "depth": 2, - "title": "Unbond Your Tokens", - "anchor": "unbond-your-tokens" + "title": "Configure Zombienet", + "anchor": "configure-zombienet" + }, + { + "depth": 3, + "title": "Configuration Files", + "anchor": "configuration-files" + }, + { + "depth": 3, + "title": "CLI Usage", + "anchor": "cli-usage" + }, + { + "depth": 3, + "title": "Settings", + "anchor": "settings" + }, + { + "depth": 3, + "title": "Relay Chain Configuration", + "anchor": "relay-chain-configuration" + }, + { + "depth": 3, + "title": "Parachain Configuration", + "anchor": "parachain-configuration" + }, + { + "depth": 3, + "title": "XCM Configuration", + "anchor": "xcm-configuration" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 3230, - "words": 500, - "headings": 5, - "estimated_token_count_total": 629 + "chars": 41636, + "words": 4599, + "headings": 14, + "estimated_token_count_total": 9871 }, - "hash": "sha256:0d6db361bfa7a3022849bbe39989bfdac0429537498d7f534adadec131afca98", + "hash": "sha256:0d7e04fd952cc9d5bd8cdbfd87cc4004c5f95e896a16bc7f89dfc4caeac8f371", "token_estimator": "heuristic-v1" }, { - "id": "nodes-and-validators-run-a-validator-operational-tasks-general-management", - "title": "General Management", - "slug": "nodes-and-validators-run-a-validator-operational-tasks-general-management", + "id": "reference-glossary", + "title": "Glossary", + "slug": "reference-glossary", "categories": [ - "Infrastructure" + "Reference" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-general-management.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/general-management/", - "preview": "Validator performance is pivotal in maintaining the security and stability of the Polkadot network. As a validator, optimizing your setup ensures efficient transaction processing, minimizes latency, and maintains system reliability during high-demand periods. Proper configuration and proactive monitoring also help mitigate risks like slashing and service interruptions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md", + "html_url": "https://docs.polkadot.com/reference/glossary/", + "preview": "Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Authority", + "anchor": "authority" }, { "depth": 2, - "title": "Configuration Optimization", - "anchor": "configuration-optimization" - }, - { - "depth": 3, - "title": "Deactivate Simultaneous Multithreading", - "anchor": "deactivate-simultaneous-multithreading" + "title": "Authority Round (Aura)", + "anchor": "authority-round-aura" }, { - "depth": 3, - "title": "Deactivate Automatic NUMA Balancing", - "anchor": "deactivate-automatic-numa-balancing" + "depth": 2, + "title": "Blind Assignment of Blockchain Extension (BABE)", + "anchor": "blind-assignment-of-blockchain-extension-babe" }, { - "depth": 3, - "title": "Spectre and Meltdown Mitigations", - "anchor": "spectre-and-meltdown-mitigations" + "depth": 2, + "title": "Block Author", + "anchor": "block-author" }, { "depth": 2, - "title": "Monitor Your Node", - "anchor": "monitor-your-node" + "title": "Byzantine Fault Tolerance (BFT)", + "anchor": "byzantine-fault-tolerance-bft" }, { "depth": 3, - "title": "Environment Setup", - "anchor": "environment-setup" + "title": "Byzantine Failure", + "anchor": "byzantine-failure" }, { "depth": 3, - "title": "Install and Configure Prometheus", - "anchor": "install-and-configure-prometheus" + "title": "Practical Byzantine Fault Tolerance (pBFT)", + "anchor": "practical-byzantine-fault-tolerance-pbft" }, { "depth": 3, - "title": "Start Prometheus", - "anchor": "start-prometheus" + "title": "Preimage", + "anchor": "preimage" }, { - "depth": 3, - "title": "Install and Configure Grafana", - "anchor": "install-and-configure-grafana" + "depth": 2, + "title": "Call", + "anchor": "call" }, { - "depth": 3, - "title": "Install and Configure Alertmanager", - "anchor": "install-and-configure-alertmanager" + "depth": 2, + "title": "Chain Specification", + "anchor": "chain-specification" }, { "depth": 2, - "title": "Secure Your Validator", - "anchor": "secure-your-validator" + "title": "Collator", + "anchor": "collator" }, { - "depth": 3, - "title": "Key Management", - "anchor": "key-management" + "depth": 2, + "title": "Collective", + "anchor": "collective" }, { - "depth": 3, - "title": "Signing Outside the Client", - "anchor": "signing-outside-the-client" + "depth": 2, + "title": "Consensus", + "anchor": "consensus" }, { - "depth": 3, - "title": "Secure-Validator Mode", - "anchor": "secure-validator-mode" + "depth": 2, + "title": "Consensus Algorithm", + "anchor": "consensus-algorithm" }, { - "depth": 3, - "title": "Linux Best Practices", - "anchor": "linux-best-practices" + "depth": 2, + "title": "Consensus Engine", + "anchor": "consensus-engine" }, { - "depth": 3, - "title": "Validator Best Practices", - "anchor": "validator-best-practices" + "depth": 2, + "title": "Coretime", + "anchor": "coretime" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 26673, - "words": 3357, - "headings": 18, - "estimated_token_count_total": 5866 - }, - "hash": "sha256:81eb0fe77f05155f1ec0511cd066120fc9994961e9d91e21b6666377e65b4586", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", - "title": "Pause Validating", - "slug": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-pause-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/", - "preview": "If you need to temporarily stop participating in Polkadot staking activities without fully unbonding your funds, chilling your account allows you to do so efficiently. Chilling removes your node from active validation or nomination in the next era while keeping your funds bonded, making it ideal for planned downtimes or temporary pauses.", - "outline": [ + "title": "Development Phrase", + "anchor": "development-phrase" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Digest", + "anchor": "digest" }, { "depth": 2, - "title": "Chilling Your Node", - "anchor": "chilling-your-node" + "title": "Dispatchable", + "anchor": "dispatchable" }, { "depth": 2, - "title": "Staking Election Timing Considerations", - "anchor": "staking-election-timing-considerations" + "title": "Events", + "anchor": "events" }, { "depth": 2, - "title": "Chilling as a Nominator", - "anchor": "chilling-as-a-nominator" + "title": "Executor", + "anchor": "executor" }, { "depth": 2, - "title": "Chilling as a Validator", - "anchor": "chilling-as-a-validator" + "title": "Existential Deposit", + "anchor": "existential-deposit" }, { "depth": 2, - "title": "Chill Other", - "anchor": "chill-other" - } - ], - "stats": { - "chars": 4439, - "words": 679, - "headings": 6, - "estimated_token_count_total": 861 - }, - "hash": "sha256:1af153570ce57bd5b52d08493a300996765686f2a6d04519a2e0aa91191612c1", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", - "title": "Upgrade a Validator Node", - "slug": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/upgrade-your-node/", - "preview": "Upgrading a Polkadot validator node is essential for staying current with network updates and maintaining optimal performance. This guide covers routine and extended maintenance scenarios, including software upgrades and major server changes. Following these steps, you can manage session keys and transition smoothly between servers without risking downtime, slashing, or network disruptions. The process requires strategic planning, especially if you need to perform long-lead maintenance, ensuring", - "outline": [ + "title": "Extrinsic", + "anchor": "extrinsic" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Fork Choice Rule/Strategy", + "anchor": "fork-choice-rulestrategy" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "FRAME (Framework for Runtime Aggregation of Modularized Entities)", + "anchor": "frame-framework-for-runtime-aggregation-of-modularized-entities" }, { "depth": 2, - "title": "Session Keys", - "anchor": "session-keys" + "title": "Full Node", + "anchor": "full-node" }, { "depth": 2, - "title": "Keystore", - "anchor": "keystore" + "title": "Genesis Configuration", + "anchor": "genesis-configuration" }, { "depth": 2, - "title": "Upgrade Using Backup Validator", - "anchor": "upgrade-using-backup-validator" + "title": "GRANDPA", + "anchor": "grandpa" }, { - "depth": 3, - "title": "Session `N`", - "anchor": "session-n" + "depth": 2, + "title": "Header", + "anchor": "header" }, - { - "depth": 3, - "title": "Session `N+3`", - "anchor": "session-n3" - } - ], - "stats": { - "chars": 5650, - "words": 851, - "headings": 7, - "estimated_token_count_total": 1185 - }, - "hash": "sha256:888230b128d8c648c4f06a18d3b1d1b06dd1bf22a0de4add1f28210ffccb2549", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-requirements", - "title": "Validator Requirements", - "slug": "nodes-and-validators-run-a-validator-requirements", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-requirements.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/requirements/", - "preview": "Running a validator in the Polkadot ecosystem is essential for maintaining network security and decentralization. Validators are responsible for validating transactions and adding new blocks to the chain, ensuring the system operates smoothly. In return for their services, validators earn rewards. However, the role comes with inherent risks, such as slashing penalties for misbehavior or technical failures. If you’re new to validation, starting on Kusama provides a lower-stakes environment to gai", - "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Hybrid Consensus", + "anchor": "hybrid-consensus" }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Inherent Transactions", + "anchor": "inherent-transactions" }, { "depth": 2, - "title": "Minimum Hardware Requirements", - "anchor": "minimum-hardware-requirements" + "title": "JSON-RPC", + "anchor": "json-rpc" }, { "depth": 2, - "title": "VPS Provider List", - "anchor": "vps-provider-list" + "title": "Keystore", + "anchor": "keystore" }, { "depth": 2, - "title": "Minimum Bond Requirement", - "anchor": "minimum-bond-requirement" - } - ], - "stats": { - "chars": 6842, - "words": 944, - "headings": 5, - "estimated_token_count_total": 1485 - }, - "hash": "sha256:46435b97c37ef6798d2c75c69df31c5e5f07e04b218c370ec5af6b1838d43aac", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", - "title": "Offenses and Slashes", - "slug": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/offenses-and-slashes/", - "preview": "In Polkadot's Nominated Proof of Stake (NPoS) system, validator misconduct is deterred through a combination of slashing, disabling, and reputation penalties. Validators and nominators who stake tokens face consequences for validator misbehavior, which range from token slashes to restrictions on network participation.", - "outline": [ + "title": "Kusama", + "anchor": "kusama" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "libp2p", + "anchor": "libp2p" }, { "depth": 2, - "title": "Offenses", - "anchor": "offenses" + "title": "Light Client", + "anchor": "light-client" }, { - "depth": 3, - "title": "Invalid Votes", - "anchor": "invalid-votes" + "depth": 2, + "title": "Metadata", + "anchor": "metadata" }, { - "depth": 3, - "title": "Equivocations", - "anchor": "equivocations" + "depth": 2, + "title": "Nominated Proof of Stake (NPoS)", + "anchor": "nominated-proof-of-stake-npos" }, { "depth": 2, - "title": "Penalties", - "anchor": "penalties" + "title": "Oracle", + "anchor": "oracle" }, { - "depth": 3, - "title": "Slashing", - "anchor": "slashing" + "depth": 2, + "title": "Origin", + "anchor": "origin" }, { - "depth": 3, - "title": "Disabling", - "anchor": "disabling" + "depth": 2, + "title": "Pallet", + "anchor": "pallet" }, { - "depth": 3, - "title": "Reputation Changes", - "anchor": "reputation-changes" + "depth": 2, + "title": "Parachain", + "anchor": "parachain" }, { - "depth": 3, - "title": "Penalties by Offense", - "anchor": "penalties-by-offense" - } - ], - "stats": { - "chars": 15427, - "words": 2103, - "headings": 9, - "estimated_token_count_total": 3409 - }, - "hash": "sha256:abe6bedab04f463ec07f554977b8d6355a5d2fad9bcda01cbe58568152295daa", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", - "title": "Rewards Payout", - "slug": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-rewards.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/rewards/", - "preview": "Understanding how rewards are distributed to validators and nominators is essential for network participants. In Polkadot and Kusama, validators earn rewards based on their era points, which are accrued through actions like block production and parachain validation.", - "outline": [ + "depth": 2, + "title": "Paseo", + "anchor": "paseo" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Polkadot", + "anchor": "polkadot" }, { "depth": 2, - "title": "Era Points", - "anchor": "era-points" + "title": "Polkadot Cloud", + "anchor": "polkadot-cloud" }, { "depth": 2, - "title": "Reward Variance", - "anchor": "reward-variance" + "title": "Polkadot Hub", + "anchor": "polkadot-hub" }, { "depth": 2, - "title": "Payout Scheme", - "anchor": "payout-scheme" + "title": "PolkaVM", + "anchor": "polkavm" }, { "depth": 2, - "title": "Running Multiple Validators", - "anchor": "running-multiple-validators" + "title": "Relay Chain", + "anchor": "relay-chain" }, { "depth": 2, - "title": "Nominators and Validator Payments", - "anchor": "nominators-and-validator-payments" - } - ], - "stats": { - "chars": 10976, - "words": 1753, - "headings": 6, - "estimated_token_count_total": 2588 - }, - "hash": "sha256:d5d6d72eb2cf10f624d84c65f2274f7df90acb5d071bf170bc8eae8d98a810a5", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-add-existing-pallets", - "title": "Add an Existing Pallet to the Runtime", - "slug": "parachains-customize-runtime-add-existing-pallets", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-existing-pallets.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-existing-pallets/", - "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a functional runtime that includes default [FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} development modules ([pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}) to help you get started building a custo", - "outline": [ + "title": "Rococo", + "anchor": "rococo" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Runtime", + "anchor": "runtime" }, { "depth": 2, - "title": "Check Prerequisites", - "anchor": "check-prerequisites" + "title": "Slot", + "anchor": "slot" }, { "depth": 2, - "title": "Add an Existing Polkadot SDK Pallet to Your Runtime", - "anchor": "add-an-existing-polkadot-sdk-pallet-to-your-runtime" + "title": "Sovereign Account", + "anchor": "sovereign-account" }, { - "depth": 3, - "title": "Add an Existing Pallet as a Dependency", - "anchor": "add-an-existing-pallet-as-a-dependency" + "depth": 2, + "title": "SS58 Address Format", + "anchor": "ss58-address-format" }, { - "depth": 3, - "title": "Enable Standard Library Features", - "anchor": "enable-standard-library-features" + "depth": 2, + "title": "State Transition Function (STF)", + "anchor": "state-transition-function-stf" }, { - "depth": 3, - "title": "Review the Config Trait", - "anchor": "review-the-config-trait" + "depth": 2, + "title": "Storage Item", + "anchor": "storage-item" }, { - "depth": 3, - "title": "Implement the Config Trait", - "anchor": "implement-the-config-trait" + "depth": 2, + "title": "Substrate", + "anchor": "substrate" }, { - "depth": 3, - "title": "Add to Runtime Construct", - "anchor": "add-to-runtime-construct" + "depth": 2, + "title": "Transaction", + "anchor": "transaction" }, { - "depth": 3, - "title": "Verify the Runtime Compiles", - "anchor": "verify-the-runtime-compiles" + "depth": 2, + "title": "Transaction Era", + "anchor": "transaction-era" }, { "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" + "title": "Trie (Patricia Merkle Tree)", + "anchor": "trie-patricia-merkle-tree" }, { - "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" + "depth": 2, + "title": "Validator", + "anchor": "validator" }, { - "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" + "depth": 2, + "title": "WebAssembly (Wasm)", + "anchor": "webassembly-wasm" }, { - "depth": 3, - "title": "Interact with the Pallet", - "anchor": "interact-with-the-pallet" + "depth": 2, + "title": "Weight", + "anchor": "weight" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Westend", + "anchor": "westend" } ], "stats": { - "chars": 11924, - "words": 1585, - "headings": 14, - "estimated_token_count_total": 2724 + "chars": 24739, + "words": 3626, + "headings": 63, + "estimated_token_count_total": 5273 }, - "hash": "sha256:93d123cbaaccc2515b4a70be8e1327b4f75b1051d16c5e3daf5a2035af7b7ca3", + "hash": "sha256:40bd67811e7eabc79ca5d105eae388b19380d9f035022da17fc0d6bb173c817c", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-add-pallet-instances", - "title": "Add Multiple Pallet Instances", - "slug": "parachains-customize-runtime-add-pallet-instances", + "id": "reference-governance-origins-tracks", + "title": "Origins and Tracks", + "slug": "reference-governance-origins-tracks", "categories": [ - "Parachains" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-pallet-instances.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-pallet-instances/", - "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a solid foundation for building custom parachains. While most pallets are typically included as single instances within a runtime, some scenarios benefit from running multiple instances of the same pallet with different configurations. This approach lets you reuse pallet logic without reimplementing it, enabling diverse functionality from a single codebase.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance-origins-tracks.md", + "html_url": "https://docs.polkadot.com/reference/governance/origins-tracks/", + "preview": "Polkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency.", "outline": [ { "depth": 2, @@ -4609,124 +4000,107 @@ }, { "depth": 2, - "title": "Check Prerequisites", - "anchor": "check-prerequisites" + "title": "Origins", + "anchor": "origins" }, { "depth": 2, - "title": "Understanding Instantiable Pallets", - "anchor": "understanding-instantiable-pallets" - }, - { - "depth": 3, - "title": "Identifying an Instantiable Pallet", - "anchor": "identifying-an-instantiable-pallet" - }, - { - "depth": 3, - "title": "How Instance Generics Work", - "anchor": "how-instance-generics-work" + "title": "Tracks", + "anchor": "tracks" }, { "depth": 2, - "title": "Add Multiple Instances of a Pallet to Your Runtime", - "anchor": "add-multiple-instances-of-a-pallet-to-your-runtime" - }, - { - "depth": 3, - "title": "Add the Pallet as a Dependency", - "anchor": "add-the-pallet-as-a-dependency" - }, - { - "depth": 3, - "title": "Enable Standard Library Features", - "anchor": "enable-standard-library-features" - }, - { - "depth": 3, - "title": "Review the Config Trait", - "anchor": "review-the-config-trait" - }, - { - "depth": 3, - "title": "Define Pallet Parameters", - "anchor": "define-pallet-parameters" - }, - { - "depth": 3, - "title": "Create Instance Type Definitions", - "anchor": "create-instance-type-definitions" - }, - { - "depth": 3, - "title": "Implement Config Trait for First Instance", - "anchor": "implement-config-trait-for-first-instance" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 3333, + "words": 469, + "headings": 4, + "estimated_token_count_total": 631 + }, + "hash": "sha256:baba9dd41091b792d09005d55d3df0bf65b35f42b40ebe63caf425a0978a22b0", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-governance", + "title": "On-Chain Governance Overview", + "slug": "reference-governance", + "categories": [ + "Basics", + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md", + "html_url": "https://docs.polkadot.com/reference/governance/", + "preview": "Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model.", + "outline": [ { - "depth": 3, - "title": "Implement Config Trait for Second Instance", - "anchor": "implement-config-trait-for-second-instance" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Add Instances to Runtime Construct", - "anchor": "add-instances-to-runtime-construct" + "depth": 2, + "title": "Governance Evolution", + "anchor": "governance-evolution" }, { - "depth": 3, - "title": "Verify the Runtime Compiles", - "anchor": "verify-the-runtime-compiles" + "depth": 2, + "title": "OpenGov Key Features", + "anchor": "opengov-key-features" }, { "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" + "title": "Origins and Tracks", + "anchor": "origins-and-tracks" }, { - "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" + "depth": 2, + "title": "Referendums", + "anchor": "referendums" }, { "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" + "title": "Vote on Referendums", + "anchor": "vote-on-referendums" }, { "depth": 3, - "title": "Interact with Both Pallet Instances", - "anchor": "interact-with-both-pallet-instances" + "title": "Delegate Voting Power", + "anchor": "delegate-voting-power" }, { "depth": 3, - "title": "Test Instance Independence", - "anchor": "test-instance-independence" + "title": "Cancel a Referendum", + "anchor": "cancel-a-referendum" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 17923, - "words": 2203, - "headings": 21, - "estimated_token_count_total": 3811 + "chars": 7493, + "words": 1019, + "headings": 9, + "estimated_token_count_total": 1611 }, - "hash": "sha256:d83e574726c524fa017236eb5e3b8a0676d598be4da1ce4fe25a60141baeee49", + "hash": "sha256:62beec261e72529f70e07a641177d489d2c8872f9c9d618cbadf1ac0fd881986", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-add-smart-contract-functionality", - "title": "Add Smart Contract Functionality", - "slug": "parachains-customize-runtime-add-smart-contract-functionality", + "id": "reference-parachains-accounts", + "title": "Polkadot SDK Accounts", + "slug": "reference-parachains-accounts", "categories": [ - "Parachains" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-smart-contract-functionality/", - "preview": "When building your custom blockchain with the Polkadot SDK, you can add smart contract capabilities through specialized pallets. These pallets enable users to deploy and execute smart contracts, enhancing your chain's programmability and allowing developers to build decentralized applications on your network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md", + "html_url": "https://docs.polkadot.com/reference/parachains/accounts/", + "preview": "Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains.", "outline": [ { "depth": 2, @@ -4735,100 +4109,95 @@ }, { "depth": 2, - "title": "pallet-revive", - "anchor": "pallet-revive" + "title": "Account Data Structure", + "anchor": "account-data-structure" }, { "depth": 3, - "title": "Core Components", - "anchor": "core-components" + "title": "Account", + "anchor": "account" }, { "depth": 3, - "title": "Supported Languages and Compilers", - "anchor": "supported-languages-and-compilers" + "title": "Account Info", + "anchor": "account-info" }, { "depth": 3, - "title": "How It Works", - "anchor": "how-it-works" + "title": "Account Reference Counters", + "anchor": "account-reference-counters" }, { - "depth": 3, - "title": "Key Benefits", - "anchor": "key-benefits" + "depth": 2, + "title": "Account Balance Types", + "anchor": "account-balance-types" }, { "depth": 3, - "title": "Implementation Examples", - "anchor": "implementation-examples" - }, - { - "depth": 2, - "title": "Frontier", - "anchor": "frontier" + "title": "Balance Types", + "anchor": "balance-types" }, { "depth": 3, - "title": "Integration Options", - "anchor": "integration-options" + "title": "Locks", + "anchor": "locks" }, { "depth": 3, - "title": "EVM Execution Only", - "anchor": "evm-execution-only" + "title": "Balance Types on Polkadot.js", + "anchor": "balance-types-on-polkadotjs" }, { - "depth": 3, - "title": "Full Ethereum Compatibility", - "anchor": "full-ethereum-compatibility" + "depth": 2, + "title": "Address Formats", + "anchor": "address-formats" }, { "depth": 3, - "title": "Key Benefits", - "anchor": "key-benefits-2" + "title": "Basic Format", + "anchor": "basic-format" }, { "depth": 3, - "title": "Implementation Examples", - "anchor": "implementation-examples-2" + "title": "Address Type", + "anchor": "address-type" }, { - "depth": 2, - "title": "pallet-contracts (Legacy)", - "anchor": "pallet-contracts-legacy" + "depth": 3, + "title": "Address Length", + "anchor": "address-length" }, { "depth": 3, - "title": "Implementation Example", - "anchor": "implementation-example" + "title": "Checksum Types", + "anchor": "checksum-types" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Validating Addresses", + "anchor": "validating-addresses" } ], "stats": { - "chars": 6655, - "words": 833, - "headings": 16, - "estimated_token_count_total": 1631 + "chars": 29604, + "words": 4194, + "headings": 15, + "estimated_token_count_total": 6507 }, - "hash": "sha256:6297bb5e0809fdd0585d6170054599f7ab4a3ce7c687ad03ae43092057c493b7", + "hash": "sha256:0104a9132a69345a2faac37fca0e2853a2ded1efb009511a83a98d44509ab887", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", - "title": "Add Pallets to the Runtime", - "slug": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", + "id": "reference-parachains-blocks-transactions-fees-blocks", + "title": "Blocks", + "slug": "reference-parachains-blocks-transactions-fees-blocks", "categories": [ "Basics", - "Parachains" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-add-pallet-to-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/", - "preview": "In previous tutorials, you learned how to [create a custom pallet](/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/){target=\\_blank} and [test it](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/){target=\\_blank}. The next step is to include this pallet in your runtime, integrating it into the core logic of your blockchain.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md", + "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/", + "preview": "In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the", "outline": [ { "depth": 2, @@ -4837,160 +4206,157 @@ }, { "depth": 2, - "title": "Add the Pallets as Dependencies", - "anchor": "add-the-pallets-as-dependencies" + "title": "What is a Block?", + "anchor": "what-is-a-block" + }, + { + "depth": 2, + "title": "Block Production", + "anchor": "block-production" }, { "depth": 3, - "title": "Update the Runtime Configuration", - "anchor": "update-the-runtime-configuration" + "title": "Initialize Block", + "anchor": "initialize-block" }, { - "depth": 2, - "title": "Recompile the Runtime", - "anchor": "recompile-the-runtime" + "depth": 3, + "title": "Finalize Block", + "anchor": "finalize-block" }, { "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" + "title": "Block Authoring and Import", + "anchor": "block-authoring-and-import" + }, + { + "depth": 3, + "title": "Block Import Queue", + "anchor": "block-import-queue" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 13091, - "words": 1522, - "headings": 6, - "estimated_token_count_total": 3091 + "chars": 6252, + "words": 910, + "headings": 8, + "estimated_token_count_total": 1395 }, - "hash": "sha256:87add0ae178e4970601a27efccadb58eff1375d19819201034ba2829914f1cd5", + "hash": "sha256:424783c102bea5dae5b8749635858c6c59055563442a98f57521f0027dafa8d3", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-pallet-development-benchmark-pallet", - "title": "Benchmark Your Pallet", - "slug": "parachains-customize-runtime-pallet-development-benchmark-pallet", + "id": "reference-parachains-blocks-transactions-fees-fees", + "title": "Transactions Weights and Fees", + "slug": "reference-parachains-blocks-transactions-fees-fees", "categories": [ - "Parachains" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/benchmark-pallet/", - "preview": "Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md", + "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/", + "preview": "When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop th", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Create the Benchmarking Module", - "anchor": "create-the-benchmarking-module" - }, - { - "depth": 2, - "title": "Define the Weight Trait", - "anchor": "define-the-weight-trait" + "title": "Introductions", + "anchor": "introductions" }, { "depth": 2, - "title": "Add WeightInfo to Config", - "anchor": "add-weightinfo-to-config" + "title": "How Fees are Calculated", + "anchor": "how-fees-are-calculated" }, { "depth": 2, - "title": "Update Extrinsic Weight Annotations", - "anchor": "update-extrinsic-weight-annotations" + "title": "Using the Transaction Payment Pallet", + "anchor": "using-the-transaction-payment-pallet" }, { - "depth": 2, - "title": "Include the Benchmarking Module", - "anchor": "include-the-benchmarking-module" + "depth": 3, + "title": "Understanding the Inclusion Fee", + "anchor": "understanding-the-inclusion-fee" }, { - "depth": 2, - "title": "Configure Pallet Dependencies", - "anchor": "configure-pallet-dependencies" + "depth": 3, + "title": "Accounts with an Insufficient Balance", + "anchor": "accounts-with-an-insufficient-balance" }, { - "depth": 2, - "title": "Update Mock Runtime", - "anchor": "update-mock-runtime" + "depth": 3, + "title": "Fee Multipliers", + "anchor": "fee-multipliers" }, { "depth": 2, - "title": "Configure Runtime Benchmarking", - "anchor": "configure-runtime-benchmarking" + "title": "Transactions with Special Requirements", + "anchor": "transactions-with-special-requirements" }, { "depth": 2, - "title": "Test Benchmark Compilation", - "anchor": "test-benchmark-compilation" + "title": "Default Weight Annotations", + "anchor": "default-weight-annotations" }, { - "depth": 2, - "title": "Build the Runtime with Benchmarks", - "anchor": "build-the-runtime-with-benchmarks" + "depth": 3, + "title": "Weights and Database Read/Write Operations", + "anchor": "weights-and-database-readwrite-operations" }, { - "depth": 2, - "title": "Install the Benchmarking Tool", - "anchor": "install-the-benchmarking-tool" + "depth": 3, + "title": "Dispatch Classes", + "anchor": "dispatch-classes" }, { - "depth": 2, - "title": "Download the Weight Template", - "anchor": "download-the-weight-template" + "depth": 3, + "title": "Dynamic Weights", + "anchor": "dynamic-weights" }, { "depth": 2, - "title": "Execute Benchmarks", - "anchor": "execute-benchmarks" + "title": "Post Dispatch Weight Correction", + "anchor": "post-dispatch-weight-correction" }, { "depth": 2, - "title": "Use Generated Weights", - "anchor": "use-generated-weights" + "title": "Custom Fees", + "anchor": "custom-fees" }, { - "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" + "depth": 3, + "title": "Custom Weights", + "anchor": "custom-weights" }, { "depth": 2, - "title": "Related Resources", - "anchor": "related-resources" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 22752, - "words": 2813, - "headings": 18, - "estimated_token_count_total": 5191 + "chars": 20800, + "words": 2917, + "headings": 15, + "estimated_token_count_total": 4464 }, - "hash": "sha256:c1b53ecbfc3dea02097104c7a4c652e61ccc42ad56325a9c80684850a198fbdd", + "hash": "sha256:7d0c3fa7982b3e1843adb8f27422456397580b3a3eba5047b381da8517742536", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-pallet-development-create-a-pallet", - "title": "Create a Custom Pallet", - "slug": "parachains-customize-runtime-pallet-development-create-a-pallet", + "id": "reference-parachains-blocks-transactions-fees-transactions", + "title": "Transactions", + "slug": "reference-parachains-blocks-transactions-fees-transactions", "categories": [ - "Parachains" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/create-a-pallet/", - "preview": "[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functional", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md", + "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/", + "preview": "Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions.", "outline": [ { "depth": 2, @@ -4999,149 +4365,130 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "What Is a Transaction?", + "anchor": "what-is-a-transaction" }, { - "depth": 2, - "title": "Core Pallet Components", - "anchor": "core-pallet-components" + "depth": 3, + "title": "Signed Transactions", + "anchor": "signed-transactions" }, { - "depth": 2, - "title": "Create the Pallet Project", - "anchor": "create-the-pallet-project" + "depth": 3, + "title": "Unsigned Transactions", + "anchor": "unsigned-transactions" }, { - "depth": 2, - "title": "Configure Dependencies", - "anchor": "configure-dependencies" + "depth": 3, + "title": "Inherent Transactions", + "anchor": "inherent-transactions" }, { "depth": 2, - "title": "Initialize the Pallet Structure", - "anchor": "initialize-the-pallet-structure" + "title": "Transaction Formats", + "anchor": "transaction-formats" }, { - "depth": 2, - "title": "Configure the Pallet", - "anchor": "configure-the-pallet" + "depth": 3, + "title": "Types of Transaction Formats", + "anchor": "types-of-transaction-formats" }, { - "depth": 2, - "title": "Define Events", - "anchor": "define-events" + "depth": 3, + "title": "Signed Transaction Data Structure", + "anchor": "signed-transaction-data-structure" }, { - "depth": 2, - "title": "Define Errors", - "anchor": "define-errors" + "depth": 3, + "title": "Signed Extensions", + "anchor": "signed-extensions" }, { "depth": 2, - "title": "Add Storage Items", - "anchor": "add-storage-items" + "title": "Transaction Construction", + "anchor": "transaction-construction" }, { - "depth": 2, - "title": "Configure Genesis State", - "anchor": "configure-genesis-state" + "depth": 3, + "title": "Construct a Signed Transaction", + "anchor": "construct-a-signed-transaction" }, { - "depth": 2, - "title": "Implement Dispatchable Functions", - "anchor": "implement-dispatchable-functions" + "depth": 3, + "title": "Transaction Encoding", + "anchor": "transaction-encoding" }, { "depth": 3, - "title": "Dispatchable Function Details", - "anchor": "dispatchable-function-details" + "title": "Customize Transaction Construction", + "anchor": "customize-transaction-construction" }, { "depth": 2, - "title": "Verify Pallet Compilation", - "anchor": "verify-pallet-compilation" + "title": "Lifecycle of a Transaction", + "anchor": "lifecycle-of-a-transaction" }, { - "depth": 2, - "title": "Add the Pallet to Your Runtime", - "anchor": "add-the-pallet-to-your-runtime" + "depth": 3, + "title": "Define Transaction Properties", + "anchor": "define-transaction-properties" }, { "depth": 3, - "title": "Add Runtime Dependency", - "anchor": "add-runtime-dependency" + "title": "Process on a Block Authoring Node", + "anchor": "process-on-a-block-authoring-node" }, { "depth": 3, - "title": "Implement the Config Trait", - "anchor": "implement-the-config-trait" - }, - { - "depth": 3, - "title": "Add to Runtime Construct", - "anchor": "add-to-runtime-construct" - }, - { - "depth": 3, - "title": "Configure Genesis for Your Runtime", - "anchor": "configure-genesis-for-your-runtime" - }, - { - "depth": 3, - "title": "Verify Runtime Compilation", - "anchor": "verify-runtime-compilation" - }, - { - "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" + "title": "Validate and Queue", + "anchor": "validate-and-queue" }, { "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" + "title": "Transaction Ordering and Priority", + "anchor": "transaction-ordering-and-priority" }, { "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" + "title": "Transaction Execution", + "anchor": "transaction-execution" }, { "depth": 2, - "title": "Interact with Your Pallet", - "anchor": "interact-with-your-pallet" + "title": "Transaction Mortality", + "anchor": "transaction-mortality" }, { "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" + "title": "Unique Identifiers for Extrinsics", + "anchor": "unique-identifiers-for-extrinsics" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 26958, - "words": 3085, - "headings": 26, - "estimated_token_count_total": 6194 + "chars": 23610, + "words": 3333, + "headings": 22, + "estimated_token_count_total": 4708 }, - "hash": "sha256:dad68ea59fd05fd60dc8890c4cf5615243c7ea879830b0dcf3a5e5e53c3ccec7", + "hash": "sha256:66726634d3a51cd9c471621054a6e5f09c8061dca6144b64c8bcf45626359617", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-pallet-development-mock-runtime", - "title": "Mock Your Runtime", - "slug": "parachains-customize-runtime-pallet-development-mock-runtime", + "id": "reference-parachains-chain-data", + "title": "Chain Data", + "slug": "reference-parachains-chain-data", "categories": [ - "Parachains" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/", - "preview": "Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md", + "html_url": "https://docs.polkadot.com/reference/parachains/chain-data/", + "preview": "Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you", "outline": [ { "depth": 2, @@ -5150,84 +4497,114 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Application Development", + "anchor": "application-development" }, { "depth": 2, - "title": "Understand Mock Runtimes", - "anchor": "understand-mock-runtimes" + "title": "Understand Metadata", + "anchor": "understand-metadata" }, { "depth": 2, - "title": "Create the Mock Runtime Module", - "anchor": "create-the-mock-runtime-module" + "title": "Expose Runtime Information as Metadata", + "anchor": "expose-runtime-information-as-metadata" }, { "depth": 2, - "title": "Set Up Basic Mock", - "anchor": "set-up-basic-mock" + "title": "Generate Metadata", + "anchor": "generate-metadata" }, { "depth": 2, - "title": "Implement Essential Configuration", - "anchor": "implement-essential-configuration" + "title": "Retrieve Runtime Metadata", + "anchor": "retrieve-runtime-metadata" }, { - "depth": 2, - "title": "Implement Your Pallet's Configuration", - "anchor": "implement-your-pallets-configuration" + "depth": 3, + "title": "Use Polkadot.js", + "anchor": "use-polkadotjs" }, { - "depth": 2, - "title": "Configure Genesis Storage", - "anchor": "configure-genesis-storage" + "depth": 3, + "title": "Use Curl", + "anchor": "use-curl" }, { "depth": 3, - "title": "Basic Test Environment", - "anchor": "basic-test-environment" + "title": "Use Subxt", + "anchor": "use-subxt" }, { - "depth": 3, - "title": "Custom Genesis Configurations", - "anchor": "custom-genesis-configurations" + "depth": 2, + "title": "Client Applications and Metadata", + "anchor": "client-applications-and-metadata" }, { "depth": 2, - "title": "Verify Mock Compilation", - "anchor": "verify-mock-compilation" + "title": "Metadata Format", + "anchor": "metadata-format" + }, + { + "depth": 3, + "title": "Pallets", + "anchor": "pallets" + }, + { + "depth": 3, + "title": "Extrinsic", + "anchor": "extrinsic" }, { "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" + "title": "Included RPC APIs", + "anchor": "included-rpc-apis" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 11766, - "words": 1369, - "headings": 13, - "estimated_token_count_total": 2514 + "chars": 18650, + "words": 2216, + "headings": 15, + "estimated_token_count_total": 3774 }, - "hash": "sha256:dd784a5d2daebb9a885fe09f6a967e6c84958d96ddb38d8366eabe9d860fa539", + "hash": "sha256:49238d1e9e2c33e0fcd3a84b5e30f0d3840d7d23a783b538875e0a23f38efc1d", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime-pallet-development-pallet-testing", - "title": "Unit Test Pallets", - "slug": "parachains-customize-runtime-pallet-development-pallet-testing", + "id": "reference-parachains-consensus-async-backing", + "title": "reference-parachains-consensus-async-backing", + "slug": "reference-parachains-consensus-async-backing", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/", - "preview": "Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-async-backing.md", + "html_url": "https://docs.polkadot.com/reference/parachains/consensus/async-backing/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-consensus-elastic-scaling", + "title": "Elastic Scaling", + "slug": "reference-parachains-consensus-elastic-scaling", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-elastic-scaling.md", + "html_url": "https://docs.polkadot.com/reference/parachains/consensus/elastic-scaling/", + "preview": "Polkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains.", "outline": [ { "depth": 2, @@ -5236,55 +4613,80 @@ }, { "depth": 2, - "title": "Writing Unit Tests", - "anchor": "writing-unit-tests" + "title": "How Elastic Scaling Works", + "anchor": "how-elastic-scaling-works" }, { - "depth": 3, - "title": "Test Initialization", - "anchor": "test-initialization" + "depth": 2, + "title": "Benefits of Elastic Scaling", + "anchor": "benefits-of-elastic-scaling" + }, + { + "depth": 2, + "title": "Use Cases", + "anchor": "use-cases" }, { "depth": 3, - "title": "Function Call Testing", - "anchor": "function-call-testing" + "title": "Handling Sudden Traffic Spikes", + "anchor": "handling-sudden-traffic-spikes" }, { "depth": 3, - "title": "Storage Testing", - "anchor": "storage-testing" + "title": "Supporting Early-Stage Growth", + "anchor": "supporting-early-stage-growth" }, { "depth": 3, - "title": "Event Testing", - "anchor": "event-testing" + "title": "Scaling Massive IoT Networks", + "anchor": "scaling-massive-iot-networks" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Powering Real-Time, Low-Latency Systems", + "anchor": "powering-real-time-low-latency-systems" } ], "stats": { - "chars": 6895, - "words": 912, - "headings": 7, - "estimated_token_count_total": 1563 + "chars": 7871, + "words": 1047, + "headings": 8, + "estimated_token_count_total": 1440 }, - "hash": "sha256:041ccd82f0c1ddfb93be05feb6cf9d7d4a7e37af6caa8fa8fdab5d5538017122", + "hash": "sha256:2d228c52844df8952520fafdd3e6f0e26bfd2f32b5ee60c6241cf7d38603643c", "token_estimator": "heuristic-v1" }, { - "id": "parachains-customize-runtime", - "title": "Overview of FRAME", - "slug": "parachains-customize-runtime", + "id": "reference-parachains-consensus", + "title": "reference-parachains-consensus", + "slug": "reference-parachains-consensus", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus.md", + "html_url": "https://docs.polkadot.com/reference/parachains/consensus/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-cryptography", + "title": "Cryptography", + "slug": "reference-parachains-cryptography", "categories": [ "Basics", - "Parachains" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/", - "preview": "A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a run", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md", + "html_url": "https://docs.polkadot.com/reference/parachains/cryptography/", + "preview": "Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem.", "outline": [ { "depth": 2, @@ -5293,364 +4695,406 @@ }, { "depth": 2, - "title": "Understanding Your Runtime", - "anchor": "understanding-your-runtime" + "title": "Hash Functions", + "anchor": "hash-functions" }, { - "depth": 2, - "title": "Runtime Architecture", - "anchor": "runtime-architecture" + "depth": 3, + "title": "Key Properties of Hash Functions", + "anchor": "key-properties-of-hash-functions" + }, + { + "depth": 3, + "title": "Blake2", + "anchor": "blake2" }, { "depth": 2, - "title": "Building Blocks: Pallets", - "anchor": "building-blocks-pallets" + "title": "Types of Cryptography", + "anchor": "types-of-cryptography" }, { "depth": 3, - "title": "Pre-Built Pallets vs. Custom Pallets", - "anchor": "pre-built-pallets-vs-custom-pallets" + "title": "Symmetric Cryptography", + "anchor": "symmetric-cryptography" }, { "depth": 3, - "title": "Pallet Structure", - "anchor": "pallet-structure" + "title": "Asymmetric Cryptography", + "anchor": "asymmetric-cryptography" }, { - "depth": 2, - "title": "How Runtime Customization Works", - "anchor": "how-runtime-customization-works" + "depth": 3, + "title": "Trade-offs and Compromises", + "anchor": "trade-offs-and-compromises" }, { "depth": 2, - "title": "Starting Templates", - "anchor": "starting-templates" + "title": "Digital Signatures", + "anchor": "digital-signatures" + }, + { + "depth": 3, + "title": "Example of Creating a Digital Signature", + "anchor": "example-of-creating-a-digital-signature" }, { "depth": 2, - "title": "Key Customization Scenarios", - "anchor": "key-customization-scenarios" + "title": "Elliptic Curve", + "anchor": "elliptic-curve" + }, + { + "depth": 3, + "title": "Various Implementations", + "anchor": "various-implementations" } ], "stats": { - "chars": 8236, - "words": 1101, - "headings": 9, - "estimated_token_count_total": 1828 + "chars": 8860, + "words": 1293, + "headings": 12, + "estimated_token_count_total": 1797 }, - "hash": "sha256:ad58d1c942b567acc4519abc35c0a049ab3e04711c2a49089ceba6324a5aa7ea", + "hash": "sha256:259dcef86aadc513675258b665cc3940db65af6eb32a5db85da6ac339966fa60", "token_estimator": "heuristic-v1" }, { - "id": "parachains-get-started", - "title": "Get Started with Parachain Development", - "slug": "parachains-get-started", + "id": "reference-parachains-data-encoding", + "title": "Data Encoding", + "slug": "reference-parachains-data-encoding", "categories": [ "Basics", - "Parachains" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md", - "html_url": "https://docs.polkadot.com/parachains/get-started/", - "preview": "The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md", + "html_url": "https://docs.polkadot.com/reference/parachains/data-encoding/", + "preview": "The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data.", "outline": [ { "depth": 2, - "title": "Quick Start Guides", - "anchor": "quick-start-guides" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Launch a Simple Parachain", - "anchor": "launch-a-simple-parachain" + "title": "SCALE Codec", + "anchor": "scale-codec" }, { - "depth": 2, - "title": "Customize Your Runtime", - "anchor": "customize-your-runtime" + "depth": 3, + "title": "Encode", + "anchor": "encode" }, { "depth": 3, - "title": "Pallet Development", - "anchor": "pallet-development" + "title": "Decode", + "anchor": "decode" }, { - "depth": 2, - "title": "Testing", - "anchor": "testing" + "depth": 3, + "title": "CompactAs", + "anchor": "compactas" }, { - "depth": 2, - "title": "Runtime Upgrades and Maintenance", - "anchor": "runtime-upgrades-and-maintenance" + "depth": 3, + "title": "HasCompact", + "anchor": "hascompact" }, { - "depth": 2, - "title": "Interoperability", - "anchor": "interoperability" + "depth": 3, + "title": "EncodeLike", + "anchor": "encodelike" + }, + { + "depth": 3, + "title": "Data Types", + "anchor": "data-types" }, { "depth": 2, - "title": "Integrations", - "anchor": "integrations" + "title": "Encode and Decode Rust Trait Implementations", + "anchor": "encode-and-decode-rust-trait-implementations" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "SCALE Codec Libraries", + "anchor": "scale-codec-libraries" } ], "stats": { - "chars": 7941, - "words": 631, - "headings": 9, - "estimated_token_count_total": 2292 + "chars": 13629, + "words": 1314, + "headings": 10, + "estimated_token_count_total": 3213 }, - "hash": "sha256:759ed27cf3d473445e33141089b652082c42a2c59eb822d6b506146fd9555e13", + "hash": "sha256:e448294b6e52291ac0add5fa6533572814e6cd27af42bdaccc2000b86f52d775", "token_estimator": "heuristic-v1" }, { - "id": "parachains-install-polkadot-sdk", - "title": "Install Polkadot SDK", - "slug": "parachains-install-polkadot-sdk", + "id": "reference-parachains-interoperability", + "title": "Interoperability", + "slug": "reference-parachains-interoperability", "categories": [ "Basics", - "Tooling" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md", - "html_url": "https://docs.polkadot.com/parachains/install-polkadot-sdk/", - "preview": "This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md", + "html_url": "https://docs.polkadot.com/reference/parachains/interoperability/", + "preview": "Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions.", "outline": [ { "depth": 2, - "title": "Install Dependencies: macOS", - "anchor": "install-dependencies-macos" + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-mac-os }", - "anchor": "before-you-begin-before-you-begin-mac-os" + "depth": 2, + "title": "Why Interoperability Matters", + "anchor": "why-interoperability-matters" }, { - "depth": 3, - "title": "Install Homebrew", - "anchor": "install-homebrew" + "depth": 2, + "title": "Key Mechanisms for Interoperability", + "anchor": "key-mechanisms-for-interoperability" }, { "depth": 3, - "title": "Support for Apple Silicon", - "anchor": "support-for-apple-silicon" + "title": "Cross-Consensus Messaging (XCM): The Backbone of Communication", + "anchor": "cross-consensus-messaging-xcm-the-backbone-of-communication" }, { "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-mac-os" + "title": "Bridges: Connecting External Networks", + "anchor": "bridges-connecting-external-networks" }, { "depth": 2, - "title": "Install Dependencies: Linux", - "anchor": "install-dependencies-linux" - }, - { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-linux }", - "anchor": "before-you-begin-before-you-begin-linux" - }, - { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-linux }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-linux" + "title": "The Polkadot Advantage", + "anchor": "the-polkadot-advantage" }, { "depth": 2, - "title": "Install Dependencies: Windows (WSL)", - "anchor": "install-dependencies-windows-wsl" - }, + "title": "Looking Ahead", + "anchor": "looking-ahead" + } + ], + "stats": { + "chars": 4635, + "words": 584, + "headings": 7, + "estimated_token_count_total": 772 + }, + "hash": "sha256:11bb4f113bdda5852a3115e64d5ba47f8eccd4e3619a05ad960ab3a541f31346", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-parachains-networks", + "title": "Networks", + "slug": "reference-parachains-networks", + "categories": [ + "Basics", + "Polkadot Protocol", + "Networks" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md", + "html_url": "https://docs.polkadot.com/reference/parachains/networks/", + "preview": "The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's va", + "outline": [ { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-windows-wls }", - "anchor": "before-you-begin-before-you-begin-windows-wls" + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Set Up Windows Subsystem for Linux", - "anchor": "set-up-windows-subsystem-for-linux" + "depth": 2, + "title": "Network Overview", + "anchor": "network-overview" }, { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-windows-wls" + "depth": 2, + "title": "Polkadot Development Networks", + "anchor": "polkadot-development-networks" }, { "depth": 2, - "title": "Build the Polkadot SDK", - "anchor": "build-the-polkadot-sdk" + "title": "Kusama Network", + "anchor": "kusama-network" }, { - "depth": 3, - "title": "Clone the Polkadot SDK", - "anchor": "clone-the-polkadot-sdk" + "depth": 2, + "title": "Test Networks", + "anchor": "test-networks" }, { "depth": 3, - "title": "Compile the Polkadot SDK", - "anchor": "compile-the-polkadot-sdk" + "title": "Westend", + "anchor": "westend" }, { "depth": 3, - "title": "Verify the Build", - "anchor": "verify-the-build" + "title": "Paseo", + "anchor": "paseo" }, { "depth": 2, - "title": "Optional: Run the Kitchensink Node", - "anchor": "optional-run-the-kitchensink-node" + "title": "Local Test Networks", + "anchor": "local-test-networks" }, { "depth": 3, - "title": "Run the Kitchensink Node in Development Mode", - "anchor": "run-the-kitchensink-node-in-development-mode" + "title": "Zombienet", + "anchor": "zombienet" }, { "depth": 3, - "title": "Interact with the Kitchensink Node", - "anchor": "interact-with-the-kitchensink-node" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Chopsticks", + "anchor": "chopsticks" } ], "stats": { - "chars": 16051, - "words": 2312, - "headings": 20, - "estimated_token_count_total": 3345 + "chars": 7834, + "words": 1111, + "headings": 10, + "estimated_token_count_total": 1473 }, - "hash": "sha256:a52c05b623f3780f14be3a5f36b3d79a6c1965c2fbfd6864b512a9a70c47cd60", + "hash": "sha256:e49e063a2cc0fb5a48c6cdc3de266bb6e025a006940fea8e90cc4d5f9884900f", "token_estimator": "heuristic-v1" }, { - "id": "parachains-integrations-indexers", - "title": "Indexers", - "slug": "parachains-integrations-indexers", + "id": "reference-parachains-node-and-runtime", + "title": "Node and Runtime", + "slug": "reference-parachains-node-and-runtime", "categories": [ - "Tooling", - "Dapps" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/indexers/", - "preview": "Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md", + "html_url": "https://docs.polkadot.com/reference/parachains/node-and-runtime/", + "preview": "Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network.", "outline": [ { "depth": 2, - "title": "The Challenge of Blockchain Data Access", - "anchor": "the-challenge-of-blockchain-data-access" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "What is a Blockchain Indexer?", - "anchor": "what-is-a-blockchain-indexer" + "title": "Architectural Principles", + "anchor": "architectural-principles" + }, + { + "depth": 3, + "title": "Advantages of this Architecture", + "anchor": "advantages-of-this-architecture" }, { "depth": 2, - "title": "Indexer Implementations", - "anchor": "indexer-implementations" - } - ], - "stats": { - "chars": 2230, - "words": 302, - "headings": 3, - "estimated_token_count_total": 428 - }, - "hash": "sha256:cfcc76bb24779c9b613f2c046b6f99a0f2529c25fd82287d804f6b945b936227", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-integrations-oracles", - "title": "Oracles", - "slug": "parachains-integrations-oracles", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/oracles/", - "preview": "Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the \"blockchain oracle problem.\" Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain.", - "outline": [ + "title": "Node (Client)", + "anchor": "node-client" + }, { "depth": 2, - "title": "What is a Blockchain Oracle?", - "anchor": "what-is-a-blockchain-oracle" + "title": "Runtime", + "anchor": "runtime" + }, + { + "depth": 3, + "title": "Characteristics", + "anchor": "characteristics" + }, + { + "depth": 3, + "title": "Key Functions", + "anchor": "key-functions" }, { "depth": 2, - "title": "Oracle Implementations", - "anchor": "oracle-implementations" + "title": "Communication Between Node and Runtime", + "anchor": "communication-between-node-and-runtime" + }, + { + "depth": 3, + "title": "Runtime APIs", + "anchor": "runtime-apis" + }, + { + "depth": 3, + "title": "Host Functions", + "anchor": "host-functions" } ], "stats": { - "chars": 1343, - "words": 181, - "headings": 2, - "estimated_token_count_total": 245 + "chars": 4937, + "words": 628, + "headings": 10, + "estimated_token_count_total": 914 }, - "hash": "sha256:6d8e01281a5895fd2bc4438b24c170c72a496de0b838626a53e87685aea4aa25", + "hash": "sha256:8122e21c149d0863cfe3b37fc5606bcdb91668e9d265f0f05451a61ff70e4e93", "token_estimator": "heuristic-v1" }, { - "id": "parachains-integrations-wallets", - "title": "Wallets", - "slug": "parachains-integrations-wallets", + "id": "reference-parachains-randomness", + "title": "Randomness", + "slug": "reference-parachains-randomness", "categories": [ - "Tooling", - "Dapps" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/wallets/", - "preview": "A wallet serves as your gateway to interacting with blockchain networks. Rather than storing funds, wallets secure your private keys, controlling access to your blockchain assets. Your private key provides complete control over all permitted transactions on your blockchain account, making it essential to keep it secure.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md", + "html_url": "https://docs.polkadot.com/reference/parachains/randomness/", + "preview": "Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as \"random\" numbers on a computer are actually pseudo-random. These numbers rely on an initial \"seed,\" which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\\_blank}, [heart rates](https://m", "outline": [ { "depth": 2, - "title": "What is a Blockchain Wallet?", - "anchor": "what-is-a-blockchain-wallet" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Hot Wallets", - "anchor": "hot-wallets" + "title": "VRF", + "anchor": "vrf" + }, + { + "depth": 3, + "title": "How VRF Works", + "anchor": "how-vrf-works" }, { "depth": 2, - "title": "Cold Wallets", - "anchor": "cold-wallets" + "title": "RANDAO", + "anchor": "randao" }, { "depth": 2, - "title": "Wallet Tools", - "anchor": "wallet-tools" + "title": "VDFs", + "anchor": "vdfs" + }, + { + "depth": 2, + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 3588, - "words": 489, - "headings": 4, - "estimated_token_count_total": 786 + "chars": 6503, + "words": 1005, + "headings": 6, + "estimated_token_count_total": 1388 }, - "hash": "sha256:62c5ad101282227f79eac0e30a3ba9ce3ae1bf9e358bd58c0b17ef45db29c2ff", + "hash": "sha256:c7d8a5a4263fd21af458ab0bd102377104affdf2431b4fe74eeff4ebe62a4a81", "token_estimator": "heuristic-v1" }, { - "id": "parachains-interoperability-channels-between-parachains", - "title": "Opening HRMP Channels Between Parachains", - "slug": "parachains-interoperability-channels-between-parachains", + "id": "reference-parachains", + "title": "Parachains Overview", + "slug": "reference-parachains", "categories": [ + "Basics", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/", - "preview": "For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md", + "html_url": "https://docs.polkadot.com/reference/parachains/", + "preview": "A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network.", "outline": [ { "depth": 2, @@ -5659,69 +5103,49 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Procedure to Initiate an HRMP Channel", - "anchor": "procedure-to-initiate-an-hrmp-channel" + "title": "Polkadot SDK: Parachain Architecture", + "anchor": "polkadot-sdk-parachain-architecture" }, { "depth": 3, - "title": "Fund Sender Sovereign Account", - "anchor": "fund-sender-sovereign-account" + "title": "Substrate: The Foundation", + "anchor": "substrate-the-foundation" }, { "depth": 3, - "title": "Create Channel Opening Extrinsic", - "anchor": "create-channel-opening-extrinsic" + "title": "FRAME: Building Blocks for Your Runtime", + "anchor": "frame-building-blocks-for-your-runtime" }, { "depth": 3, - "title": "Craft and Submit the XCM Message from the Sender", - "anchor": "craft-and-submit-the-xcm-message-from-the-sender" + "title": "Cumulus: Parachain-Specific Functionality", + "anchor": "cumulus-parachain-specific-functionality" }, { "depth": 2, - "title": "Procedure to Accept an HRMP Channel", - "anchor": "procedure-to-accept-an-hrmp-channel" - }, - { - "depth": 3, - "title": "Fund Receiver Sovereign Account", - "anchor": "fund-receiver-sovereign-account" - }, - { - "depth": 3, - "title": "Create Channel Accepting Extrinsic", - "anchor": "create-channel-accepting-extrinsic" - }, - { - "depth": 3, - "title": "Craft and Submit the XCM Message from the Receiver", - "anchor": "craft-and-submit-the-xcm-message-from-the-receiver" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 10934, - "words": 1549, - "headings": 10, - "estimated_token_count_total": 2285 + "chars": 8495, + "words": 1029, + "headings": 6, + "estimated_token_count_total": 1759 }, - "hash": "sha256:b8de1228b9976765accd18ff724038bed6f2449367f500bc3177ab2a053abe63", + "hash": "sha256:ecb0d9459e08920db7d2d59dc7c01aba7a91ce8c9e39256bd0c3efa473dbaa17", "token_estimator": "heuristic-v1" }, { - "id": "parachains-interoperability-channels-with-system-parachains", - "title": "Opening HRMP Channels with System Parachains", - "slug": "parachains-interoperability-channels-with-system-parachains", + "id": "reference-polkadot-hub-assets-and-smart-contracts", + "title": "Asset Hub", + "slug": "reference-polkadot-hub-assets-and-smart-contracts", "categories": [ - "Parachains" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/", - "preview": "While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/assets-and-smart-contracts/", + "preview": "The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integra", "outline": [ { "depth": 2, @@ -5730,50 +5154,124 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Assets Basics", + "anchor": "assets-basics" }, { "depth": 2, - "title": "Procedure to Establish an HRMP Channel", - "anchor": "procedure-to-establish-an-hrmp-channel" + "title": "Assets Pallet", + "anchor": "assets-pallet" }, { "depth": 3, - "title": "Fund Parachain Sovereign Account", - "anchor": "fund-parachain-sovereign-account" + "title": "Key Features", + "anchor": "key-features" }, { "depth": 3, - "title": "Create Establish Channel with System Extrinsic", - "anchor": "create-establish-channel-with-system-extrinsic" + "title": "Main Functions", + "anchor": "main-functions" }, { "depth": 3, - "title": "Craft and Submit the XCM Message", - "anchor": "craft-and-submit-the-xcm-message" + "title": "Querying Functions", + "anchor": "querying-functions" + }, + { + "depth": 3, + "title": "Permission Models and Roles", + "anchor": "permission-models-and-roles" + }, + { + "depth": 3, + "title": "Asset Freezing", + "anchor": "asset-freezing" + }, + { + "depth": 3, + "title": "Non-Custodial Transfers (Approval API)", + "anchor": "non-custodial-transfers-approval-api" + }, + { + "depth": 2, + "title": "Foreign Assets", + "anchor": "foreign-assets" + }, + { + "depth": 3, + "title": "Handling Foreign Assets", + "anchor": "handling-foreign-assets" + }, + { + "depth": 2, + "title": "Integration", + "anchor": "integration" + }, + { + "depth": 3, + "title": "API Sidecar", + "anchor": "api-sidecar" + }, + { + "depth": 3, + "title": "TxWrapper", + "anchor": "txwrapper" + }, + { + "depth": 3, + "title": "Parachain Node", + "anchor": "parachain-node" + }, + { + "depth": 2, + "title": "XCM Transfer Monitoring", + "anchor": "xcm-transfer-monitoring" + }, + { + "depth": 3, + "title": "Monitor XCM Deposits", + "anchor": "monitor-xcm-deposits" + }, + { + "depth": 3, + "title": "Track XCM Information Back to the Source", + "anchor": "track-xcm-information-back-to-the-source" + }, + { + "depth": 3, + "title": "Practical Monitoring Examples", + "anchor": "practical-monitoring-examples" + }, + { + "depth": 3, + "title": "Monitor for Failed XCM Transfers", + "anchor": "monitor-for-failed-xcm-transfers" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 7203, - "words": 889, - "headings": 6, - "estimated_token_count_total": 1427 + "chars": 18211, + "words": 2649, + "headings": 21, + "estimated_token_count_total": 3678 }, - "hash": "sha256:b501d99c464fb049d46676827b6a325a195c90617becc4a7db305441c115350a", + "hash": "sha256:3d10c04cffc5f737ff75b079d661c2c1904629d23ae1e415e64fd6ae4e98759e", "token_estimator": "heuristic-v1" }, { - "id": "parachains-interoperability-get-started", - "title": "Introduction to XCM", - "slug": "parachains-interoperability-get-started", + "id": "reference-polkadot-hub-bridging", + "title": "Bridge Hub", + "slug": "reference-polkadot-hub-bridging", "categories": [ - "Basics", "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/get-started/", - "preview": "Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-bridging.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/bridging/", + "preview": "The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interope", "outline": [ { "depth": 2, @@ -5782,54 +5280,49 @@ }, { "depth": 2, - "title": "Messaging Format", - "anchor": "messaging-format" - }, - { - "depth": 2, - "title": "The Four Principles of XCM", - "anchor": "the-four-principles-of-xcm" + "title": "Trustless Bridging", + "anchor": "trustless-bridging" }, { "depth": 2, - "title": "The XCM Tech Stack", - "anchor": "the-xcm-tech-stack" + "title": "Bridging Components", + "anchor": "bridging-components" }, { - "depth": 2, - "title": "Core Functionalities of XCM", - "anchor": "core-functionalities-of-xcm" + "depth": 3, + "title": "Ethereum-Specific Support", + "anchor": "ethereum-specific-support" }, { "depth": 2, - "title": "XCM Example", - "anchor": "xcm-example" + "title": "Deployed Bridges", + "anchor": "deployed-bridges" }, { "depth": 2, - "title": "Overview", - "anchor": "overview" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 7450, - "words": 974, - "headings": 7, - "estimated_token_count_total": 1501 + "chars": 5467, + "words": 776, + "headings": 6, + "estimated_token_count_total": 1220 }, - "hash": "sha256:3b26606dd5310c4b8ade5d05270ebf1e06f59afcda4ca2b985e07948215a197e", + "hash": "sha256:86734ba8bcdea7913f488edf666a6104bed0a18649d57abde82c149c41c2b871", "token_estimator": "heuristic-v1" }, { - "id": "parachains-launch-a-parachain-deploy-to-polkadot", - "title": "Deploy on Polkadot", - "slug": "parachains-launch-a-parachain-deploy-to-polkadot", + "id": "reference-polkadot-hub-collectives-and-daos", + "title": "Collectives Chain", + "slug": "reference-polkadot-hub-collectives-and-daos", "categories": [ - "Parachains" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-deploy-to-polkadot.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/deploy-to-polkadot/", - "preview": "Previously, you learned how to [choose and set up a parachain template](/parachains/launch-a-parachain/choose-a-template/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to the Polkadot TestNet. Deploying to a TestNet is a crucial step for validating your parachain's functionality and preparing it for eventual MainNet deployment.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-collectives-and-daos.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/collectives-and-daos/", + "preview": "Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem.", "outline": [ { "depth": 2, @@ -5838,64 +5331,75 @@ }, { "depth": 2, - "title": "Get Started with an Account and Tokens", - "anchor": "get-started-with-an-account-and-tokens" - }, - { - "depth": 2, - "title": "Reserve a Parachain Identifier", - "anchor": "reserve-a-parachain-identifier" - }, - { - "depth": 2, - "title": "Generate Custom Keys for Your Collators", - "anchor": "generate-custom-keys-for-your-collators" - }, + "title": "Key Collectives", + "anchor": "key-collectives" + } + ], + "stats": { + "chars": 2288, + "words": 293, + "headings": 2, + "estimated_token_count_total": 424 + }, + "hash": "sha256:59ec351fbb8d3a392e90f4f5bf6b62f58b21d6d7a900c5e367e5d2e09ecb3aca", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-polkadot-hub-consensus-and-security-agile-coretime", + "title": "Agile Coretime", + "slug": "reference-polkadot-hub-consensus-and-security-agile-coretime", + "categories": [ + "Polkadot Protocol" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/agile-coretime/", + "preview": "Agile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains.", + "outline": [ { "depth": 2, - "title": "Generate the Chain Specification", - "anchor": "generate-the-chain-specification" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Export Required Files", - "anchor": "export-required-files" + "title": "Bulk Coretime", + "anchor": "bulk-coretime" }, { - "depth": 2, - "title": "Register a Parathread", - "anchor": "register-a-parathread" + "depth": 3, + "title": "Coretime Interlacing", + "anchor": "coretime-interlacing" }, { - "depth": 2, - "title": "Start the Collator Node", - "anchor": "start-the-collator-node" + "depth": 3, + "title": "Coretime Splitting", + "anchor": "coretime-splitting" }, { "depth": 2, - "title": "Producing Blocks", - "anchor": "producing-blocks" + "title": "On-Demand Coretime", + "anchor": "on-demand-coretime" } ], "stats": { - "chars": 20252, - "words": 2357, - "headings": 9, - "estimated_token_count_total": 4129 + "chars": 3028, + "words": 452, + "headings": 5, + "estimated_token_count_total": 619 }, - "hash": "sha256:fde940bced4380fc01b1840907059d03f6d47b6cb54bf78c95269ac57adbc99e", + "hash": "sha256:00be43ac8d666bbe15c5c2fa5a5085697d0bb5a6f341ebbb943a209f0be355df", "token_estimator": "heuristic-v1" }, { - "id": "parachains-launch-a-parachain-obtain-coretime", - "title": "Obtain Coretime", - "slug": "parachains-launch-a-parachain-obtain-coretime", + "id": "reference-polkadot-hub-consensus-and-security-pos-consensus", + "title": "Proof of Stake Consensus", + "slug": "reference-polkadot-hub-consensus-and-security-pos-consensus", "categories": [ - "Parachains" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/", - "preview": "After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/pos-consensus/", + "preview": "Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank} model and a com", "outline": [ { "depth": 2, @@ -5904,80 +5408,86 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Nominated Proof of Stake", + "anchor": "nominated-proof-of-stake" }, { "depth": 2, - "title": "Order On-Demand Coretime", - "anchor": "order-on-demand-coretime" + "title": "Hybrid Consensus", + "anchor": "hybrid-consensus" }, { - "depth": 3, - "title": "On-Demand Extrinsics", - "anchor": "on-demand-extrinsics" + "depth": 2, + "title": "Block Production - BABE", + "anchor": "block-production-babe" }, { "depth": 3, - "title": "Place an On-Demand Order", - "anchor": "place-an-on-demand-order" + "title": "Validator Participation", + "anchor": "validator-participation" }, { - "depth": 2, - "title": "Purchase Bulk Coretime", - "anchor": "purchase-bulk-coretime" + "depth": 3, + "title": "Additional Resources", + "anchor": "additional-resources" }, { - "depth": 3, - "title": "Connect Your Wallet to RegionX", - "anchor": "connect-your-wallet-to-regionx" + "depth": 2, + "title": "Finality Gadget - GRANDPA", + "anchor": "finality-gadget-grandpa" }, { "depth": 3, - "title": "Obtain Coretime Chain Funds", - "anchor": "obtain-coretime-chain-funds" + "title": "Probabilistic vs. Provable Finality", + "anchor": "probabilistic-vs-provable-finality" }, { "depth": 3, - "title": "Purchase a Core", - "anchor": "purchase-a-core" + "title": "Additional Resources", + "anchor": "additional-resources-2" }, { - "depth": 3, - "title": "Verify Your Purchase", - "anchor": "verify-your-purchase" + "depth": 2, + "title": "Fork Choice", + "anchor": "fork-choice" }, { "depth": 3, - "title": "Assign Your Parachain to the Core", - "anchor": "assign-your-parachain-to-the-core" + "title": "Additional Resources", + "anchor": "additional-resources-3" }, { "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" + "title": "Bridging - BEEFY", + "anchor": "bridging-beefy" + }, + { + "depth": 3, + "title": "Additional Resources", + "anchor": "additional-resources-4" } ], "stats": { - "chars": 9049, - "words": 1345, - "headings": 12, - "estimated_token_count_total": 2103 + "chars": 12753, + "words": 1834, + "headings": 13, + "estimated_token_count_total": 2526 }, - "hash": "sha256:15154f211753665d9af70dc81d15ceb3f0954e3febf9282c68c0074881d620c6", + "hash": "sha256:231fc555eefe5f910fb36e0c03945147d0fb235272850797391751f4444b0a9c", "token_estimator": "heuristic-v1" }, { - "id": "parachains-launch-a-parachain-set-up-the-parachain-template", - "title": "Set Up the Polkadot SDK Parachain Template", - "slug": "parachains-launch-a-parachain-set-up-the-parachain-template", + "id": "reference-polkadot-hub-consensus-and-security-relay-chain", + "title": "Overview of the Polkadot Relay Chain", + "slug": "reference-polkadot-hub-consensus-and-security-relay-chain", "categories": [ "Basics", + "Polkadot Protocol", "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/", - "preview": "The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/", + "preview": "Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank}, and cross-chain int", "outline": [ { "depth": 2, @@ -5986,74 +5496,74 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Polkadot 1.0", + "anchor": "polkadot-10" }, { - "depth": 2, - "title": "Polkadot SDK Utility Tools", - "anchor": "polkadot-sdk-utility-tools" + "depth": 3, + "title": "High-Level Architecture", + "anchor": "high-level-architecture" }, { - "depth": 2, - "title": "Clone the Template", - "anchor": "clone-the-template" + "depth": 3, + "title": "Polkadot's Additional Functionalities", + "anchor": "polkadots-additional-functionalities" }, { - "depth": 2, - "title": "Explore the Project Structure", - "anchor": "explore-the-project-structure" + "depth": 3, + "title": "Polkadot's Resilience", + "anchor": "polkadots-resilience" }, { - "depth": 2, - "title": "Compile the Runtime", - "anchor": "compile-the-runtime" + "depth": 3, + "title": "Polkadot's Blockspace", + "anchor": "polkadots-blockspace" }, { "depth": 2, - "title": "Verify the Build", - "anchor": "verify-the-build" + "title": "DOT Token", + "anchor": "dot-token" }, { - "depth": 2, - "title": "Run the Node Locally", - "anchor": "run-the-node-locally" + "depth": 3, + "title": "Redenomination of DOT", + "anchor": "redenomination-of-dot" }, { - "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" + "depth": 3, + "title": "The Planck Unit", + "anchor": "the-planck-unit" }, { - "depth": 2, - "title": "Stop the Node", - "anchor": "stop-the-node" + "depth": 3, + "title": "Uses for DOT", + "anchor": "uses-for-dot" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "JAM and the Road Ahead", + "anchor": "jam-and-the-road-ahead" } ], "stats": { - "chars": 10591, - "words": 1510, + "chars": 12458, + "words": 1774, "headings": 11, - "estimated_token_count_total": 2377 + "estimated_token_count_total": 2580 }, - "hash": "sha256:1277261cb3de71cac194f26e765124ea9f3e09cffdcd94bb717965a11cb7f374", + "hash": "sha256:60f5ac9f67fb9f2188121219830538d334028b3b9e85d42bd1e7279043654e39", "token_estimator": "heuristic-v1" }, { - "id": "parachains-runtime-maintenance-runtime-upgrades", - "title": "Runtime Upgrades", - "slug": "parachains-runtime-maintenance-runtime-upgrades", + "id": "reference-polkadot-hub-people-and-identity", + "title": "People Chain", + "slug": "reference-polkadot-hub-people-and-identity", "categories": [ - "Parachains" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/", - "preview": "One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-people-and-identity.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/people-and-identity/", + "preview": "People chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management.", "outline": [ { "depth": 2, @@ -6062,44 +5572,100 @@ }, { "depth": 2, - "title": "How Runtime Upgrades Work", - "anchor": "how-runtime-upgrades-work" + "title": "Identity Management System", + "anchor": "identity-management-system" }, { "depth": 3, - "title": "Runtime Versioning", - "anchor": "runtime-versioning" + "title": "Sub-Identities", + "anchor": "sub-identities" + }, + { + "depth": 2, + "title": "Verification Process", + "anchor": "verification-process" }, { "depth": 3, - "title": "Accessing the Runtime Version", - "anchor": "accessing-the-runtime-version" + "title": "Judgment Requests", + "anchor": "judgment-requests" + }, + { + "depth": 3, + "title": "Judgment Classifications", + "anchor": "judgment-classifications" + }, + { + "depth": 3, + "title": "Registrars", + "anchor": "registrars" }, { "depth": 2, - "title": "Storage Migrations", - "anchor": "storage-migrations" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 5837, - "words": 811, - "headings": 5, - "estimated_token_count_total": 1161 + "chars": 4750, + "words": 606, + "headings": 8, + "estimated_token_count_total": 876 }, - "hash": "sha256:ec31270001a6cd9d0a8ecb7974ad161d5c1ef4d3023d5a6af9fbc5a6ca46cbca", + "hash": "sha256:8239d1e8d8642cb7c10e9e5f971c99b999e9e4a87373b50bf4a691225c1e4702", "token_estimator": "heuristic-v1" }, { - "id": "parachains-runtime-maintenance-storage-migrations", - "title": "Storage Migrations", - "slug": "parachains-runtime-maintenance-storage-migrations", + "id": "reference-polkadot-hub", + "title": "reference-polkadot-hub", + "slug": "reference-polkadot-hub", "categories": [ - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/", - "preview": "Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub.md", + "html_url": "https://docs.polkadot.com/reference/polkadot-hub/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-chopsticks", + "title": "reference-tools-chopsticks", + "slug": "reference-tools-chopsticks", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md", + "html_url": "https://docs.polkadot.com/reference/tools/chopsticks/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-dedot", + "title": "Dedot", + "slug": "reference-tools-dedot", + "categories": [ + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md", + "html_url": "https://docs.polkadot.com/reference/tools/dedot/", + "preview": "[Dedot](https://github.com/dedotdev/dedot){target=\\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\\_blank}.", "outline": [ { "depth": 2, @@ -6107,70 +5673,66 @@ "anchor": "introduction" }, { - "depth": 2, - "title": "Storage Migration Scenarios", - "anchor": "storage-migration-scenarios" + "depth": 3, + "title": "Key Features", + "anchor": "key-features" }, { "depth": 2, - "title": "Implement Storage Migrations", - "anchor": "implement-storage-migrations" + "title": "Installation", + "anchor": "installation" }, { - "depth": 3, - "title": "Core Migration Function", - "anchor": "core-migration-function" + "depth": 2, + "title": "Get Started", + "anchor": "get-started" }, { "depth": 3, - "title": "Migration Testing Hooks", - "anchor": "migration-testing-hooks" + "title": "Initialize a Client Instance", + "anchor": "initialize-a-client-instance" }, { "depth": 3, - "title": "Migration Structure", - "anchor": "migration-structure" + "title": "Enable Type and API Suggestions", + "anchor": "enable-type-and-api-suggestions" }, { "depth": 3, - "title": "Migration Organization", - "anchor": "migration-organization" + "title": "Read On-Chain Data", + "anchor": "read-on-chain-data" }, { "depth": 3, - "title": "Scheduling Migrations", - "anchor": "scheduling-migrations" - }, - { - "depth": 2, - "title": "Single-Block Migrations", - "anchor": "single-block-migrations" + "title": "Sign and Send Transactions", + "anchor": "sign-and-send-transactions" }, { "depth": 2, - "title": "Multi Block Migrations", - "anchor": "multi-block-migrations" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 18500, - "words": 2363, - "headings": 10, - "estimated_token_count_total": 4014 + "chars": 8855, + "words": 1100, + "headings": 9, + "estimated_token_count_total": 2300 }, - "hash": "sha256:55dc252fdecf1590048ce8d009b822e90231442abe81e9593cf1635944a31336", + "hash": "sha256:ba24e31e2ad94fbf1d73f1878da92dd2e1476db00170780bbdf0e65ab18bc961", "token_estimator": "heuristic-v1" }, { - "id": "parachains-runtime-maintenance-unlock-parachains", - "title": "Unlock a Parachain", - "slug": "parachains-runtime-maintenance-unlock-parachains", + "id": "reference-tools-light-clients", + "title": "Light Clients", + "slug": "reference-tools-light-clients", "categories": [ - "Parachains" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-unlock-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/unlock-parachains/", - "preview": "Parachain locks are a critical security mechanism in the Polkadot ecosystem designed to maintain decentralization during the parachain lifecycle. These locks prevent potential centralization risks that could emerge during the early stages of parachain operation.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md", + "html_url": "https://docs.polkadot.com/reference/tools/light-clients/", + "preview": "Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes.", "outline": [ { "depth": 2, @@ -6179,50 +5741,55 @@ }, { "depth": 2, - "title": "Check If the Parachain Is Locked", - "anchor": "check-if-the-parachain-is-locked" + "title": "Light Clients Workflow", + "anchor": "light-clients-workflow" }, { "depth": 2, - "title": "How to Unlock a Parachain", - "anchor": "how-to-unlock-a-parachain" + "title": "JSON-RPC and Light Client Comparison", + "anchor": "json-rpc-and-light-client-comparison" }, { - "depth": 3, - "title": "Prepare the Unlock Call", - "anchor": "prepare-the-unlock-call" + "depth": 2, + "title": "Using Light Clients", + "anchor": "using-light-clients" }, { "depth": 3, - "title": "Fund the Sovereign Account", - "anchor": "fund-the-sovereign-account" + "title": "PAPI Light Client Support", + "anchor": "papi-light-client-support" }, { "depth": 3, - "title": "Craft and Submit the XCM", - "anchor": "craft-and-submit-the-xcm" + "title": "Substrate Connect - Browser Extension", + "anchor": "substrate-connect-browser-extension" + }, + { + "depth": 2, + "title": "Resources", + "anchor": "resources" } ], "stats": { - "chars": 9232, - "words": 1276, - "headings": 6, - "estimated_token_count_total": 2028 + "chars": 6490, + "words": 870, + "headings": 7, + "estimated_token_count_total": 1430 }, - "hash": "sha256:e408d05199cc184fc6fe8bb212efb3c9aa6cb79258977e07566692176c912def", + "hash": "sha256:1284c42be692167e01bcc44e2e134ec20615402675fac26df246c00aa1588d80", "token_estimator": "heuristic-v1" }, { - "id": "parachains-testing-fork-a-parachain", - "title": "Get Started", - "slug": "parachains-testing-fork-a-parachain", + "id": "reference-tools-moonwall", + "title": "E2E Testing with Moonwall", + "slug": "reference-tools-moonwall", "categories": [ "Parachains", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md", - "html_url": "https://docs.polkadot.com/parachains/testing/fork-a-parachain/", - "preview": "[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md", + "html_url": "https://docs.polkadot.com/reference/tools/moonwall/", + "preview": "Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations.", "outline": [ { "depth": 2, @@ -6236,8 +5803,8 @@ }, { "depth": 2, - "title": "Install Chopsticks", - "anchor": "install-chopsticks" + "title": "Install Moonwall", + "anchor": "install-moonwall" }, { "depth": 3, @@ -6251,23 +5818,18 @@ }, { "depth": 2, - "title": "Configure Chopsticks", - "anchor": "configure-chopsticks" - }, - { - "depth": 3, - "title": "Configuration File", - "anchor": "configuration-file" + "title": "Initialize Moonwall", + "anchor": "initialize-moonwall" }, { - "depth": 3, - "title": "CLI Flags", - "anchor": "cli-flags" + "depth": 2, + "title": "Writing Tests", + "anchor": "writing-tests" }, { "depth": 2, - "title": "WebSocket Commands", - "anchor": "websocket-commands" + "title": "Running the Tests", + "anchor": "running-the-tests" }, { "depth": 2, @@ -6276,25 +5838,25 @@ } ], "stats": { - "chars": 10894, - "words": 1330, - "headings": 10, - "estimated_token_count_total": 2614 + "chars": 10240, + "words": 1295, + "headings": 9, + "estimated_token_count_total": 2453 }, - "hash": "sha256:4325cdd697814b8043db808da3dee86d3d9c6fc7dd523aae7fe8914d59d1b39c", + "hash": "sha256:2c77cfb38bb2e466a8f56dabbb706fcd2e90cf1634fc9beb7f0ee95a75735653", "token_estimator": "heuristic-v1" }, { - "id": "parachains-testing-run-a-parachain-network", - "title": "Get Started", - "slug": "parachains-testing-run-a-parachain-network", + "id": "reference-tools-omninode", + "title": "Polkadot Omni Node", + "slug": "reference-tools-omninode", "categories": [ "Parachains", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md", - "html_url": "https://docs.polkadot.com/parachains/testing/run-a-parachain-network/", - "preview": "Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md", + "html_url": "https://docs.polkadot.com/reference/tools/omninode/", + "preview": "The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\\_blank} file, allowing it to adapt dynamically to different parachains.", "outline": [ { "depth": 2, @@ -6303,90 +5865,65 @@ }, { "depth": 2, - "title": "Install Zombienet", - "anchor": "install-zombienet" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Providers", - "anchor": "providers" - }, - { - "depth": 3, - "title": "Kubernetes", - "anchor": "kubernetes" - }, - { - "depth": 3, - "title": "Podman", - "anchor": "podman" - }, - { - "depth": 3, - "title": "Local Provider", - "anchor": "local-provider" + "title": "Install Polkadot Omni Node", + "anchor": "install-polkadot-omni-node" }, { "depth": 2, - "title": "Configure Zombienet", - "anchor": "configure-zombienet" - }, - { - "depth": 3, - "title": "Configuration Files", - "anchor": "configuration-files" + "title": "Obtain Chain Specifications", + "anchor": "obtain-chain-specifications" }, { - "depth": 3, - "title": "CLI Usage", - "anchor": "cli-usage" + "depth": 2, + "title": "Run a Parachain Full Node", + "anchor": "run-a-parachain-full-node" }, { - "depth": 3, - "title": "Settings", - "anchor": "settings" + "depth": 2, + "title": "Interact with the Node", + "anchor": "interact-with-the-node" }, { - "depth": 3, - "title": "Relay Chain Configuration", - "anchor": "relay-chain-configuration" + "depth": 2, + "title": "Parachain Compatibility", + "anchor": "parachain-compatibility" }, { "depth": 3, - "title": "Parachain Configuration", - "anchor": "parachain-configuration" + "title": "Required Runtime APIs", + "anchor": "required-runtime-apis" }, { "depth": 3, - "title": "XCM Configuration", - "anchor": "xcm-configuration" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Required Pallets", + "anchor": "required-pallets" } ], "stats": { - "chars": 41636, - "words": 4599, - "headings": 14, - "estimated_token_count_total": 9871 + "chars": 8913, + "words": 1164, + "headings": 9, + "estimated_token_count_total": 2017 }, - "hash": "sha256:0d7e04fd952cc9d5bd8cdbfd87cc4004c5f95e896a16bc7f89dfc4caeac8f371", + "hash": "sha256:7db2d31ba37abad20b026c875f632b89739b45707e58809e2e8b32a09715c6f9", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-parachains-consensus", - "title": "Parachain Consensus", - "slug": "polkadot-protocol-architecture-parachains-consensus", + "id": "reference-tools-papi", + "title": "Polkadot-API", + "slug": "reference-tools-papi", "categories": [ - "Polkadot Protocol", - "Parachains" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains-consensus.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/consensus/", - "preview": "Parachains are independent blockchains built with the Polkadot SDK, designed to leverage Polkadot’s relay chain for shared security and transaction finality. These specialized chains operate as part of Polkadot’s execution sharding model, where each parachain manages its own state and transactions while relying on the relay chain for validation and consensus.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md", + "html_url": "https://docs.polkadot.com/reference/tools/papi/", + "preview": "[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications.", "outline": [ { "depth": 2, @@ -6395,18 +5932,23 @@ }, { "depth": 2, - "title": "The Role of Collators", - "anchor": "the-role-of-collators" + "title": "Get Started", + "anchor": "get-started" }, { - "depth": 2, - "title": "Consensus and Validation", - "anchor": "consensus-and-validation" + "depth": 3, + "title": "API Instantiation", + "anchor": "api-instantiation" + }, + { + "depth": 3, + "title": "Reading Chain Data", + "anchor": "reading-chain-data" }, { "depth": 3, - "title": "Path of a Parachain Block", - "anchor": "path-of-a-parachain-block" + "title": "Sending Transactions", + "anchor": "sending-transactions" }, { "depth": 2, @@ -6415,26 +5957,24 @@ } ], "stats": { - "chars": 6150, - "words": 790, - "headings": 5, - "estimated_token_count_total": 1125 + "chars": 8957, + "words": 1156, + "headings": 6, + "estimated_token_count_total": 1987 }, - "hash": "sha256:9875239c6071033a37a0f67fabca5a6e840c4a287620309f47b4f29c5a95a1cb", + "hash": "sha256:2ca93b09d3bb9159bbf53816886a9b242bb3c13b996c51fd52962e049e2d5477", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-parachains-overview", - "title": "Overview", - "slug": "polkadot-protocol-architecture-parachains-overview", + "id": "reference-tools-paraspell", + "title": "ParaSpell XCM SDK", + "slug": "reference-tools-paraspell", "categories": [ - "Basics", - "Polkadot Protocol", - "Parachains" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains-overview.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/overview/", - "preview": "A [_parachain_](/polkadot-protocol/glossary#parachain){target=\\_blank} is a coherent, application-specific blockchain that derives security from its respective relay chain. Parachains on Polkadot are each their own separate, fully functioning blockchain. The primary difference between a parachain and a regular, \"solo\" blockchain is that the relay chain verifies the state of all parachains that are connected to it. In many ways, parachains can be thought of as a [\"cynical\" rollup](#cryptoeconomic", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md", + "html_url": "https://docs.polkadot.com/reference/tools/paraspell/", + "preview": "[ParaSpell](https://paraspell.github.io/docs/){target=\\_blank} is a comprehensive suite of open-source tools designed to simplify cross-chain interactions within the Polkadot ecosystem. At its core, ParaSpell is dedicated to enhancing the functionality of the [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} protocol by providing developers with a unified and streamlined experience for building interoperable decentralized applications (dApps).", "outline": [ { "depth": 2, @@ -6442,34 +5982,14 @@ "anchor": "introduction" }, { - "depth": 2, - "title": "Coherent Systems", - "anchor": "coherent-systems" - }, - { - "depth": 2, - "title": "Flexible Ecosystem", - "anchor": "flexible-ecosystem" + "depth": 3, + "title": "ParaSpell XCM SDK", + "anchor": "paraspell-xcm-sdk" }, { "depth": 2, - "title": "State Transition Functions (Runtimes)", - "anchor": "state-transition-functions-runtimes" - }, - { - "depth": 2, - "title": "Shared Security: Validated by the Relay Chain", - "anchor": "shared-security-validated-by-the-relay-chain" - }, - { - "depth": 3, - "title": "Cryptoeconomic Security: ELVES Protocol", - "anchor": "cryptoeconomic-security-elves-protocol" - }, - { - "depth": 2, - "title": "Interoperability", - "anchor": "interoperability" + "title": "Install ParaSpell", + "anchor": "install-paraspell" }, { "depth": 2, @@ -6478,91 +5998,70 @@ } ], "stats": { - "chars": 9561, - "words": 1321, - "headings": 8, - "estimated_token_count_total": 1861 + "chars": 4043, + "words": 562, + "headings": 4, + "estimated_token_count_total": 888 }, - "hash": "sha256:932c12e1af939698279ede2eacb2190e1f56119582adf2064d6cf86f7a4f3e3c", + "hash": "sha256:c8741954ea656680aa3322c825e3f6acbaac369baaa42232b06af9e5e482f74f", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-parachains", - "title": "Parachains", - "slug": "polkadot-protocol-architecture-parachains", + "id": "reference-tools-polkadart", + "title": "Polkadart", + "slug": "reference-tools-polkadart", "categories": [ - "Uncategorized" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-parachains.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/parachains/", - "preview": "Discover how parachains secure their networks and reach consensus by harnessing Polkadot’s relay chain and its robust validator framework. This integrated architecture ensures shared security and seamless coordination across the entire ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md", + "html_url": "https://docs.polkadot.com/reference/tools/polkadart/", + "preview": "Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications.", "outline": [ { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 725, - "words": 93, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:3b9160b166d9b42b124f3b07eb26bdc5499fbbace6f951095009a5eee7fccbb6", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-architecture-polkadot-chain", - "title": "The Polkadot Relay Chain", - "slug": "polkadot-protocol-architecture-polkadot-chain", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-polkadot-chain.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/polkadot-chain/", - "preview": "Discover the central role of the Polkadot relay chain in securing the network and fostering interoperability. As the backbone of Polkadot, the relay chain provides shared security and ensures consensus across the ecosystem. It empowers parachains with flexible coretime allocation, enabling them to purchase blockspace on demand, ensuring efficiency and scalability for diverse blockchain applications.", - "outline": [ + "title": "Installation", + "anchor": "installation" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 481, - "words": 63, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:c29356358f095b0d413e4c6525146b3f1b0b900853aada2168e7e55cd8dd6641", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-architecture-system-chains-coretime", - "title": "Coretime Chain", - "slug": "polkadot-protocol-architecture-system-chains-coretime", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-system-chains-coretime.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/system-chains/coretime/", - "preview": "The Coretime system chain facilitates the allocation, procurement, sale, and scheduling of bulk [coretime](/reference/glossary/#coretime){target=\\_blank}, enabling tasks (such as [parachains](/reference/glossary/#parachain){target=\\_blank}) to utilize the computation and security provided by Polkadot.", - "outline": [ + "title": "Get Started", + "anchor": "get-started" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Type Generation", + "anchor": "type-generation" }, { - "depth": 2, - "title": "Bulk Coretime Assignment", - "anchor": "bulk-coretime-assignment" + "depth": 3, + "title": "Run Generator", + "anchor": "run-generator" }, { - "depth": 2, - "title": "On Demand Coretime", - "anchor": "on-demand-coretime" + "depth": 3, + "title": "Use Generated Types", + "anchor": "use-generated-types" + }, + { + "depth": 3, + "title": "Creating an API Instance", + "anchor": "creating-an-api-instance" + }, + { + "depth": 3, + "title": "Reading Chain Data", + "anchor": "reading-chain-data" + }, + { + "depth": 3, + "title": "Subscribe to New Blocks", + "anchor": "subscribe-to-new-blocks" + }, + { + "depth": 3, + "title": "Send a Transaction", + "anchor": "send-a-transaction" }, { "depth": 2, @@ -6571,25 +6070,25 @@ } ], "stats": { - "chars": 5279, - "words": 772, - "headings": 4, - "estimated_token_count_total": 1230 + "chars": 5178, + "words": 624, + "headings": 10, + "estimated_token_count_total": 1084 }, - "hash": "sha256:8d186fa56ccbbf4b6c85cffc5521b9a99a20e9517f3b4a435730745803cbf2e8", + "hash": "sha256:7f533abe61586af8438e350c41b741d74a8edb839f9dc4139bc4619ba3748258", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-system-chains-overview", - "title": "Overview of Polkadot's System Chains", - "slug": "polkadot-protocol-architecture-system-chains-overview", + "id": "reference-tools-polkadot-js-api", + "title": "Polkadot.js API", + "slug": "reference-tools-polkadot-js-api", "categories": [ - "Basics", - "Polkadot Protocol" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-system-chains-overview.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/system-chains/overview/", - "preview": "Polkadot's relay chain is designed to secure parachains and facilitate seamless inter-chain communication. However, resource-intensive—tasks like governance, asset management, and bridging are more efficiently handled by system parachains. These specialized chains offload functionality from the relay chain, leveraging Polkadot's parallel execution model to improve performance and scalability. By distributing key functionalities across system parachains, Polkadot can maximize its relay chain's bl", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md", + "html_url": "https://docs.polkadot.com/reference/tools/polkadot-js-api/", + "preview": "!!! warning \"Maintenance Mode Only\" The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank} (modern, type-safe API) as actively maintained alternatives.", "outline": [ { "depth": 2, @@ -6597,206 +6096,175 @@ "anchor": "introduction" }, { - "depth": 2, - "title": "System Chains", - "anchor": "system-chains" + "depth": 3, + "title": "Dynamic API Generation", + "anchor": "dynamic-api-generation" }, { - "depth": 2, - "title": "Existing System Chains", - "anchor": "existing-system-chains" + "depth": 3, + "title": "Available API Categories", + "anchor": "available-api-categories" }, { - "depth": 3, - "title": "Asset Hub", - "anchor": "asset-hub" + "depth": 2, + "title": "Installation", + "anchor": "installation" }, { - "depth": 3, - "title": "Collectives", - "anchor": "collectives" + "depth": 2, + "title": "Get Started", + "anchor": "get-started" }, { "depth": 3, - "title": "Bridge Hub", - "anchor": "bridge-hub" + "title": "Creating an API Instance", + "anchor": "creating-an-api-instance" }, { "depth": 3, - "title": "People Chain", - "anchor": "people-chain" + "title": "Reading Chain Data", + "anchor": "reading-chain-data" }, { "depth": 3, - "title": "Coretime Chain", - "anchor": "coretime-chain" + "title": "Sending Transactions", + "anchor": "sending-transactions" }, { - "depth": 3, - "title": "Encointer", - "anchor": "encointer" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 7727, - "words": 1105, + "chars": 5042, + "words": 684, "headings": 9, - "estimated_token_count_total": 1643 + "estimated_token_count_total": 1166 }, - "hash": "sha256:100377787627052a29bd1173270b5ad307639b828c331e71c85d4c00bc5692d8", + "hash": "sha256:ed3986f30880fefca5975fcdc847c68b4aca65862c63e3002b25391b0521781d", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-architecture-system-chains", - "title": "System Chains", - "slug": "polkadot-protocol-architecture-system-chains", + "id": "reference-tools-py-substrate-interface", + "title": "Python Substrate Interface", + "slug": "reference-tools-py-substrate-interface", "categories": [ - "Uncategorized" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture-system-chains.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/system-chains/", - "preview": "Explore the critical roles Polkadot’s system chains play in enhancing the network’s efficiency and scalability. From managing on-chain assets with the Asset Hub to enabling seamless Web3 integration through the Bridge Hub and facilitating coretime operations with the Coretime chain, each system chain is designed to offload specialized tasks from the relay chain, optimizing the entire ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md", + "html_url": "https://docs.polkadot.com/reference/tools/py-substrate-interface/", + "preview": "The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for:", "outline": [ { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 929, - "words": 124, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:6ef13c197dd1865fcc1a405d67486f1d053534d576bb32fe47a442fd2c11b6cd", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-architecture", - "title": "Architecture", - "slug": "polkadot-protocol-architecture", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-architecture.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/architecture/", - "preview": "Explore Polkadot's architecture, including the relay chain, parachains, and system chains, and discover the role each component plays in the broader ecosystem.", - "outline": [ + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Installation", + "anchor": "installation" + }, { "depth": 2, - "title": "A Brief Look at Polkadot’s Chain Ecosystem", - "anchor": "a-brief-look-at-polkadots-chain-ecosystem" + "title": "Get Started", + "anchor": "get-started" + }, + { + "depth": 3, + "title": "Establishing Connection", + "anchor": "establishing-connection" + }, + { + "depth": 3, + "title": "Reading Chain State", + "anchor": "reading-chain-state" + }, + { + "depth": 3, + "title": "Submitting Transactions", + "anchor": "submitting-transactions" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 990, - "words": 132, - "headings": 2, - "estimated_token_count_total": 177 + "chars": 4302, + "words": 541, + "headings": 7, + "estimated_token_count_total": 942 }, - "hash": "sha256:ffda04c93c70ec7204be28b642fa6e51f6bf9436d4792ecd25136696683f0902", + "hash": "sha256:8987fc35cd28602054ee018031f773e2e3837425107c51d0e2ac68a94b86e9c0", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-onchain-governance", - "title": "On-Chain Governance", - "slug": "polkadot-protocol-onchain-governance", + "id": "reference-tools-sidecar", + "title": "Sidecar REST API", + "slug": "reference-tools-sidecar", "categories": [ - "Uncategorized" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-onchain-governance.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/onchain-governance/", - "preview": "Polkadot's on-chain governance system, OpenGov, enables decentralized decision-making across the network. It empowers stakeholders to propose, vote on, and enact changes with transparency and efficiency. This system ensures that governance is both flexible and inclusive, allowing developers to integrate custom governance solutions and mechanisms within the network. Understanding how OpenGov functions is crucial for anyone looking to engage with Polkadot’s decentralized ecosystem, whether you’re", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md", + "html_url": "https://docs.polkadot.com/reference/tools/sidecar/", + "preview": "The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more.", "outline": [ { "depth": 2, - "title": "Start Building Governance Solutions", - "anchor": "start-building-governance-solutions" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 2114, - "words": 285, - "headings": 2, - "estimated_token_count_total": 233 - }, - "hash": "sha256:58fd5c8c092ee748c2979164f985a67071a6ccb88492e79cdad536363364c858", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-parachain-basics-blocks-transactions-fees", - "title": "Blocks, Transactions, and Fees", - "slug": "polkadot-protocol-parachain-basics-blocks-transactions-fees", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics-blocks-transactions-fees.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/blocks-transactions-fees/", - "preview": "Discover the inner workings of Polkadot’s blocks and transactions, including their structure, processing, and lifecycle within the network. Learn how blocks are authored, validated, and finalized, ensuring seamless operation and consensus across the ecosystem. Dive into the various types of transactions—signed, unsigned, and inherent—and understand how they are constructed, submitted, and validated.", - "outline": [ + "title": "Prerequisites", + "anchor": "prerequisites" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 788, - "words": 105, - "headings": 1, - "estimated_token_count_total": 12 - }, - "hash": "sha256:235f33cdb64494815dbb3eb58ea98c69935098684e1b34b6d15356bc54b082ea", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol-parachain-basics", - "title": "Parachain Basics", - "slug": "polkadot-protocol-parachain-basics", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-parachain-basics.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/parachain-basics/", - "preview": "This section equips developers with the essential knowledge to create, deploy, and enhance applications and blockchains within the Polkadot ecosystem. Gain a comprehensive understanding of Polkadot’s foundational components, including accounts, balances, and transactions, as well as advanced topics like data encoding and cryptographic methods. Mastering these concepts is vital for building robust and secure applications on Polkadot.", - "outline": [ + "title": "Installation", + "anchor": "installation" + }, + { + "depth": 2, + "title": "Usage", + "anchor": "usage" + }, + { + "depth": 3, + "title": "Endpoints", + "anchor": "endpoints" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 998, - "words": 130, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 7309, + "words": 1033, + "headings": 6, + "estimated_token_count_total": 1945 }, - "hash": "sha256:1514316acba1e9bba82ae1c82b09481e9d03d286e6f5d93b66e5a85fd4be7bca", + "hash": "sha256:0795462182cb97256bb5c2acb035855fe0d6557185de8ac99482725ecb4f94c1", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-smart-contract-basics-evm-vs-polkavm", - "title": "EVM vs PolkaVM", - "slug": "polkadot-protocol-smart-contract-basics-evm-vs-polkavm", + "id": "reference-tools-subxt", + "title": "Subxt Rust API", + "slug": "reference-tools-subxt", "categories": [ - "Basics", - "Polkadot Protocol" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-evm-vs-polkavm.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md", + "html_url": "https://docs.polkadot.com/reference/tools/subxt/", + "preview": "Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability.", "outline": [ { "depth": 2, @@ -6805,110 +6273,71 @@ }, { "depth": 2, - "title": "Core Virtual Machine Architecture", - "anchor": "core-virtual-machine-architecture" - }, - { - "depth": 3, - "title": "High-Level Architecture Comparison", - "anchor": "high-level-architecture-comparison" - }, - { - "depth": 2, - "title": "Gas Model", - "anchor": "gas-model" - }, - { - "depth": 3, - "title": "Dynamic Gas Value Scaling", - "anchor": "dynamic-gas-value-scaling" - }, - { - "depth": 3, - "title": "Multi-Dimensional Resource Metering", - "anchor": "multi-dimensional-resource-metering" - }, - { - "depth": 2, - "title": "Memory Management", - "anchor": "memory-management" - }, - { - "depth": 3, - "title": "Current Memory Limits", - "anchor": "current-memory-limits" - }, - { - "depth": 2, - "title": "Account Management - Existential Deposit", - "anchor": "account-management-existential-deposit" - }, - { - "depth": 3, - "title": "Account Management Comparison", - "anchor": "account-management-comparison" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Contract Deployment", - "anchor": "contract-deployment" + "title": "Installation", + "anchor": "installation" }, { "depth": 2, - "title": "Solidity and YUL IR Translation Incompatibilities", - "anchor": "solidity-and-yul-ir-translation-incompatibilities" + "title": "Get Started", + "anchor": "get-started" }, { "depth": 3, - "title": "Contract Code Structure", - "anchor": "contract-code-structure" + "title": "Download Chain Metadata", + "anchor": "download-chain-metadata" }, { "depth": 3, - "title": "Solidity-Specific Differences", - "anchor": "solidity-specific-differences" + "title": "Generate Type-Safe Interfaces", + "anchor": "generate-type-safe-interfaces" }, { "depth": 3, - "title": "YUL Function Translation Differences", - "anchor": "yul-function-translation-differences" + "title": "Initialize the Subxt Client", + "anchor": "initialize-the-subxt-client" }, { "depth": 3, - "title": "Unsupported Operations", - "anchor": "unsupported-operations" + "title": "Read Chain Data", + "anchor": "read-chain-data" }, { "depth": 3, - "title": "Compilation Pipeline Considerations", - "anchor": "compilation-pipeline-considerations" + "title": "Submit Transactions", + "anchor": "submit-transactions" }, { - "depth": 3, - "title": "Memory Pointer Limitations", - "anchor": "memory-pointer-limitations" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 27673, - "words": 3392, - "headings": 18, - "estimated_token_count_total": 5305 + "chars": 9174, + "words": 1175, + "headings": 10, + "estimated_token_count_total": 2187 }, - "hash": "sha256:fe651be49fe0a9ae899b2cbf9c663325f407718dc63f1d2c6a2dc4931be751fa", + "hash": "sha256:56269d9ea47f5b4e92cd7d5a1e65ab06d181a9c380f90bb3ef285529b12299f7", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-smart-contract-basics-networks", - "title": "Networks for Polkadot Hub Smart Contracts", - "slug": "polkadot-protocol-smart-contract-basics-networks", + "id": "reference-tools-xcm-tools", + "title": "XCM Tools", + "slug": "reference-tools-xcm-tools", "categories": [ "Basics", - "Polkadot Protocol" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-networks.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/networks/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md", + "html_url": "https://docs.polkadot.com/reference/tools/xcm-tools/", + "preview": "As described in the [Interoperability](/develop/interoperability){target=\\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem.", "outline": [ { "depth": 2, @@ -6917,65 +6346,76 @@ }, { "depth": 2, - "title": "Network Overview", - "anchor": "network-overview" - }, - { - "depth": 2, - "title": "Local Development", - "anchor": "local-development" - }, - { - "depth": 2, - "title": "Test Networks", - "anchor": "test-networks" + "title": "Popular XCM Tools", + "anchor": "popular-xcm-tools" }, { "depth": 3, - "title": "Passet Hub", - "anchor": "passet-hub" + "title": "Moonsong Labs XCM Tools", + "anchor": "moonsong-labs-xcm-tools" }, { "depth": 3, - "title": "Westend Hub", - "anchor": "westend-hub" + "title": "ParaSpell", + "anchor": "paraspell" }, { - "depth": 2, - "title": "Production Networks", - "anchor": "production-networks" + "depth": 3, + "title": "Astar XCM Tools", + "anchor": "astar-xcm-tools" }, { "depth": 3, - "title": "Polkadot Hub", - "anchor": "polkadot-hub" + "title": "Chopsticks", + "anchor": "chopsticks" }, { "depth": 3, - "title": "Kusama Hub", - "anchor": "kusama-hub" + "title": "Moonbeam XCM SDK", + "anchor": "moonbeam-xcm-sdk" } ], "stats": { - "chars": 5108, - "words": 696, - "headings": 9, - "estimated_token_count_total": 891 + "chars": 6146, + "words": 852, + "headings": 7, + "estimated_token_count_total": 1377 + }, + "hash": "sha256:674e4f60c82fc7544c7af8e09f1e0f677c9907cdff88b107f6c8489e97a43487", + "token_estimator": "heuristic-v1" + }, + { + "id": "reference-tools-zombienet", + "title": "reference-tools-zombienet", + "slug": "reference-tools-zombienet", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md", + "html_url": "https://docs.polkadot.com/reference/tools/zombienet/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 }, - "hash": "sha256:b5acdc9acf0e44836b8a4518155eba7d16cc3b103c557a00970ffb1c44c3e9f6", + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-smart-contract-basics-overview", - "title": "Smart Contracts Basics Overview", - "slug": "polkadot-protocol-smart-contract-basics-overview", + "id": "reference", + "title": "Technical Reference Overview", + "slug": "reference", "categories": [ "Basics", - "Polkadot Protocol" + "Polkadot Protocol", + "Reference" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics-overview.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/overview/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md", + "html_url": "https://docs.polkadot.com/reference/", + "preview": "The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need.", "outline": [ { "depth": 2, @@ -6984,442 +6424,476 @@ }, { "depth": 2, - "title": "Smart Contracts Versus Parachains", - "anchor": "smart-contracts-versus-parachains" + "title": "Polkadot Hub", + "anchor": "polkadot-hub" }, { "depth": 2, - "title": "Building a Smart Contract", - "anchor": "building-a-smart-contract" + "title": "Parachains", + "anchor": "parachains" }, { - "depth": 3, - "title": "PolkaVM Contracts", - "anchor": "polkavm-contracts" + "depth": 2, + "title": "On-Chain Governance", + "anchor": "on-chain-governance" }, { - "depth": 3, - "title": "EVM Contracts", - "anchor": "evm-contracts" + "depth": 2, + "title": "Glossary", + "anchor": "glossary" }, { - "depth": 3, - "title": "Wasm Contracts", - "anchor": "wasm-contracts" + "depth": 2, + "title": "Tools", + "anchor": "tools" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 10854, - "words": 1559, - "headings": 6, - "estimated_token_count_total": 2550 + "chars": 7648, + "words": 937, + "headings": 7, + "estimated_token_count_total": 1682 }, - "hash": "sha256:5d293525ce81d27e32c26938a029a6a82b137221a0630d084f528853ffaf798e", + "hash": "sha256:9f71f3b4018f7a9e127cff51fab7cfe1168adcde2553cd1fc5dc8c25fb97a30d", "token_estimator": "heuristic-v1" }, { - "id": "polkadot-protocol-smart-contract-basics", - "title": "Smart Contract Basics", - "slug": "polkadot-protocol-smart-contract-basics", + "id": "smart-contracts-connect", + "title": "Connect to Polkadot", + "slug": "smart-contracts-connect", "categories": [ - "Uncategorized" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol-smart-contract-basics.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Gain a deep understanding of smart contracts on Polkadot, from execution environments to transaction mechanics.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-connect.md", + "html_url": "https://docs.polkadot.com/smart-contracts/connect/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", "outline": [ { "depth": 2, - "title": "Key Topics", - "anchor": "key-topics" + "title": "Networks Details", + "anchor": "networks-details" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 1110, - "words": 136, - "headings": 2, - "estimated_token_count_total": 148 - }, - "hash": "sha256:e8dac01e89b7aac4b887e962e91084c253f5ea25c1abc3a56355390d0c3201c8", - "token_estimator": "heuristic-v1" - }, - { - "id": "polkadot-protocol", - "title": "Learn About the Polkadot Protocol", - "slug": "polkadot-protocol", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/polkadot-protocol.md", - "html_url": "https://docs.polkadot.com/polkadot-protocol/", - "preview": "The Polkadot protocol is designed to enable scalable, secure, and interoperable networks. It introduces a unique multichain architecture that allows independent blockchains, known as parachains, to operate seamlessly while benefiting from the shared security of the relay chain. Polkadot’s decentralized governance ensures that network upgrades and decisions are community-driven, while its cross-chain messaging and interoperability features make it a hub for multichain applications.", - "outline": [ + "title": "Test Tokens", + "anchor": "test-tokens" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 1170, - "words": 150, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 3459, + "words": 476, + "headings": 3, + "estimated_token_count_total": 558 }, - "hash": "sha256:49be4b4b5289572086eaaaf9ccff3bee7879b534188331c9a8052b3fe5aa4933", + "hash": "sha256:a2490223926957381913ae0ed22e2df3611a6713ec9d77a3015d1cd6a578b3f6", "token_estimator": "heuristic-v1" }, { - "id": "reference-glossary", - "title": "Glossary", - "slug": "reference-glossary", + "id": "smart-contracts-cookbook-dapps-zero-to-hero", + "title": "Zero to Hero Smart Contract DApp", + "slug": "smart-contracts-cookbook-dapps-zero-to-hero", "categories": [ - "Reference" + "dApp", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md", - "html_url": "https://docs.polkadot.com/reference/glossary/", - "preview": "Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/dapps/zero-to-hero/", + "preview": "Decentralized applications (dApps) are a key component of the Web3 ecosystem, enabling developers to build applications that communicate directly with blockchain networks. Polkadot Hub, a blockchain with smart contract support, serves as a robust platform for deploying and interacting with dApps.", "outline": [ { "depth": 2, - "title": "Authority", - "anchor": "authority" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Authority Round (Aura)", - "anchor": "authority-round-aura" + "title": "Project Overview", + "anchor": "project-overview" }, { "depth": 2, - "title": "Blind Assignment of Blockchain Extension (BABE)", - "anchor": "blind-assignment-of-blockchain-extension-babe" + "title": "Create and Deploy the Storage Contract", + "anchor": "create-and-deploy-the-storage-contract" }, { - "depth": 2, - "title": "Block Author", - "anchor": "block-author" + "depth": 3, + "title": "Set Up Hardhat Project", + "anchor": "set-up-hardhat-project" }, { - "depth": 2, - "title": "Byzantine Fault Tolerance (BFT)", - "anchor": "byzantine-fault-tolerance-bft" + "depth": 3, + "title": "Create the Storage Contract", + "anchor": "create-the-storage-contract" }, { "depth": 3, - "title": "Byzantine Failure", - "anchor": "byzantine-failure" + "title": "Configure Hardhat for Polkadot Hub", + "anchor": "configure-hardhat-for-polkadot-hub" }, { "depth": 3, - "title": "Practical Byzantine Fault Tolerance (pBFT)", - "anchor": "practical-byzantine-fault-tolerance-pbft" + "title": "Compile the Contract", + "anchor": "compile-the-contract" }, { "depth": 3, - "title": "Preimage", - "anchor": "preimage" + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" }, { - "depth": 2, - "title": "Call", - "anchor": "call" + "depth": 3, + "title": "Export the Contract ABI", + "anchor": "export-the-contract-abi" }, { "depth": 2, - "title": "Chain Specification", - "anchor": "chain-specification" + "title": "Set Up the dApp Project", + "anchor": "set-up-the-dapp-project" }, { "depth": 2, - "title": "Collator", - "anchor": "collator" + "title": "Install Dependencies", + "anchor": "install-dependencies" }, { "depth": 2, - "title": "Collective", - "anchor": "collective" + "title": "Connect to Polkadot Hub", + "anchor": "connect-to-polkadot-hub" }, { "depth": 2, - "title": "Consensus", - "anchor": "consensus" + "title": "Set Up the Smart Contract Interface", + "anchor": "set-up-the-smart-contract-interface" }, { "depth": 2, - "title": "Consensus Algorithm", - "anchor": "consensus-algorithm" + "title": "Create the Wallet Connection Component", + "anchor": "create-the-wallet-connection-component" }, { "depth": 2, - "title": "Consensus Engine", - "anchor": "consensus-engine" + "title": "Create the Read Contract Component", + "anchor": "create-the-read-contract-component" }, { "depth": 2, - "title": "Coretime", - "anchor": "coretime" + "title": "Create the Write Contract Component", + "anchor": "create-the-write-contract-component" }, { "depth": 2, - "title": "Development Phrase", - "anchor": "development-phrase" - }, - { - "depth": 2, - "title": "Digest", - "anchor": "digest" - }, - { - "depth": 2, - "title": "Dispatchable", - "anchor": "dispatchable" - }, - { - "depth": 2, - "title": "Events", - "anchor": "events" - }, - { - "depth": 2, - "title": "Executor", - "anchor": "executor" - }, - { - "depth": 2, - "title": "Existential Deposit", - "anchor": "existential-deposit" + "title": "How It Works", + "anchor": "how-it-works" }, { - "depth": 2, - "title": "Extrinsic", - "anchor": "extrinsic" + "depth": 3, + "title": "Wallet Connection", + "anchor": "wallet-connection" }, { - "depth": 2, - "title": "Fork Choice Rule/Strategy", - "anchor": "fork-choice-rulestrategy" + "depth": 3, + "title": "Data Reads", + "anchor": "data-reads" }, { - "depth": 2, - "title": "FRAME (Framework for Runtime Aggregation of Modularized Entities)", - "anchor": "frame-framework-for-runtime-aggregation-of-modularized-entities" + "depth": 3, + "title": "Data Writes", + "anchor": "data-writes" }, { "depth": 2, - "title": "Full Node", - "anchor": "full-node" + "title": "Conclusion", + "anchor": "conclusion" }, { "depth": 2, - "title": "Genesis Configuration", - "anchor": "genesis-configuration" - }, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 31207, + "words": 3688, + "headings": 22, + "estimated_token_count_total": 6967 + }, + "hash": "sha256:b200f93a9179f0b2588ba722dd4c118536136faf3c39eabccf4abf5c346f78a8", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-eth-dapps-uniswap-v2", + "title": "Deploying Uniswap V2 on Polkadot", + "slug": "smart-contracts-cookbook-eth-dapps-uniswap-v2", + "categories": [ + "dApps", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "outline": [ { "depth": 2, - "title": "GRANDPA", - "anchor": "grandpa" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Header", - "anchor": "header" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Hybrid Consensus", - "anchor": "hybrid-consensus" + "title": "Set Up the Project", + "anchor": "set-up-the-project" }, { "depth": 2, - "title": "Inherent Transactions", - "anchor": "inherent-transactions" + "title": "Understanding Uniswap V2 Architecture", + "anchor": "understanding-uniswap-v2-architecture" }, { "depth": 2, - "title": "JSON-RPC", - "anchor": "json-rpc" + "title": "Test the Contracts", + "anchor": "test-the-contracts" }, { "depth": 2, - "title": "Keystore", - "anchor": "keystore" + "title": "Deploy the Contracts", + "anchor": "deploy-the-contracts" }, { "depth": 2, - "title": "Kusama", - "anchor": "kusama" - }, + "title": "Conclusion", + "anchor": "conclusion" + } + ], + "stats": { + "chars": 11280, + "words": 1560, + "headings": 7, + "estimated_token_count_total": 2671 + }, + "hash": "sha256:2a42198668c759f63aa602115bf2d290ec7d03bbc3a3df20e30e85027e1b1cc3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", + "title": "Deploy a Basic Contract to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/.deploy-basic-pvm/", + "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", + "outline": [ { "depth": 2, - "title": "libp2p", - "anchor": "libp2p" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Light Client", - "anchor": "light-client" + "title": "JavaScript with Ethers.js", + "anchor": "javascript-with-ethersjs" }, { - "depth": 2, - "title": "Metadata", - "anchor": "metadata" + "depth": 3, + "title": "Setup", + "anchor": "setup" }, { - "depth": 2, - "title": "Nominated Proof of Stake (NPoS)", - "anchor": "nominated-proof-of-stake-npos" + "depth": 3, + "title": "Create and Compile Your Contract", + "anchor": "create-and-compile-your-contract" }, { - "depth": 2, - "title": "Oracle", - "anchor": "oracle" + "depth": 3, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" }, { "depth": 2, - "title": "Origin", - "anchor": "origin" + "title": "Remix IDE", + "anchor": "remix-ide" }, { - "depth": 2, - "title": "Pallet", - "anchor": "pallet" + "depth": 3, + "title": "Access Remix", + "anchor": "access-remix" }, { - "depth": 2, - "title": "Parachain", - "anchor": "parachain" + "depth": 3, + "title": "Compile", + "anchor": "compile" }, { - "depth": 2, - "title": "Paseo", - "anchor": "paseo" + "depth": 3, + "title": "Deploy", + "anchor": "deploy" }, { "depth": 2, - "title": "Polkadot", - "anchor": "polkadot" + "title": "Hardhat", + "anchor": "hardhat" }, { - "depth": 2, - "title": "Polkadot Cloud", - "anchor": "polkadot-cloud" + "depth": 3, + "title": "Setup", + "anchor": "setup-2" }, { - "depth": 2, - "title": "Polkadot Hub", - "anchor": "polkadot-hub" + "depth": 3, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" }, { - "depth": 2, - "title": "PolkaVM", - "anchor": "polkavm" + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { - "depth": 2, - "title": "Relay Chain", - "anchor": "relay-chain" + "depth": 3, + "title": "Compile", + "anchor": "compile-2" }, { - "depth": 2, - "title": "Rococo", - "anchor": "rococo" + "depth": 3, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" }, { - "depth": 2, - "title": "Runtime", - "anchor": "runtime" + "depth": 3, + "title": "Deploy", + "anchor": "deploy-2" }, { "depth": 2, - "title": "Slot", - "anchor": "slot" + "title": "Foundry", + "anchor": "foundry" }, { - "depth": 2, - "title": "Sovereign Account", - "anchor": "sovereign-account" + "depth": 3, + "title": "Setup", + "anchor": "setup-3" }, { - "depth": 2, - "title": "SS58 Address Format", - "anchor": "ss58-address-format" + "depth": 3, + "title": "Configure Foundry", + "anchor": "configure-foundry" }, { - "depth": 2, - "title": "State Transition Function (STF)", - "anchor": "state-transition-function-stf" + "depth": 3, + "title": "Create Your Contract", + "anchor": "create-your-contract-2" }, { - "depth": 2, - "title": "Storage Item", - "anchor": "storage-item" + "depth": 3, + "title": "Compile", + "anchor": "compile-3" }, { - "depth": 2, - "title": "Substrate", - "anchor": "substrate" + "depth": 3, + "title": "Deploy", + "anchor": "deploy-3" }, { "depth": 2, - "title": "Transaction", - "anchor": "transaction" + "title": "Conclusion", + "anchor": "conclusion" }, { - "depth": 2, - "title": "Transaction Era", - "anchor": "transaction-era" + "depth": 3, + "title": "Next Steps", + "anchor": "next-steps" + } + ], + "stats": { + "chars": 13872, + "words": 1640, + "headings": 24, + "estimated_token_count_total": 3228 + }, + "hash": "sha256:8f29b0f0b56f8c136206211a858cdc5bc27bcd9119eab179a6cd306182d910cb", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry", + "title": "Deploy a Basic Contract with Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry", + "categories": [ + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/.foundry/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Foundry](https://getfoundry.sh/){target=\\_blank}, which offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", + "outline": [ + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Trie (Patricia Merkle Tree)", - "anchor": "trie-patricia-merkle-tree" + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { "depth": 2, - "title": "Validator", - "anchor": "validator" + "title": "Configure Foundry", + "anchor": "configure-foundry" }, { "depth": 2, - "title": "WebAssembly (Wasm)", - "anchor": "webassembly-wasm" + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { "depth": 2, - "title": "Weight", - "anchor": "weight" + "title": "Compile", + "anchor": "compile" }, { "depth": 2, - "title": "Westend", - "anchor": "westend" + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 24739, - "words": 3626, - "headings": 63, - "estimated_token_count_total": 5273 + "chars": 2731, + "words": 355, + "headings": 7, + "estimated_token_count_total": 598 }, - "hash": "sha256:40bd67811e7eabc79ca5d105eae388b19380d9f035022da17fc0d6bb173c817c", + "hash": "sha256:63defd84f302f0778c90129abbe69ecd2a5d9d83c622f2b7e5c2ffc9bcb3312f", "token_estimator": "heuristic-v1" }, { - "id": "reference-governance-origins-tracks", - "title": "Origins and Tracks", - "slug": "reference-governance-origins-tracks", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", + "title": "Deploy a Basic Contract with Hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", "categories": [ - "Polkadot Protocol" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance-origins-tracks.md", - "html_url": "https://docs.polkadot.com/reference/governance/origins-tracks/", - "preview": "Polkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Hardhat](https://hardhat.org/){target=\\_blank}, which provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", "outline": [ { "depth": 2, @@ -7428,40 +6902,64 @@ }, { "depth": 2, - "title": "Origins", - "anchor": "origins" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Tracks", - "anchor": "tracks" + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Configure Hardhat", + "anchor": "configure-hardhat" + }, + { + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" + }, + { + "depth": 2, + "title": "Compile", + "anchor": "compile" + }, + { + "depth": 2, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" + }, + { + "depth": 2, + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 3333, - "words": 469, - "headings": 4, - "estimated_token_count_total": 631 + "chars": 4051, + "words": 475, + "headings": 9, + "estimated_token_count_total": 981 }, - "hash": "sha256:baba9dd41091b792d09005d55d3df0bf65b35f42b40ebe63caf425a0978a22b0", + "hash": "sha256:98f5c5c1a26db913e1c4c435062d214ca8c4b5f2dbed5b64d2e54c3435f06452", "token_estimator": "heuristic-v1" }, { - "id": "reference-governance", - "title": "On-Chain Governance Overview", - "slug": "reference-governance", + "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", + "title": "Deploy a Basic Contract with Remix IDE", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", "categories": [ - "Basics", - "Polkadot Protocol" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md", - "html_url": "https://docs.polkadot.com/reference/governance/", - "preview": "Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/", + "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Remix IDE](https://remix.ethereum.org/){target=\\_blank}, which offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", "outline": [ { "depth": 2, @@ -7470,65 +6968,50 @@ }, { "depth": 2, - "title": "Governance Evolution", - "anchor": "governance-evolution" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "OpenGov Key Features", - "anchor": "opengov-key-features" + "title": "Access Remix", + "anchor": "access-remix" }, { "depth": 2, - "title": "Origins and Tracks", - "anchor": "origins-and-tracks" + "title": "Compile", + "anchor": "compile" }, { "depth": 2, - "title": "Referendums", - "anchor": "referendums" - }, - { - "depth": 3, - "title": "Vote on Referendums", - "anchor": "vote-on-referendums" - }, - { - "depth": 3, - "title": "Delegate Voting Power", - "anchor": "delegate-voting-power" - }, - { - "depth": 3, - "title": "Cancel a Referendum", - "anchor": "cancel-a-referendum" + "title": "Deploy", + "anchor": "deploy" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 7493, - "words": 1019, - "headings": 9, - "estimated_token_count_total": 1611 + "chars": 2978, + "words": 430, + "headings": 6, + "estimated_token_count_total": 738 }, - "hash": "sha256:62beec261e72529f70e07a641177d489d2c8872f9c9d618cbadf1ac0fd881986", + "hash": "sha256:0c00544ba0be9c0a6fa0c54bdb38045d64e95af714785b86e57f885a03b4b17a", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-accounts", - "title": "Polkadot SDK Accounts", - "slug": "reference-parachains-accounts", + "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat", + "title": "Deploy an ERC-20 to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat", "categories": [ "Basics", - "Polkadot Protocol" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md", - "html_url": "https://docs.polkadot.com/reference/parachains/accounts/", - "preview": "Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/", + "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", "outline": [ { "depth": 2, @@ -7537,95 +7020,60 @@ }, { "depth": 2, - "title": "Account Data Structure", - "anchor": "account-data-structure" - }, - { - "depth": 3, - "title": "Account", - "anchor": "account" - }, - { - "depth": 3, - "title": "Account Info", - "anchor": "account-info" - }, - { - "depth": 3, - "title": "Account Reference Counters", - "anchor": "account-reference-counters" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Account Balance Types", - "anchor": "account-balance-types" - }, - { - "depth": 3, - "title": "Balance Types", - "anchor": "balance-types" - }, - { - "depth": 3, - "title": "Locks", - "anchor": "locks" + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { - "depth": 3, - "title": "Balance Types on Polkadot.js", - "anchor": "balance-types-on-polkadotjs" + "depth": 2, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" }, { "depth": 2, - "title": "Address Formats", - "anchor": "address-formats" + "title": "Compile your Contract", + "anchor": "compile-your-contract" }, { - "depth": 3, - "title": "Basic Format", - "anchor": "basic-format" + "depth": 2, + "title": "Test your Contract", + "anchor": "test-your-contract" }, { - "depth": 3, - "title": "Address Type", - "anchor": "address-type" + "depth": 2, + "title": "Deploy your Contract", + "anchor": "deploy-your-contract" }, { - "depth": 3, - "title": "Address Length", - "anchor": "address-length" - }, - { - "depth": 3, - "title": "Checksum Types", - "anchor": "checksum-types" - }, - { - "depth": 3, - "title": "Validating Addresses", - "anchor": "validating-addresses" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 29604, - "words": 4194, - "headings": 15, - "estimated_token_count_total": 6507 + "chars": 8131, + "words": 1205, + "headings": 8, + "estimated_token_count_total": 2156 }, - "hash": "sha256:0104a9132a69345a2faac37fca0e2853a2ded1efb009511a83a98d44509ab887", + "hash": "sha256:4036cb47abaf081ce480654bece336f83bd043f5225d5d8d20f152fb91aa2157", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-blocks", - "title": "Blocks", - "slug": "reference-parachains-blocks-transactions-fees-blocks", + "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", + "title": "Deploy an ERC-20 to Polkadot Hub", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", "categories": [ "Basics", - "Polkadot Protocol" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/", - "preview": "In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/", + "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", "outline": [ { "depth": 2, @@ -7634,157 +7082,184 @@ }, { "depth": 2, - "title": "What is a Block?", - "anchor": "what-is-a-block" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Block Production", - "anchor": "block-production" - }, - { - "depth": 3, - "title": "Initialize Block", - "anchor": "initialize-block" + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { - "depth": 3, - "title": "Finalize Block", - "anchor": "finalize-block" + "depth": 2, + "title": "Compile", + "anchor": "compile" }, { "depth": 2, - "title": "Block Authoring and Import", - "anchor": "block-authoring-and-import" + "title": "Deploy", + "anchor": "deploy" }, { - "depth": 3, - "title": "Block Import Queue", - "anchor": "block-import-queue" + "depth": 2, + "title": "Interact with Your Contract", + "anchor": "interact-with-your-contract" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 6252, - "words": 910, - "headings": 8, - "estimated_token_count_total": 1395 + "chars": 9121, + "words": 1261, + "headings": 7, + "estimated_token_count_total": 2183 }, - "hash": "sha256:424783c102bea5dae5b8749635858c6c59055563442a98f57521f0027dafa8d3", + "hash": "sha256:992767525da7c1323f28bcaee5b6d1256ee2c0c70dbd16ae521245299858d996", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-fees", - "title": "Transactions Weights and Fees", - "slug": "reference-parachains-blocks-transactions-fees-fees", + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry", + "title": "Deploy an NFT to Polkadot Hub with Foundry", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry", "categories": [ "Basics", - "Polkadot Protocol" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/", - "preview": "When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop th", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/.foundry/", + "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", "outline": [ { "depth": 2, - "title": "Introductions", - "anchor": "introductions" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "How Fees are Calculated", - "anchor": "how-fees-are-calculated" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Using the Transaction Payment Pallet", - "anchor": "using-the-transaction-payment-pallet" + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { - "depth": 3, - "title": "Understanding the Inclusion Fee", - "anchor": "understanding-the-inclusion-fee" + "depth": 2, + "title": "Configure Foundry", + "anchor": "configure-foundry" }, { - "depth": 3, - "title": "Accounts with an Insufficient Balance", - "anchor": "accounts-with-an-insufficient-balance" + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { - "depth": 3, - "title": "Fee Multipliers", - "anchor": "fee-multipliers" + "depth": 2, + "title": "Compile", + "anchor": "compile" }, { "depth": 2, - "title": "Transactions with Special Requirements", - "anchor": "transactions-with-special-requirements" + "title": "Deploy", + "anchor": "deploy" }, { "depth": 2, - "title": "Default Weight Annotations", - "anchor": "default-weight-annotations" + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 3489, + "words": 438, + "headings": 8, + "estimated_token_count_total": 847 + }, + "hash": "sha256:c4b410125946db479b9c262a5132a31bb7730a778501c3a95910ad9d38007cf4", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", + "title": "Deploy an NFT to Polkadot Hub with Hardhat", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", + "categories": [ + "Basics", + "Smart Contracts" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/", + "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "Weights and Database Read/Write Operations", - "anchor": "weights-and-database-readwrite-operations" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "Dispatch Classes", - "anchor": "dispatch-classes" + "depth": 2, + "title": "Set Up Your Project", + "anchor": "set-up-your-project" }, { - "depth": 3, - "title": "Dynamic Weights", - "anchor": "dynamic-weights" + "depth": 2, + "title": "Configure Hardhat", + "anchor": "configure-hardhat" }, { "depth": 2, - "title": "Post Dispatch Weight Correction", - "anchor": "post-dispatch-weight-correction" + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { "depth": 2, - "title": "Custom Fees", - "anchor": "custom-fees" + "title": "Compile", + "anchor": "compile" }, { - "depth": 3, - "title": "Custom Weights", - "anchor": "custom-weights" + "depth": 2, + "title": "Set Up Deployment", + "anchor": "set-up-deployment" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Deploy", + "anchor": "deploy" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 20800, - "words": 2917, - "headings": 15, - "estimated_token_count_total": 4464 + "chars": 4837, + "words": 565, + "headings": 9, + "estimated_token_count_total": 1152 }, - "hash": "sha256:7d0c3fa7982b3e1843adb8f27422456397580b3a3eba5047b381da8517742536", + "hash": "sha256:1e44c9df24715affa822f0df9680413cd995909f2c086d3a70499ee69901985e", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-transactions", - "title": "Transactions", - "slug": "reference-parachains-blocks-transactions-fees-transactions", + "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", + "title": "Deploy an NFT to Polkadot Hub with Remix", + "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", "categories": [ "Basics", - "Polkadot Protocol" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/", - "preview": "Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/", + "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", "outline": [ { "depth": 2, @@ -7793,225 +7268,91 @@ }, { "depth": 2, - "title": "What Is a Transaction?", - "anchor": "what-is-a-transaction" - }, - { - "depth": 3, - "title": "Signed Transactions", - "anchor": "signed-transactions" - }, - { - "depth": 3, - "title": "Unsigned Transactions", - "anchor": "unsigned-transactions" - }, - { - "depth": 3, - "title": "Inherent Transactions", - "anchor": "inherent-transactions" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Transaction Formats", - "anchor": "transaction-formats" + "title": "Access Remix", + "anchor": "access-remix" }, { - "depth": 3, - "title": "Types of Transaction Formats", - "anchor": "types-of-transaction-formats" + "depth": 2, + "title": "Create Your Contract", + "anchor": "create-your-contract" }, { - "depth": 3, - "title": "Signed Transaction Data Structure", - "anchor": "signed-transaction-data-structure" + "depth": 2, + "title": "Compile", + "anchor": "compile" }, { - "depth": 3, - "title": "Signed Extensions", - "anchor": "signed-extensions" + "depth": 2, + "title": "Deploy", + "anchor": "deploy" }, { "depth": 2, - "title": "Transaction Construction", - "anchor": "transaction-construction" - }, - { - "depth": 3, - "title": "Construct a Signed Transaction", - "anchor": "construct-a-signed-transaction" - }, - { - "depth": 3, - "title": "Transaction Encoding", - "anchor": "transaction-encoding" - }, - { - "depth": 3, - "title": "Customize Transaction Construction", - "anchor": "customize-transaction-construction" - }, - { - "depth": 2, - "title": "Lifecycle of a Transaction", - "anchor": "lifecycle-of-a-transaction" - }, - { - "depth": 3, - "title": "Define Transaction Properties", - "anchor": "define-transaction-properties" - }, - { - "depth": 3, - "title": "Process on a Block Authoring Node", - "anchor": "process-on-a-block-authoring-node" - }, - { - "depth": 3, - "title": "Validate and Queue", - "anchor": "validate-and-queue" - }, - { - "depth": 3, - "title": "Transaction Ordering and Priority", - "anchor": "transaction-ordering-and-priority" - }, - { - "depth": 3, - "title": "Transaction Execution", - "anchor": "transaction-execution" - }, - { - "depth": 2, - "title": "Transaction Mortality", - "anchor": "transaction-mortality" - }, - { - "depth": 2, - "title": "Unique Identifiers for Extrinsics", - "anchor": "unique-identifiers-for-extrinsics" - }, - { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 23610, - "words": 3333, - "headings": 22, - "estimated_token_count_total": 4708 + "chars": 3754, + "words": 505, + "headings": 7, + "estimated_token_count_total": 928 }, - "hash": "sha256:66726634d3a51cd9c471621054a6e5f09c8061dca6144b64c8bcf45626359617", + "hash": "sha256:12a8debfbc05c5ac0e2c94daa40167adab837dc4e1b2731f5b48ae8bc9bc2c93", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-chain-data", - "title": "Chain Data", - "slug": "reference-parachains-chain-data", + "id": "smart-contracts-cookbook", + "title": "Smart Contracts Cookbook Index", + "slug": "smart-contracts-cookbook", "categories": [ "Basics", - "Polkadot Protocol" + "dApps", + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md", - "html_url": "https://docs.polkadot.com/reference/parachains/chain-data/", - "preview": "Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md", + "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/", + "preview": "Welcome to the Polkadot smart contracts cookbook index.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Application Development", - "anchor": "application-development" - }, - { - "depth": 2, - "title": "Understand Metadata", - "anchor": "understand-metadata" - }, - { - "depth": 2, - "title": "Expose Runtime Information as Metadata", - "anchor": "expose-runtime-information-as-metadata" - }, - { - "depth": 2, - "title": "Generate Metadata", - "anchor": "generate-metadata" - }, - { - "depth": 2, - "title": "Retrieve Runtime Metadata", - "anchor": "retrieve-runtime-metadata" - }, - { - "depth": 3, - "title": "Use Polkadot.js", - "anchor": "use-polkadotjs" - }, - { - "depth": 3, - "title": "Use Curl", - "anchor": "use-curl" - }, - { - "depth": 3, - "title": "Use Subxt", - "anchor": "use-subxt" - }, - { - "depth": 2, - "title": "Client Applications and Metadata", - "anchor": "client-applications-and-metadata" - }, - { - "depth": 2, - "title": "Metadata Format", - "anchor": "metadata-format" - }, - { - "depth": 3, - "title": "Pallets", - "anchor": "pallets" - }, - { - "depth": 3, - "title": "Extrinsic", - "anchor": "extrinsic" + "title": "Get Tokens from the Faucet", + "anchor": "get-tokens-from-the-faucet" }, { "depth": 2, - "title": "Included RPC APIs", - "anchor": "included-rpc-apis" + "title": "EVM/PVM Smart Contracts", + "anchor": "evmpvm-smart-contracts" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Port Ethereum DApps", + "anchor": "port-ethereum-dapps" } ], "stats": { - "chars": 18650, - "words": 2216, - "headings": 15, - "estimated_token_count_total": 3774 + "chars": 2815, + "words": 206, + "headings": 3, + "estimated_token_count_total": 1014 }, - "hash": "sha256:49238d1e9e2c33e0fcd3a84b5e30f0d3840d7d23a783b538875e0a23f38efc1d", + "hash": "sha256:cea0745bf1f1ac5680690a78494977b5e111c33638f5ceaa2c19ce0804cc74ad", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-consensus-async-backing", - "title": "reference-parachains-consensus-async-backing", - "slug": "reference-parachains-consensus-async-backing", + "id": "smart-contracts-dev-environments-hardhat-compile-and-test", + "title": "smart-contracts-dev-environments-hardhat-compile-and-test", + "slug": "smart-contracts-dev-environments-hardhat-compile-and-test", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-async-backing.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/async-backing/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-compile-and-test.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/compile-and-test/", "preview": "TODO", "outline": [], "stats": { @@ -8024,75 +7365,81 @@ "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-consensus-elastic-scaling", - "title": "Elastic Scaling", - "slug": "reference-parachains-consensus-elastic-scaling", + "id": "smart-contracts-dev-environments-hardhat-deploy-a-contract", + "title": "smart-contracts-dev-environments-hardhat-deploy-a-contract", + "slug": "smart-contracts-dev-environments-hardhat-deploy-a-contract", "categories": [ - "Polkadot Protocol" + "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-elastic-scaling.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/elastic-scaling/", - "preview": "Polkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-deploy-a-contract.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/deploy-a-contract/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-hardhat-get-started", + "title": "Use Hardhat with Polkadot Hub", + "slug": "smart-contracts-dev-environments-hardhat-get-started", + "categories": [ + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/get-started/", + "preview": "Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Overview", + "anchor": "overview" }, { "depth": 2, - "title": "How Elastic Scaling Works", - "anchor": "how-elastic-scaling-works" + "title": "Hardhat Workflow", + "anchor": "hardhat-workflow" }, { "depth": 2, - "title": "Benefits of Elastic Scaling", - "anchor": "benefits-of-elastic-scaling" + "title": "Project Anatomy", + "anchor": "project-anatomy" }, { "depth": 2, - "title": "Use Cases", - "anchor": "use-cases" - }, - { - "depth": 3, - "title": "Handling Sudden Traffic Spikes", - "anchor": "handling-sudden-traffic-spikes" - }, - { - "depth": 3, - "title": "Supporting Early-Stage Growth", - "anchor": "supporting-early-stage-growth" - }, - { - "depth": 3, - "title": "Scaling Massive IoT Networks", - "anchor": "scaling-massive-iot-networks" + "title": "Core Functionalities", + "anchor": "core-functionalities" }, { - "depth": 3, - "title": "Powering Real-Time, Low-Latency Systems", - "anchor": "powering-real-time-low-latency-systems" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 7871, - "words": 1047, - "headings": 8, - "estimated_token_count_total": 1440 + "chars": 4795, + "words": 589, + "headings": 5, + "estimated_token_count_total": 1057 }, - "hash": "sha256:2d228c52844df8952520fafdd3e6f0e26bfd2f32b5ee60c6241cf7d38603643c", + "hash": "sha256:39bef792d34440bab5986dd030660af167537019c959526603900811a7b6d408", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-consensus", - "title": "reference-parachains-consensus", - "slug": "reference-parachains-consensus", + "id": "smart-contracts-dev-environments-hardhat-install-and-config", + "title": "smart-contracts-dev-environments-hardhat-install-and-config", + "slug": "smart-contracts-dev-environments-hardhat-install-and-config", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-install-and-config.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/install-and-config/", "preview": "TODO", "outline": [], "stats": { @@ -8105,5345 +7452,55 @@ "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-cryptography", - "title": "Cryptography", - "slug": "reference-parachains-cryptography", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md", - "html_url": "https://docs.polkadot.com/reference/parachains/cryptography/", - "preview": "Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Hash Functions", - "anchor": "hash-functions" - }, - { - "depth": 3, - "title": "Key Properties of Hash Functions", - "anchor": "key-properties-of-hash-functions" - }, - { - "depth": 3, - "title": "Blake2", - "anchor": "blake2" - }, - { - "depth": 2, - "title": "Types of Cryptography", - "anchor": "types-of-cryptography" - }, - { - "depth": 3, - "title": "Symmetric Cryptography", - "anchor": "symmetric-cryptography" - }, - { - "depth": 3, - "title": "Asymmetric Cryptography", - "anchor": "asymmetric-cryptography" - }, - { - "depth": 3, - "title": "Trade-offs and Compromises", - "anchor": "trade-offs-and-compromises" - }, - { - "depth": 2, - "title": "Digital Signatures", - "anchor": "digital-signatures" - }, - { - "depth": 3, - "title": "Example of Creating a Digital Signature", - "anchor": "example-of-creating-a-digital-signature" - }, - { - "depth": 2, - "title": "Elliptic Curve", - "anchor": "elliptic-curve" - }, - { - "depth": 3, - "title": "Various Implementations", - "anchor": "various-implementations" - } - ], - "stats": { - "chars": 8860, - "words": 1293, - "headings": 12, - "estimated_token_count_total": 1797 - }, - "hash": "sha256:259dcef86aadc513675258b665cc3940db65af6eb32a5db85da6ac339966fa60", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-data-encoding", - "title": "Data Encoding", - "slug": "reference-parachains-data-encoding", + "id": "smart-contracts-dev-environments-hardhat-troubleshooting", + "title": "smart-contracts-dev-environments-hardhat-troubleshooting", + "slug": "smart-contracts-dev-environments-hardhat-troubleshooting", "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md", - "html_url": "https://docs.polkadot.com/reference/parachains/data-encoding/", - "preview": "The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "SCALE Codec", - "anchor": "scale-codec" - }, - { - "depth": 3, - "title": "Encode", - "anchor": "encode" - }, - { - "depth": 3, - "title": "Decode", - "anchor": "decode" - }, - { - "depth": 3, - "title": "CompactAs", - "anchor": "compactas" - }, - { - "depth": 3, - "title": "HasCompact", - "anchor": "hascompact" - }, - { - "depth": 3, - "title": "EncodeLike", - "anchor": "encodelike" - }, - { - "depth": 3, - "title": "Data Types", - "anchor": "data-types" - }, - { - "depth": 2, - "title": "Encode and Decode Rust Trait Implementations", - "anchor": "encode-and-decode-rust-trait-implementations" - }, - { - "depth": 2, - "title": "SCALE Codec Libraries", - "anchor": "scale-codec-libraries" - } + "Uncategorized" ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-troubleshooting.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/troubleshooting/", + "preview": "TODO", + "outline": [], "stats": { - "chars": 13629, - "words": 1314, - "headings": 10, - "estimated_token_count_total": 3213 + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 }, - "hash": "sha256:e448294b6e52291ac0add5fa6533572814e6cd27af42bdaccc2000b86f52d775", + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-interoperability", - "title": "Interoperability", - "slug": "reference-parachains-interoperability", + "id": "smart-contracts-dev-environments-hardhat-verify-a-contract", + "title": "smart-contracts-dev-environments-hardhat-verify-a-contract", + "slug": "smart-contracts-dev-environments-hardhat-verify-a-contract", "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md", - "html_url": "https://docs.polkadot.com/reference/parachains/interoperability/", - "preview": "Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Why Interoperability Matters", - "anchor": "why-interoperability-matters" - }, - { - "depth": 2, - "title": "Key Mechanisms for Interoperability", - "anchor": "key-mechanisms-for-interoperability" - }, - { - "depth": 3, - "title": "Cross-Consensus Messaging (XCM): The Backbone of Communication", - "anchor": "cross-consensus-messaging-xcm-the-backbone-of-communication" - }, - { - "depth": 3, - "title": "Bridges: Connecting External Networks", - "anchor": "bridges-connecting-external-networks" - }, - { - "depth": 2, - "title": "The Polkadot Advantage", - "anchor": "the-polkadot-advantage" - }, - { - "depth": 2, - "title": "Looking Ahead", - "anchor": "looking-ahead" - } + "Uncategorized" ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-verify-a-contract.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/verify-a-contract/", + "preview": "TODO", + "outline": [], "stats": { - "chars": 4635, - "words": 584, - "headings": 7, - "estimated_token_count_total": 772 + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 }, - "hash": "sha256:11bb4f113bdda5852a3115e64d5ba47f8eccd4e3619a05ad960ab3a541f31346", + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-networks", - "title": "Networks", - "slug": "reference-parachains-networks", - "categories": [ - "Basics", - "Polkadot Protocol", - "Networks" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md", - "html_url": "https://docs.polkadot.com/reference/parachains/networks/", - "preview": "The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's va", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Network Overview", - "anchor": "network-overview" - }, - { - "depth": 2, - "title": "Polkadot Development Networks", - "anchor": "polkadot-development-networks" - }, - { - "depth": 2, - "title": "Kusama Network", - "anchor": "kusama-network" - }, - { - "depth": 2, - "title": "Test Networks", - "anchor": "test-networks" - }, - { - "depth": 3, - "title": "Westend", - "anchor": "westend" - }, - { - "depth": 3, - "title": "Paseo", - "anchor": "paseo" - }, - { - "depth": 2, - "title": "Local Test Networks", - "anchor": "local-test-networks" - }, - { - "depth": 3, - "title": "Zombienet", - "anchor": "zombienet" - }, - { - "depth": 3, - "title": "Chopsticks", - "anchor": "chopsticks" - } - ], - "stats": { - "chars": 7834, - "words": 1111, - "headings": 10, - "estimated_token_count_total": 1473 - }, - "hash": "sha256:e49e063a2cc0fb5a48c6cdc3de266bb6e025a006940fea8e90cc4d5f9884900f", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-node-and-runtime", - "title": "Node and Runtime", - "slug": "reference-parachains-node-and-runtime", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md", - "html_url": "https://docs.polkadot.com/reference/parachains/node-and-runtime/", - "preview": "Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Architectural Principles", - "anchor": "architectural-principles" - }, - { - "depth": 3, - "title": "Advantages of this Architecture", - "anchor": "advantages-of-this-architecture" - }, - { - "depth": 2, - "title": "Node (Client)", - "anchor": "node-client" - }, - { - "depth": 2, - "title": "Runtime", - "anchor": "runtime" - }, - { - "depth": 3, - "title": "Characteristics", - "anchor": "characteristics" - }, - { - "depth": 3, - "title": "Key Functions", - "anchor": "key-functions" - }, - { - "depth": 2, - "title": "Communication Between Node and Runtime", - "anchor": "communication-between-node-and-runtime" - }, - { - "depth": 3, - "title": "Runtime APIs", - "anchor": "runtime-apis" - }, - { - "depth": 3, - "title": "Host Functions", - "anchor": "host-functions" - } - ], - "stats": { - "chars": 4937, - "words": 628, - "headings": 10, - "estimated_token_count_total": 914 - }, - "hash": "sha256:8122e21c149d0863cfe3b37fc5606bcdb91668e9d265f0f05451a61ff70e4e93", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-randomness", - "title": "Randomness", - "slug": "reference-parachains-randomness", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md", - "html_url": "https://docs.polkadot.com/reference/parachains/randomness/", - "preview": "Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as \"random\" numbers on a computer are actually pseudo-random. These numbers rely on an initial \"seed,\" which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\\_blank}, [heart rates](https://m", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "VRF", - "anchor": "vrf" - }, - { - "depth": 3, - "title": "How VRF Works", - "anchor": "how-vrf-works" - }, - { - "depth": 2, - "title": "RANDAO", - "anchor": "randao" - }, - { - "depth": 2, - "title": "VDFs", - "anchor": "vdfs" - }, - { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 6503, - "words": 1005, - "headings": 6, - "estimated_token_count_total": 1388 - }, - "hash": "sha256:c7d8a5a4263fd21af458ab0bd102377104affdf2431b4fe74eeff4ebe62a4a81", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains", - "title": "Parachains Overview", - "slug": "reference-parachains", - "categories": [ - "Basics", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md", - "html_url": "https://docs.polkadot.com/reference/parachains/", - "preview": "A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Polkadot SDK: Parachain Architecture", - "anchor": "polkadot-sdk-parachain-architecture" - }, - { - "depth": 3, - "title": "Substrate: The Foundation", - "anchor": "substrate-the-foundation" - }, - { - "depth": 3, - "title": "FRAME: Building Blocks for Your Runtime", - "anchor": "frame-building-blocks-for-your-runtime" - }, - { - "depth": 3, - "title": "Cumulus: Parachain-Specific Functionality", - "anchor": "cumulus-parachain-specific-functionality" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 8495, - "words": 1029, - "headings": 6, - "estimated_token_count_total": 1759 - }, - "hash": "sha256:ecb0d9459e08920db7d2d59dc7c01aba7a91ce8c9e39256bd0c3efa473dbaa17", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-assets-and-smart-contracts", - "title": "Asset Hub", - "slug": "reference-polkadot-hub-assets-and-smart-contracts", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/assets-and-smart-contracts/", - "preview": "The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integra", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Assets Basics", - "anchor": "assets-basics" - }, - { - "depth": 2, - "title": "Assets Pallet", - "anchor": "assets-pallet" - }, - { - "depth": 3, - "title": "Key Features", - "anchor": "key-features" - }, - { - "depth": 3, - "title": "Main Functions", - "anchor": "main-functions" - }, - { - "depth": 3, - "title": "Querying Functions", - "anchor": "querying-functions" - }, - { - "depth": 3, - "title": "Permission Models and Roles", - "anchor": "permission-models-and-roles" - }, - { - "depth": 3, - "title": "Asset Freezing", - "anchor": "asset-freezing" - }, - { - "depth": 3, - "title": "Non-Custodial Transfers (Approval API)", - "anchor": "non-custodial-transfers-approval-api" - }, - { - "depth": 2, - "title": "Foreign Assets", - "anchor": "foreign-assets" - }, - { - "depth": 3, - "title": "Handling Foreign Assets", - "anchor": "handling-foreign-assets" - }, - { - "depth": 2, - "title": "Integration", - "anchor": "integration" - }, - { - "depth": 3, - "title": "API Sidecar", - "anchor": "api-sidecar" - }, - { - "depth": 3, - "title": "TxWrapper", - "anchor": "txwrapper" - }, - { - "depth": 3, - "title": "Parachain Node", - "anchor": "parachain-node" - }, - { - "depth": 2, - "title": "XCM Transfer Monitoring", - "anchor": "xcm-transfer-monitoring" - }, - { - "depth": 3, - "title": "Monitor XCM Deposits", - "anchor": "monitor-xcm-deposits" - }, - { - "depth": 3, - "title": "Track XCM Information Back to the Source", - "anchor": "track-xcm-information-back-to-the-source" - }, - { - "depth": 3, - "title": "Practical Monitoring Examples", - "anchor": "practical-monitoring-examples" - }, - { - "depth": 3, - "title": "Monitor for Failed XCM Transfers", - "anchor": "monitor-for-failed-xcm-transfers" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 18211, - "words": 2649, - "headings": 21, - "estimated_token_count_total": 3678 - }, - "hash": "sha256:3d10c04cffc5f737ff75b079d661c2c1904629d23ae1e415e64fd6ae4e98759e", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-bridging", - "title": "Bridge Hub", - "slug": "reference-polkadot-hub-bridging", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-bridging.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/bridging/", - "preview": "The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interope", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Trustless Bridging", - "anchor": "trustless-bridging" - }, - { - "depth": 2, - "title": "Bridging Components", - "anchor": "bridging-components" - }, - { - "depth": 3, - "title": "Ethereum-Specific Support", - "anchor": "ethereum-specific-support" - }, - { - "depth": 2, - "title": "Deployed Bridges", - "anchor": "deployed-bridges" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 5467, - "words": 776, - "headings": 6, - "estimated_token_count_total": 1220 - }, - "hash": "sha256:86734ba8bcdea7913f488edf666a6104bed0a18649d57abde82c149c41c2b871", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-collectives-and-daos", - "title": "Collectives Chain", - "slug": "reference-polkadot-hub-collectives-and-daos", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-collectives-and-daos.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/collectives-and-daos/", - "preview": "Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Key Collectives", - "anchor": "key-collectives" - } - ], - "stats": { - "chars": 2288, - "words": 293, - "headings": 2, - "estimated_token_count_total": 424 - }, - "hash": "sha256:59ec351fbb8d3a392e90f4f5bf6b62f58b21d6d7a900c5e367e5d2e09ecb3aca", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-consensus-and-security-agile-coretime", - "title": "Agile Coretime", - "slug": "reference-polkadot-hub-consensus-and-security-agile-coretime", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/agile-coretime/", - "preview": "Agile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Bulk Coretime", - "anchor": "bulk-coretime" - }, - { - "depth": 3, - "title": "Coretime Interlacing", - "anchor": "coretime-interlacing" - }, - { - "depth": 3, - "title": "Coretime Splitting", - "anchor": "coretime-splitting" - }, - { - "depth": 2, - "title": "On-Demand Coretime", - "anchor": "on-demand-coretime" - } - ], - "stats": { - "chars": 3028, - "words": 452, - "headings": 5, - "estimated_token_count_total": 619 - }, - "hash": "sha256:00be43ac8d666bbe15c5c2fa5a5085697d0bb5a6f341ebbb943a209f0be355df", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-consensus-and-security-pos-consensus", - "title": "Proof of Stake Consensus", - "slug": "reference-polkadot-hub-consensus-and-security-pos-consensus", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/pos-consensus/", - "preview": "Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank} model and a com", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Nominated Proof of Stake", - "anchor": "nominated-proof-of-stake" - }, - { - "depth": 2, - "title": "Hybrid Consensus", - "anchor": "hybrid-consensus" - }, - { - "depth": 2, - "title": "Block Production - BABE", - "anchor": "block-production-babe" - }, - { - "depth": 3, - "title": "Validator Participation", - "anchor": "validator-participation" - }, - { - "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources" - }, - { - "depth": 2, - "title": "Finality Gadget - GRANDPA", - "anchor": "finality-gadget-grandpa" - }, - { - "depth": 3, - "title": "Probabilistic vs. Provable Finality", - "anchor": "probabilistic-vs-provable-finality" - }, - { - "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-2" - }, - { - "depth": 2, - "title": "Fork Choice", - "anchor": "fork-choice" - }, - { - "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-3" - }, - { - "depth": 2, - "title": "Bridging - BEEFY", - "anchor": "bridging-beefy" - }, - { - "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-4" - } - ], - "stats": { - "chars": 12753, - "words": 1834, - "headings": 13, - "estimated_token_count_total": 2526 - }, - "hash": "sha256:231fc555eefe5f910fb36e0c03945147d0fb235272850797391751f4444b0a9c", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-consensus-and-security-relay-chain", - "title": "Overview of the Polkadot Relay Chain", - "slug": "reference-polkadot-hub-consensus-and-security-relay-chain", - "categories": [ - "Basics", - "Polkadot Protocol", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/", - "preview": "Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank}, and cross-chain int", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Polkadot 1.0", - "anchor": "polkadot-10" - }, - { - "depth": 3, - "title": "High-Level Architecture", - "anchor": "high-level-architecture" - }, - { - "depth": 3, - "title": "Polkadot's Additional Functionalities", - "anchor": "polkadots-additional-functionalities" - }, - { - "depth": 3, - "title": "Polkadot's Resilience", - "anchor": "polkadots-resilience" - }, - { - "depth": 3, - "title": "Polkadot's Blockspace", - "anchor": "polkadots-blockspace" - }, - { - "depth": 2, - "title": "DOT Token", - "anchor": "dot-token" - }, - { - "depth": 3, - "title": "Redenomination of DOT", - "anchor": "redenomination-of-dot" - }, - { - "depth": 3, - "title": "The Planck Unit", - "anchor": "the-planck-unit" - }, - { - "depth": 3, - "title": "Uses for DOT", - "anchor": "uses-for-dot" - }, - { - "depth": 2, - "title": "JAM and the Road Ahead", - "anchor": "jam-and-the-road-ahead" - } - ], - "stats": { - "chars": 12458, - "words": 1774, - "headings": 11, - "estimated_token_count_total": 2580 - }, - "hash": "sha256:8a914e4309d4fe7070e62d7abe4665b6c76c8dc5ec3219332eccb16b77b0dd95", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-people-and-identity", - "title": "People Chain", - "slug": "reference-polkadot-hub-people-and-identity", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-people-and-identity.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/people-and-identity/", - "preview": "People chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Identity Management System", - "anchor": "identity-management-system" - }, - { - "depth": 3, - "title": "Sub-Identities", - "anchor": "sub-identities" - }, - { - "depth": 2, - "title": "Verification Process", - "anchor": "verification-process" - }, - { - "depth": 3, - "title": "Judgment Requests", - "anchor": "judgment-requests" - }, - { - "depth": 3, - "title": "Judgment Classifications", - "anchor": "judgment-classifications" - }, - { - "depth": 3, - "title": "Registrars", - "anchor": "registrars" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4750, - "words": 606, - "headings": 8, - "estimated_token_count_total": 876 - }, - "hash": "sha256:8239d1e8d8642cb7c10e9e5f971c99b999e9e4a87373b50bf4a691225c1e4702", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub", - "title": "reference-polkadot-hub", - "slug": "reference-polkadot-hub", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-chopsticks", - "title": "reference-tools-chopsticks", - "slug": "reference-tools-chopsticks", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md", - "html_url": "https://docs.polkadot.com/reference/tools/chopsticks/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-dedot", - "title": "Dedot", - "slug": "reference-tools-dedot", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md", - "html_url": "https://docs.polkadot.com/reference/tools/dedot/", - "preview": "[Dedot](https://github.com/dedotdev/dedot){target=\\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\\_blank}.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 3, - "title": "Key Features", - "anchor": "key-features" - }, - { - "depth": 2, - "title": "Installation", - "anchor": "installation" - }, - { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Initialize a Client Instance", - "anchor": "initialize-a-client-instance" - }, - { - "depth": 3, - "title": "Enable Type and API Suggestions", - "anchor": "enable-type-and-api-suggestions" - }, - { - "depth": 3, - "title": "Read On-Chain Data", - "anchor": "read-on-chain-data" - }, - { - "depth": 3, - "title": "Sign and Send Transactions", - "anchor": "sign-and-send-transactions" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 8855, - "words": 1100, - "headings": 9, - "estimated_token_count_total": 2300 - }, - "hash": "sha256:ba24e31e2ad94fbf1d73f1878da92dd2e1476db00170780bbdf0e65ab18bc961", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-light-clients", - "title": "Light Clients", - "slug": "reference-tools-light-clients", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md", - "html_url": "https://docs.polkadot.com/reference/tools/light-clients/", - "preview": "Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Light Clients Workflow", - "anchor": "light-clients-workflow" - }, - { - "depth": 2, - "title": "JSON-RPC and Light Client Comparison", - "anchor": "json-rpc-and-light-client-comparison" - }, - { - "depth": 2, - "title": "Using Light Clients", - "anchor": "using-light-clients" - }, - { - "depth": 3, - "title": "PAPI Light Client Support", - "anchor": "papi-light-client-support" - }, - { - "depth": 3, - "title": "Substrate Connect - Browser Extension", - "anchor": "substrate-connect-browser-extension" - }, - { - "depth": 2, - "title": "Resources", - "anchor": "resources" - } - ], - "stats": { - "chars": 6490, - "words": 870, - "headings": 7, - "estimated_token_count_total": 1430 - }, - "hash": "sha256:1284c42be692167e01bcc44e2e134ec20615402675fac26df246c00aa1588d80", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-moonwall", - "title": "E2E Testing with Moonwall", - "slug": "reference-tools-moonwall", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md", - "html_url": "https://docs.polkadot.com/reference/tools/moonwall/", - "preview": "Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Install Moonwall", - "anchor": "install-moonwall" - }, - { - "depth": 3, - "title": "Global Installation", - "anchor": "global-installation" - }, - { - "depth": 3, - "title": "Local Installation", - "anchor": "local-installation" - }, - { - "depth": 2, - "title": "Initialize Moonwall", - "anchor": "initialize-moonwall" - }, - { - "depth": 2, - "title": "Writing Tests", - "anchor": "writing-tests" - }, - { - "depth": 2, - "title": "Running the Tests", - "anchor": "running-the-tests" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 10240, - "words": 1295, - "headings": 9, - "estimated_token_count_total": 2453 - }, - "hash": "sha256:2c77cfb38bb2e466a8f56dabbb706fcd2e90cf1634fc9beb7f0ee95a75735653", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-omninode", - "title": "Polkadot Omni Node", - "slug": "reference-tools-omninode", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md", - "html_url": "https://docs.polkadot.com/reference/tools/omninode/", - "preview": "The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\\_blank} file, allowing it to adapt dynamically to different parachains.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Install Polkadot Omni Node", - "anchor": "install-polkadot-omni-node" - }, - { - "depth": 2, - "title": "Obtain Chain Specifications", - "anchor": "obtain-chain-specifications" - }, - { - "depth": 2, - "title": "Run a Parachain Full Node", - "anchor": "run-a-parachain-full-node" - }, - { - "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" - }, - { - "depth": 2, - "title": "Parachain Compatibility", - "anchor": "parachain-compatibility" - }, - { - "depth": 3, - "title": "Required Runtime APIs", - "anchor": "required-runtime-apis" - }, - { - "depth": 3, - "title": "Required Pallets", - "anchor": "required-pallets" - } - ], - "stats": { - "chars": 8913, - "words": 1164, - "headings": 9, - "estimated_token_count_total": 2017 - }, - "hash": "sha256:a87815deff81936d7f50842f8600004990076c1a33e7e6b408ab954b6ce47259", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-papi", - "title": "Polkadot-API", - "slug": "reference-tools-papi", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md", - "html_url": "https://docs.polkadot.com/reference/tools/papi/", - "preview": "[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "API Instantiation", - "anchor": "api-instantiation" - }, - { - "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" - }, - { - "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 8957, - "words": 1156, - "headings": 6, - "estimated_token_count_total": 1987 - }, - "hash": "sha256:2ca93b09d3bb9159bbf53816886a9b242bb3c13b996c51fd52962e049e2d5477", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-paraspell", - "title": "ParaSpell XCM SDK", - "slug": "reference-tools-paraspell", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md", - "html_url": "https://docs.polkadot.com/reference/tools/paraspell/", - "preview": "[ParaSpell](https://paraspell.github.io/docs/){target=\\_blank} is a comprehensive suite of open-source tools designed to simplify cross-chain interactions within the Polkadot ecosystem. At its core, ParaSpell is dedicated to enhancing the functionality of the [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} protocol by providing developers with a unified and streamlined experience for building interoperable decentralized applications (dApps).", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 3, - "title": "ParaSpell XCM SDK", - "anchor": "paraspell-xcm-sdk" - }, - { - "depth": 2, - "title": "Install ParaSpell", - "anchor": "install-paraspell" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4043, - "words": 562, - "headings": 4, - "estimated_token_count_total": 888 - }, - "hash": "sha256:c8741954ea656680aa3322c825e3f6acbaac369baaa42232b06af9e5e482f74f", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-polkadart", - "title": "Polkadart", - "slug": "reference-tools-polkadart", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md", - "html_url": "https://docs.polkadot.com/reference/tools/polkadart/", - "preview": "Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications.", - "outline": [ - { - "depth": 2, - "title": "Installation", - "anchor": "installation" - }, - { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Type Generation", - "anchor": "type-generation" - }, - { - "depth": 3, - "title": "Run Generator", - "anchor": "run-generator" - }, - { - "depth": 3, - "title": "Use Generated Types", - "anchor": "use-generated-types" - }, - { - "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" - }, - { - "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" - }, - { - "depth": 3, - "title": "Subscribe to New Blocks", - "anchor": "subscribe-to-new-blocks" - }, - { - "depth": 3, - "title": "Send a Transaction", - "anchor": "send-a-transaction" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 5178, - "words": 624, - "headings": 10, - "estimated_token_count_total": 1084 - }, - "hash": "sha256:7f533abe61586af8438e350c41b741d74a8edb839f9dc4139bc4619ba3748258", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-polkadot-js-api", - "title": "Polkadot.js API", - "slug": "reference-tools-polkadot-js-api", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md", - "html_url": "https://docs.polkadot.com/reference/tools/polkadot-js-api/", - "preview": "!!! warning \"Maintenance Mode Only\" The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank} (modern, type-safe API) as actively maintained alternatives.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 3, - "title": "Dynamic API Generation", - "anchor": "dynamic-api-generation" - }, - { - "depth": 3, - "title": "Available API Categories", - "anchor": "available-api-categories" - }, - { - "depth": 2, - "title": "Installation", - "anchor": "installation" - }, - { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" - }, - { - "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" - }, - { - "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 5042, - "words": 684, - "headings": 9, - "estimated_token_count_total": 1166 - }, - "hash": "sha256:ed3986f30880fefca5975fcdc847c68b4aca65862c63e3002b25391b0521781d", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-py-substrate-interface", - "title": "Python Substrate Interface", - "slug": "reference-tools-py-substrate-interface", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md", - "html_url": "https://docs.polkadot.com/reference/tools/py-substrate-interface/", - "preview": "The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for:", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Installation", - "anchor": "installation" - }, - { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Establishing Connection", - "anchor": "establishing-connection" - }, - { - "depth": 3, - "title": "Reading Chain State", - "anchor": "reading-chain-state" - }, - { - "depth": 3, - "title": "Submitting Transactions", - "anchor": "submitting-transactions" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4302, - "words": 541, - "headings": 7, - "estimated_token_count_total": 942 - }, - "hash": "sha256:8987fc35cd28602054ee018031f773e2e3837425107c51d0e2ac68a94b86e9c0", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-sidecar", - "title": "Sidecar REST API", - "slug": "reference-tools-sidecar", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md", - "html_url": "https://docs.polkadot.com/reference/tools/sidecar/", - "preview": "The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Installation", - "anchor": "installation" - }, - { - "depth": 2, - "title": "Usage", - "anchor": "usage" - }, - { - "depth": 3, - "title": "Endpoints", - "anchor": "endpoints" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 7309, - "words": 1033, - "headings": 6, - "estimated_token_count_total": 1945 - }, - "hash": "sha256:0795462182cb97256bb5c2acb035855fe0d6557185de8ac99482725ecb4f94c1", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-subxt", - "title": "Subxt Rust API", - "slug": "reference-tools-subxt", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md", - "html_url": "https://docs.polkadot.com/reference/tools/subxt/", - "preview": "Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Installation", - "anchor": "installation" - }, - { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Download Chain Metadata", - "anchor": "download-chain-metadata" - }, - { - "depth": 3, - "title": "Generate Type-Safe Interfaces", - "anchor": "generate-type-safe-interfaces" - }, - { - "depth": 3, - "title": "Initialize the Subxt Client", - "anchor": "initialize-the-subxt-client" - }, - { - "depth": 3, - "title": "Read Chain Data", - "anchor": "read-chain-data" - }, - { - "depth": 3, - "title": "Submit Transactions", - "anchor": "submit-transactions" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 9174, - "words": 1175, - "headings": 10, - "estimated_token_count_total": 2187 - }, - "hash": "sha256:56269d9ea47f5b4e92cd7d5a1e65ab06d181a9c380f90bb3ef285529b12299f7", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-xcm-tools", - "title": "XCM Tools", - "slug": "reference-tools-xcm-tools", - "categories": [ - "Basics", - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md", - "html_url": "https://docs.polkadot.com/reference/tools/xcm-tools/", - "preview": "As described in the [Interoperability](/develop/interoperability){target=\\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Popular XCM Tools", - "anchor": "popular-xcm-tools" - }, - { - "depth": 3, - "title": "Moonsong Labs XCM Tools", - "anchor": "moonsong-labs-xcm-tools" - }, - { - "depth": 3, - "title": "ParaSpell", - "anchor": "paraspell" - }, - { - "depth": 3, - "title": "Astar XCM Tools", - "anchor": "astar-xcm-tools" - }, - { - "depth": 3, - "title": "Chopsticks", - "anchor": "chopsticks" - }, - { - "depth": 3, - "title": "Moonbeam XCM SDK", - "anchor": "moonbeam-xcm-sdk" - } - ], - "stats": { - "chars": 6146, - "words": 852, - "headings": 7, - "estimated_token_count_total": 1377 - }, - "hash": "sha256:674e4f60c82fc7544c7af8e09f1e0f677c9907cdff88b107f6c8489e97a43487", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-zombienet", - "title": "reference-tools-zombienet", - "slug": "reference-tools-zombienet", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md", - "html_url": "https://docs.polkadot.com/reference/tools/zombienet/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference", - "title": "reference", - "slug": "reference", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md", - "html_url": "https://docs.polkadot.com/reference/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-connect", - "title": "Connect to Polkadot", - "slug": "smart-contracts-connect", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-connect.md", - "html_url": "https://docs.polkadot.com/smart-contracts/connect/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ", - "outline": [ - { - "depth": 2, - "title": "Networks Details", - "anchor": "networks-details" - }, - { - "depth": 2, - "title": "Test Tokens", - "anchor": "test-tokens" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 3459, - "words": 476, - "headings": 3, - "estimated_token_count_total": 558 - }, - "hash": "sha256:a2490223926957381913ae0ed22e2df3611a6713ec9d77a3015d1cd6a578b3f6", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-dapps-zero-to-hero", - "title": "Zero to Hero Smart Contract DApp", - "slug": "smart-contracts-cookbook-dapps-zero-to-hero", - "categories": [ - "dApp", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/dapps/zero-to-hero/", - "preview": "Decentralized applications (dApps) are a key component of the Web3 ecosystem, enabling developers to build applications that communicate directly with blockchain networks. Polkadot Hub, a blockchain with smart contract support, serves as a robust platform for deploying and interacting with dApps.", - "outline": [ - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Project Overview", - "anchor": "project-overview" - }, - { - "depth": 2, - "title": "Create and Deploy the Storage Contract", - "anchor": "create-and-deploy-the-storage-contract" - }, - { - "depth": 3, - "title": "Set Up Hardhat Project", - "anchor": "set-up-hardhat-project" - }, - { - "depth": 3, - "title": "Create the Storage Contract", - "anchor": "create-the-storage-contract" - }, - { - "depth": 3, - "title": "Configure Hardhat for Polkadot Hub", - "anchor": "configure-hardhat-for-polkadot-hub" - }, - { - "depth": 3, - "title": "Compile the Contract", - "anchor": "compile-the-contract" - }, - { - "depth": 3, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" - }, - { - "depth": 3, - "title": "Export the Contract ABI", - "anchor": "export-the-contract-abi" - }, - { - "depth": 2, - "title": "Set Up the dApp Project", - "anchor": "set-up-the-dapp-project" - }, - { - "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" - }, - { - "depth": 2, - "title": "Connect to Polkadot Hub", - "anchor": "connect-to-polkadot-hub" - }, - { - "depth": 2, - "title": "Set Up the Smart Contract Interface", - "anchor": "set-up-the-smart-contract-interface" - }, - { - "depth": 2, - "title": "Create the Wallet Connection Component", - "anchor": "create-the-wallet-connection-component" - }, - { - "depth": 2, - "title": "Create the Read Contract Component", - "anchor": "create-the-read-contract-component" - }, - { - "depth": 2, - "title": "Create the Write Contract Component", - "anchor": "create-the-write-contract-component" - }, - { - "depth": 2, - "title": "How It Works", - "anchor": "how-it-works" - }, - { - "depth": 3, - "title": "Wallet Connection", - "anchor": "wallet-connection" - }, - { - "depth": 3, - "title": "Data Reads", - "anchor": "data-reads" - }, - { - "depth": 3, - "title": "Data Writes", - "anchor": "data-writes" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 31207, - "words": 3688, - "headings": 22, - "estimated_token_count_total": 6967 - }, - "hash": "sha256:b200f93a9179f0b2588ba722dd4c118536136faf3c39eabccf4abf5c346f78a8", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-eth-dapps-uniswap-v2", - "title": "Deploying Uniswap V2 on Polkadot", - "slug": "smart-contracts-cookbook-eth-dapps-uniswap-v2", - "categories": [ - "dApps", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" - }, - { - "depth": 2, - "title": "Understanding Uniswap V2 Architecture", - "anchor": "understanding-uniswap-v2-architecture" - }, - { - "depth": 2, - "title": "Test the Contracts", - "anchor": "test-the-contracts" - }, - { - "depth": 2, - "title": "Deploy the Contracts", - "anchor": "deploy-the-contracts" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - } - ], - "stats": { - "chars": 11280, - "words": 1560, - "headings": 7, - "estimated_token_count_total": 2671 - }, - "hash": "sha256:2a42198668c759f63aa602115bf2d290ec7d03bbc3a3df20e30e85027e1b1cc3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", - "title": "Deploy a Basic Contract to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/.deploy-basic-pvm/", - "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "JavaScript with Ethers.js", - "anchor": "javascript-with-ethersjs" - }, - { - "depth": 3, - "title": "Setup", - "anchor": "setup" - }, - { - "depth": 3, - "title": "Create and Compile Your Contract", - "anchor": "create-and-compile-your-contract" - }, - { - "depth": 3, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" - }, - { - "depth": 2, - "title": "Remix IDE", - "anchor": "remix-ide" - }, - { - "depth": 3, - "title": "Access Remix", - "anchor": "access-remix" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Hardhat", - "anchor": "hardhat" - }, - { - "depth": 3, - "title": "Setup", - "anchor": "setup-2" - }, - { - "depth": 3, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile-2" - }, - { - "depth": 3, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy-2" - }, - { - "depth": 2, - "title": "Foundry", - "anchor": "foundry" - }, - { - "depth": 3, - "title": "Setup", - "anchor": "setup-3" - }, - { - "depth": 3, - "title": "Configure Foundry", - "anchor": "configure-foundry" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract-2" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile-3" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy-3" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 13872, - "words": 1640, - "headings": 24, - "estimated_token_count_total": 3228 - }, - "hash": "sha256:8f29b0f0b56f8c136206211a858cdc5bc27bcd9119eab179a6cd306182d910cb", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-ethers-js", - "title": "JavaScript with Ethers.js", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-ethers-js", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-ethers-js.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-ethers-js/", - "preview": "[Ethers.js](https://docs.ethers.org/v6/){target=\\_blank} provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications.", - "outline": [ - { - "depth": 3, - "title": "Setup", - "anchor": "setup" - }, - { - "depth": 3, - "title": "Create and Compile Your Contract", - "anchor": "create-and-compile-your-contract" - }, - { - "depth": 3, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 6935, - "words": 767, - "headings": 4, - "estimated_token_count_total": 1490 - }, - "hash": "sha256:b0af34b460192f665ca70e7d7985e87b9f59a1a359888f6d14d651daedbcd711", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-foundry", - "title": "Foundry", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-foundry", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-foundry.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-foundry/", - "preview": "[Foundry](https://getfoundry.sh/){target=\\_blank} offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", - "outline": [ - { - "depth": 3, - "title": "Setup", - "anchor": "setup" - }, - { - "depth": 3, - "title": "Configure Foundry", - "anchor": "configure-foundry" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 2125, - "words": 276, - "headings": 6, - "estimated_token_count_total": 429 - }, - "hash": "sha256:f7687b9a1e80ab381cf4fb24f37cccfb98ddf139bf687e8832af99364ef0a8a9", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat", - "title": "hardhat", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-hardhat.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-hardhat/", - "preview": "[Hardhat](https://hardhat.org/){target=\\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", - "outline": [ - { - "depth": 3, - "title": "Setup", - "anchor": "setup" - }, - { - "depth": 3, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 3, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 3336, - "words": 375, - "headings": 7, - "estimated_token_count_total": 672 - }, - "hash": "sha256:93ca24da15095dd0bb03657f53d27771934aee055c11af529445a50e161f79a3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-remix", - "title": "Remix IDE", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-remix", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-deploy-basic-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract/deploy-basic-remix/", - "preview": "[Remix IDE](https://remix.live/){target=\\_blank} offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", - "outline": [ - { - "depth": 3, - "title": "Access Remix", - "anchor": "access-remix" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 2473, - "words": 363, - "headings": 4, - "estimated_token_count_total": 527 - }, - "hash": "sha256:56d730c8a6d2ccf0324caf1c3f30929a93904f80e482cfcb457541e04482dbad", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-ethers-js", - "title": "JavaScript with Ethers.js", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-ethers-js", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-ethers-js.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-ethers-js/", - "preview": "[Ethers.js](https://docs.ethers.org/v6/){target=\\_blank} provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications.", - "outline": [ - { - "depth": 3, - "title": "Setup", - "anchor": "setup" - }, - { - "depth": 3, - "title": "Create and Compile Your Contract", - "anchor": "create-and-compile-your-contract" - }, - { - "depth": 3, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 6935, - "words": 767, - "headings": 4, - "estimated_token_count_total": 1490 - }, - "hash": "sha256:b0af34b460192f665ca70e7d7985e87b9f59a1a359888f6d14d651daedbcd711", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-foundry", - "title": "Foundry", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-foundry", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-foundry.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-foundry/", - "preview": "[Foundry](https://getfoundry.sh/){target=\\_blank} offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", - "outline": [ - { - "depth": 3, - "title": "Setup", - "anchor": "setup" - }, - { - "depth": 3, - "title": "Configure Foundry", - "anchor": "configure-foundry" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 2125, - "words": 276, - "headings": 6, - "estimated_token_count_total": 429 - }, - "hash": "sha256:f7687b9a1e80ab381cf4fb24f37cccfb98ddf139bf687e8832af99364ef0a8a9", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat", - "title": "hardhat", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-hardhat.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-hardhat/", - "preview": "[Hardhat](https://hardhat.org/){target=\\_blank} provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", - "outline": [ - { - "depth": 3, - "title": "Setup", - "anchor": "setup" - }, - { - "depth": 3, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 3, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 3336, - "words": 375, - "headings": 7, - "estimated_token_count_total": 672 - }, - "hash": "sha256:93ca24da15095dd0bb03657f53d27771934aee055c11af529445a50e161f79a3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-remix", - "title": "Remix IDE", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-remix", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-contract-evm-deploy-basic-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-contract-evm/deploy-basic-remix/", - "preview": "[Remix IDE](https://remix.live/){target=\\_blank} offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", - "outline": [ - { - "depth": 3, - "title": "Access Remix", - "anchor": "access-remix" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 2473, - "words": 363, - "headings": 4, - "estimated_token_count_total": 527 - }, - "hash": "sha256:56d730c8a6d2ccf0324caf1c3f30929a93904f80e482cfcb457541e04482dbad", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-ethers", - "title": "Deploy a Basic Contract with Ethers.js", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-ethers", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-ethers.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/ethers/", - "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, which provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 7370, - "words": 823, - "headings": 7, - "estimated_token_count_total": 1729 - }, - "hash": "sha256:ff8975b44870613c3aef0907df365f1ac981de74ec83019df232fe4bda6d9dbe", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-evm", - "title": "Deploy a Basic Contract to EVM", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-evm", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-evm.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-evm/", - "preview": "Deploying smart contracts to the [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished using standard EVM development tools and workflows. This guide demonstrates how to deploy a basic smart contract using four popular EVM approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}, and [Foundry](https://getfoundry.sh/){ta", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Deployment options", - "anchor": "deployment-options" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 15629, - "words": 1659, - "headings": 4, - "estimated_token_count_total": 3341 - }, - "hash": "sha256:a4fd853afb897985602e0356551edacbce77db60bbc6556de3b6ae5af3fbc9e5", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-foundry", - "title": "Deploy a Basic Contract with Foundry", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-foundry", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-foundry.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/", - "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Foundry](https://getfoundry.sh/){target=\\_blank}, which offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", - "outline": [ - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" - }, - { - "depth": 2, - "title": "Configure Foundry", - "anchor": "configure-foundry" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 2731, - "words": 355, - "headings": 7, - "estimated_token_count_total": 598 - }, - "hash": "sha256:63defd84f302f0778c90129abbe69ecd2a5d9d83c622f2b7e5c2ffc9bcb3312f", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", - "title": "Deploy a Basic Contract with Hardhat", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/", - "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Hardhat](https://hardhat.org/){target=\\_blank}, which provides a comprehensive development environment with built-in testing, debugging, and deployment capabilities. It's ideal for professional development workflows and team projects.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" - }, - { - "depth": 2, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" - }, - { - "depth": 2, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4051, - "words": 475, - "headings": 9, - "estimated_token_count_total": 981 - }, - "hash": "sha256:98f5c5c1a26db913e1c4c435062d214ca8c4b5f2dbed5b64d2e54c3435f06452", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-pvm", - "title": "Deploy a Basic Contract to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-pvm", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-pvm.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic-pvm/", - "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "JavaScript with Ethers.js", - "anchor": "javascript-with-ethersjs" - }, - { - "depth": 3, - "title": "Setup", - "anchor": "setup" - }, - { - "depth": 3, - "title": "Create and Compile Your Contract", - "anchor": "create-and-compile-your-contract" - }, - { - "depth": 3, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" - }, - { - "depth": 2, - "title": "Remix IDE", - "anchor": "remix-ide" - }, - { - "depth": 3, - "title": "Access Remix", - "anchor": "access-remix" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Hardhat", - "anchor": "hardhat" - }, - { - "depth": 3, - "title": "Setup", - "anchor": "setup-2" - }, - { - "depth": 3, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile-2" - }, - { - "depth": 3, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy-2" - }, - { - "depth": 2, - "title": "Foundry", - "anchor": "foundry" - }, - { - "depth": 3, - "title": "Setup", - "anchor": "setup-3" - }, - { - "depth": 3, - "title": "Configure Foundry", - "anchor": "configure-foundry" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract-2" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile-3" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy-3" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 13872, - "words": 1640, - "headings": 24, - "estimated_token_count_total": 3228 - }, - "hash": "sha256:8f29b0f0b56f8c136206211a858cdc5bc27bcd9119eab179a6cd306182d910cb", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", - "title": "Deploy a Basic Contract with Remix IDE", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/", - "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Remix IDE](https://remix.ethereum.org/){target=\\_blank}, which offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Access Remix", - "anchor": "access-remix" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 2978, - "words": 430, - "headings": 6, - "estimated_token_count_total": 738 - }, - "hash": "sha256:0c00544ba0be9c0a6fa0c54bdb38045d64e95af714785b86e57f885a03b4b17a", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", - "title": "Deploy a Basic Contract to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", - "title": "Deploy an ERC-20 to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/", - "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Interact with Your Contract", - "anchor": "interact-with-your-contract" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 9109, - "words": 1260, - "headings": 7, - "estimated_token_count_total": 2182 - }, - "hash": "sha256:0cb418d465a51230ece5d3a56d64754f979bc6c4ad78f2cc3df537b99739e627", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20", - "title": "Deploy an ERC-20 to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20", - "categories": [ - "Basics", - "dApps", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/.deploy-basic-pvm/", - "preview": "Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\\_blank}, [Remix IDE](https://remix.live/){target=\\_blank}, [Hardhat](https://hardhat.org/){target=\\_blank}", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "JavaScript with Ethers.js", - "anchor": "javascript-with-ethersjs" - }, - { - "depth": 3, - "title": "Setup", - "anchor": "setup" - }, - { - "depth": 3, - "title": "Create and Compile Your Contract", - "anchor": "create-and-compile-your-contract" - }, - { - "depth": 3, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" - }, - { - "depth": 2, - "title": "Remix IDE", - "anchor": "remix-ide" - }, - { - "depth": 3, - "title": "Access Remix", - "anchor": "access-remix" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Hardhat", - "anchor": "hardhat" - }, - { - "depth": 3, - "title": "Setup", - "anchor": "setup-2" - }, - { - "depth": 3, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile-2" - }, - { - "depth": 3, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy-2" - }, - { - "depth": 2, - "title": "Foundry", - "anchor": "foundry" - }, - { - "depth": 3, - "title": "Setup", - "anchor": "setup-3" - }, - { - "depth": 3, - "title": "Configure Foundry", - "anchor": "configure-foundry" - }, - { - "depth": 3, - "title": "Create Your Contract", - "anchor": "create-your-contract-2" - }, - { - "depth": 3, - "title": "Compile", - "anchor": "compile-3" - }, - { - "depth": 3, - "title": "Deploy", - "anchor": "deploy-3" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - }, - { - "depth": 3, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 13872, - "words": 1640, - "headings": 24, - "estimated_token_count_total": 3228 - }, - "hash": "sha256:296cba75b1d49aefa1b8636ba95ca20c3431b7eb0e93b0658add671ef5801732", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry", - "title": "Deploy a Basic Contract with Foundry", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-.foundry.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/.foundry/", - "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Foundry](https://getfoundry.sh/){target=\\_blank}, which offers a fast, modular toolkit written in Rust. It's perfect for developers who prefer command-line interfaces and need high-performance compilation and deployment.", - "outline": [ - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" - }, - { - "depth": 2, - "title": "Configure Foundry", - "anchor": "configure-foundry" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 2731, - "words": 355, - "headings": 7, - "estimated_token_count_total": 598 - }, - "hash": "sha256:fdd65f6fe6d109043f11a26f1477e2bbbce1a440dbcb2b191eacfa79a28766e9", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-foundry", - "title": "Deploy an NFT to Polkadot Hub with Foundry", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-foundry", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-foundry.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/foundry/", - "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" - }, - { - "depth": 2, - "title": "Configure Foundry", - "anchor": "configure-foundry" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 3489, - "words": 438, - "headings": 8, - "estimated_token_count_total": 847 - }, - "hash": "sha256:c4b410125946db479b9c262a5132a31bb7730a778501c3a95910ad9d38007cf4", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", - "title": "Deploy an NFT to Polkadot Hub with Hardhat", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/", - "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" - }, - { - "depth": 2, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4745, - "words": 550, - "headings": 9, - "estimated_token_count_total": 1137 - }, - "hash": "sha256:f787f9c66787c53aa5c6fccf30d622b2b617794d1292641ea256e0896d418b28", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", - "title": "Deploy an NFT to Polkadot Hub with Remix", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/", - "preview": "Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Access Remix", - "anchor": "access-remix" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 3754, - "words": 505, - "headings": 7, - "estimated_token_count_total": 928 - }, - "hash": "sha256:12a8debfbc05c5ac0e2c94daa40167adab837dc4e1b2731f5b48ae8bc9bc2c93", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook", - "title": "Smart Contracts Cookbook Index", - "slug": "smart-contracts-cookbook", - "categories": [ - "Basics", - "dApps", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/", - "preview": "Welcome to the Polkadot smart contracts cookbook index.", - "outline": [ - { - "depth": 2, - "title": "Get Tokens from the Faucet", - "anchor": "get-tokens-from-the-faucet" - }, - { - "depth": 2, - "title": "EVM/PVM Smart Contracts", - "anchor": "evmpvm-smart-contracts" - }, - { - "depth": 2, - "title": "Port Ethereum DApps", - "anchor": "port-ethereum-dapps" - } - ], - "stats": { - "chars": 1586, - "words": 204, - "headings": 3, - "estimated_token_count_total": 406 - }, - "hash": "sha256:ea0d085c376117436a9cf68e786da942cf88993651d4e06550f9ee03d2e810f4", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", - "title": "Deploy a Basic Contract with Hardhat", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-hardhat", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-compile-and-test.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/foundry/compile-and-test/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-foundry-deploy-a-contract", - "title": "smart-contracts-dev-environments-foundry-deploy-a-contract", - "slug": "smart-contracts-dev-environments-foundry-deploy-a-contract", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-deploy-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/foundry/deploy-a-contract/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-foundry-get-started", - "title": "Use Foundry with Polkadot Hub", - "slug": "smart-contracts-dev-environments-foundry-get-started", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-get-started.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/foundry/get-started/", - "preview": "!!! warning Consider that features like Anvil (Foundry's local blockchain) and `forge test` (for running Solidity tests) are not yet supported in `foundry-polkadot`.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" - }, - { - "depth": 2, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Set Up Deployment", - "anchor": "set-up-deployment" - }, - { - "depth": 2, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 4051, - "words": 475, - "headings": 9, - "estimated_token_count_total": 981 - }, - "hash": "sha256:72e41f816f07026d96c803f399c71852aa1151c464e79cec3e1746b282d5eaae", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", - "title": "Deploy a Basic Contract with Remix IDE", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-basic-remix", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/", - "preview": "This guide demonstrates how to deploy a basic Solidity smart contract to Polkadot Hub using [Remix IDE](https://remix.ethereum.org/){target=\\_blank}, which offers a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Access Remix", - "anchor": "access-remix" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 2978, - "words": 430, - "headings": 6, - "estimated_token_count_total": 738 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat", - "title": "Deploy an ERC-20 to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/", - "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" - }, - { - "depth": 2, - "title": "Configure Hardhat", - "anchor": "configure-hardhat" - }, - { - "depth": 2, - "title": "Compile your Contract", - "anchor": "compile-your-contract" - }, - { - "depth": 2, - "title": "Test your Contract", - "anchor": "test-your-contract" - }, - { - "depth": 2, - "title": "Deploy your Contract", - "anchor": "deploy-your-contract" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 8131, - "words": 1205, - "headings": 8, - "estimated_token_count_total": 2156 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", - "title": "Deploy an ERC-20 to Polkadot Hub", - "slug": "smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md", - "html_url": "https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/", - "preview": "[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Create Your Contract", - "anchor": "create-your-contract" - }, - { - "depth": 2, - "title": "Compile", - "anchor": "compile" - }, - { - "depth": 2, - "title": "Deploy", - "anchor": "deploy" - }, - { - "depth": 2, - "title": "Interact with Your Contract", - "anchor": "interact-with-your-contract" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 9121, - "words": 1261, - "headings": 7, - "estimated_token_count_total": 2183 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-hardhat-compile-and-test", - "title": "smart-contracts-dev-environments-hardhat-compile-and-test", - "slug": "smart-contracts-dev-environments-hardhat-compile-and-test", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-compile-and-test.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/compile-and-test/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-hardhat-deploy-a-contract", - "title": "smart-contracts-dev-environments-hardhat-deploy-a-contract", - "slug": "smart-contracts-dev-environments-hardhat-deploy-a-contract", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-deploy-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/deploy-a-contract/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-hardhat-get-started", - "title": "Use Hardhat with Polkadot Hub", - "slug": "smart-contracts-dev-environments-hardhat-get-started", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/get-started/", - "preview": "Building on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer.", - "outline": [ - { - "depth": 2, - "title": "Overview", - "anchor": "overview" - }, - { - "depth": 2, - "title": "Hardhat Workflow", - "anchor": "hardhat-workflow" - }, - { - "depth": 2, - "title": "Project Anatomy", - "anchor": "project-anatomy" - }, - { - "depth": 2, - "title": "Core Functionalities", - "anchor": "core-functionalities" - }, - { - "depth": 3, - "title": "Project Setup", - "anchor": "project-setup" - }, - { - "depth": 3, - "title": "Contract Compilation", - "anchor": "contract-compilation" - }, - { - "depth": 3, - "title": "Testing Environment", - "anchor": "testing-environment" - }, - { - "depth": 3, - "title": "Deployment", - "anchor": "deployment" - }, - { - "depth": 3, - "title": "Contract Interaction", - "anchor": "contract-interaction" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 5817, - "words": 730, - "headings": 10, - "estimated_token_count_total": 1282 - }, - "hash": "sha256:95352e48926dd24d6363218dfd703840871be8822bc522f45bf343436612eff4", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-hardhat-install-and-config", - "title": "smart-contracts-dev-environments-hardhat-install-and-config", - "slug": "smart-contracts-dev-environments-hardhat-install-and-config", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-install-and-config.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/install-and-config/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-hardhat-troubleshooting", - "title": "smart-contracts-dev-environments-hardhat-troubleshooting", - "slug": "smart-contracts-dev-environments-hardhat-troubleshooting", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-troubleshooting.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/troubleshooting/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-hardhat-verify-a-contract", - "title": "smart-contracts-dev-environments-hardhat-verify-a-contract", - "slug": "smart-contracts-dev-environments-hardhat-verify-a-contract", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-verify-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/hardhat/verify-a-contract/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-local-dev-node", - "title": "Local Development Node", - "slug": "smart-contracts-dev-environments-local-dev-node", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-local-dev-node.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/local-dev-node/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Install the Revive Dev Node and ETH-RPC Adapter", - "anchor": "install-the-revive-dev-node-and-eth-rpc-adapter" - }, - { - "depth": 2, - "title": "Run the Local Node", - "anchor": "run-the-local-node" - } - ], - "stats": { - "chars": 9052, - "words": 1431, - "headings": 4, - "estimated_token_count_total": 2428 - }, - "hash": "sha256:e3d8b84cb2cee7010978582998b2269296a042aec53fb016388690ab6adf355e", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-remix-deploy-a-contract", - "title": "smart-contracts-dev-environments-remix-deploy-a-contract", - "slug": "smart-contracts-dev-environments-remix-deploy-a-contract", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-remix-get-started", - "title": "Use the Polkadot Remix IDE", - "slug": "smart-contracts-dev-environments-remix-get-started", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/get-started/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
- :octicons-code-16:{ .lg .middle } __Deploy NFTs Using Remix IDE__", - "outline": [ - { - "depth": 2, - "title": "Overview", - "anchor": "overview" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Accessing Remix IDE", - "anchor": "accessing-remix-ide" - }, - { - "depth": 2, - "title": "Creating a New Contract", - "anchor": "creating-a-new-contract" - }, - { - "depth": 2, - "title": "Compiling Your Contract", - "anchor": "compiling-your-contract" - }, - { - "depth": 2, - "title": "Deploying Contracts", - "anchor": "deploying-contracts" - }, - { - "depth": 2, - "title": "Interacting with Contracts", - "anchor": "interacting-with-contracts" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 6664, - "words": 905, - "headings": 8, - "estimated_token_count_total": 1347 - }, - "hash": "sha256:7589fa1dbdbf5748892ab6d42fc784d833f33e254bd3f95ee58424effcd38323", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-remix-troubleshooting", - "title": "smart-contracts-dev-environments-remix-troubleshooting", - "slug": "smart-contracts-dev-environments-remix-troubleshooting", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-remix-verify-a-contract", - "title": "smart-contracts-dev-environments-remix-verify-a-contract", - "slug": "smart-contracts-dev-environments-remix-verify-a-contract", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/verify-a-contract/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-explorers", - "title": "Block Explorers", - "slug": "smart-contracts-explorers", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-explorers.md", - "html_url": "https://docs.polkadot.com/smart-contracts/explorers/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Core Functionality", - "anchor": "core-functionality" - }, - { - "depth": 2, - "title": "Available Block Explorers", - "anchor": "available-block-explorers" - }, - { - "depth": 3, - "title": "BlockScout", - "anchor": "blockscout" - } - ], - "stats": { - "chars": 1793, - "words": 223, - "headings": 4, - "estimated_token_count_total": 309 - }, - "hash": "sha256:93e8a3043d65583e3d66f8f5f0ed6f4ef89a908ef85da2b6ca906a1100b7dded", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-faucet", - "title": "Faucet", - "slug": "smart-contracts-faucet", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-faucet.md", - "html_url": "https://docs.polkadot.com/smart-contracts/faucet/", - "preview": "Test tokens allow you to experiment with smart contracts, test transactions, and validate your dApp functionality without using real cryptocurrency.", - "outline": [ - { - "depth": 2, - "title": "Get Test Tokens", - "anchor": "get-test-tokens" - }, - { - "depth": 2, - "title": "Things to Consider", - "anchor": "things-to-consider" - }, - { - "depth": 2, - "title": "Using Your Test Tokens", - "anchor": "using-your-test-tokens" - } - ], - "stats": { - "chars": 1890, - "words": 279, - "headings": 3, - "estimated_token_count_total": 313 - }, - "hash": "sha256:c609bc98cba5efa2d2a808548cf93ad9d0a06455b35a8fd9f534daf52824f506", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-for-eth-devs-accounts", - "title": "Accounts in Asset Hub Smart Contracts", - "slug": "smart-contracts-for-eth-devs-accounts", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-accounts.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/accounts/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Address Types and Mappings", - "anchor": "address-types-and-mappings" - }, - { - "depth": 3, - "title": "Ethereum to Polkadot Mapping", - "anchor": "ethereum-to-polkadot-mapping" - }, - { - "depth": 3, - "title": "Polkadot to Ethereum Mapping", - "anchor": "polkadot-to-ethereum-mapping" - }, - { - "depth": 3, - "title": "Account Mapping for Native Polkadot Accounts", - "anchor": "account-mapping-for-native-polkadot-accounts" - }, - { - "depth": 2, - "title": "Account Registration", - "anchor": "account-registration" - }, - { - "depth": 2, - "title": "Fallback Accounts", - "anchor": "fallback-accounts" - }, - { - "depth": 2, - "title": "Contract Address Generation", - "anchor": "contract-address-generation" - }, - { - "depth": 2, - "title": "Security Considerations", - "anchor": "security-considerations" - } - ], - "stats": { - "chars": 8521, - "words": 1138, - "headings": 9, - "estimated_token_count_total": 1816 - }, - "hash": "sha256:f50cd1177dd4aff8eb031d6f21cb640f8187a7f2dd0edcaef5c73354a378e44d", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-for-eth-devs-blocks-transactions-fees", - "title": "Transactions and Fees on Asset Hub", - "slug": "smart-contracts-for-eth-devs-blocks-transactions-fees", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-blocks-transactions-fees.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/blocks-transactions-fees/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Smart Contract Blocks", - "anchor": "smart-contract-blocks" - }, - { - "depth": 2, - "title": "Smart Contract Transactions", - "anchor": "smart-contract-transactions" - }, - { - "depth": 3, - "title": "EVM Transaction Types", - "anchor": "evm-transaction-types" - }, - { - "depth": 2, - "title": "Fees and Gas", - "anchor": "fees-and-gas" - }, - { - "depth": 3, - "title": "Gas Model Overview", - "anchor": "gas-model-overview" - }, - { - "depth": 3, - "title": "Fee Components", - "anchor": "fee-components" - }, - { - "depth": 3, - "title": "Gas Calculation and Conversion", - "anchor": "gas-calculation-and-conversion" - } - ], - "stats": { - "chars": 6366, - "words": 791, - "headings": 8, - "estimated_token_count_total": 1182 - }, - "hash": "sha256:9542f40acae725e628f4c3155ad1e7e0e18b2eb518484856ad439a1d9f86d1f3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-for-eth-devs-contract-deployment", - "title": "Contract Deployment", - "slug": "smart-contracts-for-eth-devs-contract-deployment", - "categories": [ - "Smart Contracts", - "Basics" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-contract-deployment.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/contract-deployment/", - "preview": "Polkadot's smart contract platform supports two distinct virtual machine backends: Rust Ethereum Virtual Machine (REVM) and PolkaVM. Each backend has its own deployment characteristics and optimization strategies. REVM provides full Ethereum compatibility with familiar single-step deployment, while the RISC-V-based PolkaVM uses a more structured two-step approach optimized for its architecture. Understanding these differences ensures smooth deployment regardless of which backend you choose for y", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "REVM Deployment", - "anchor": "revm-deployment" - }, - { - "depth": 2, - "title": "PolkaVM Deployment", - "anchor": "polkavm-deployment" - }, - { - "depth": 3, - "title": "Standard Contract Deployment", - "anchor": "standard-contract-deployment" - }, - { - "depth": 3, - "title": "Two-Step Deployment Model", - "anchor": "two-step-deployment-model" - }, - { - "depth": 3, - "title": "Factory Pattern Considerations", - "anchor": "factory-pattern-considerations" - }, - { - "depth": 3, - "title": "Migration Strategy for Factory Contracts", - "anchor": "migration-strategy-for-factory-contracts" - }, - { - "depth": 3, - "title": "Architecture-Specific Limitations", - "anchor": "architecture-specific-limitations" - }, - { - "depth": 3, - "title": "On-Chain Constructors", - "anchor": "on-chain-constructors" - }, - { - "depth": 2, - "title": "Gas Estimation vs Actual Consumption", - "anchor": "gas-estimation-vs-actual-consumption" - }, - { - "depth": 2, - "title": "Deployment Comparison", - "anchor": "deployment-comparison" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - } - ], - "stats": { - "chars": 5999, - "words": 766, - "headings": 12, - "estimated_token_count_total": 1133 - }, - "hash": "sha256:0792e3956242eb8e08ab82e2d73964c381074cc8b1ea46f396d136856fa6cc07", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-for-eth-devs-dual-vm-stack", - "title": "Dual Virtual Machine Stack", - "slug": "smart-contracts-for-eth-devs-dual-vm-stack", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Migrate from EVM", - "anchor": "migrate-from-evm" - }, - { - "depth": 2, - "title": "Upgrade to PolkaVM", - "anchor": "upgrade-to-polkavm" - }, - { - "depth": 2, - "title": "Architecture", - "anchor": "architecture" - }, - { - "depth": 3, - "title": "Revive Pallet", - "anchor": "revive-pallet" - }, - { - "depth": 3, - "title": "PolkaVM Design Fundamentals", - "anchor": "polkavm-design-fundamentals" - }, - { - "depth": 2, - "title": "Where To Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 5383, - "words": 702, - "headings": 7, - "estimated_token_count_total": 986 - }, - "hash": "sha256:2d918017faecf489ec786f34de6cd4366a86e9f1cecfbb7722cc03079e6b64ea", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-for-eth-devs-gas-model", - "title": "Gas Model on the Polkadot Hub", - "slug": "smart-contracts-for-eth-devs-gas-model", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-gas-model.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/gas-model/", - "preview": "The Polkadot Hub implements a gas model that bridges Ethereum's familiar gas concept with Polkadot's more sophisticated resource metering system. This page explains how gas works in the Polkadot Hub and what developers need to know when building smart contracts.", - "outline": [ - { - "depth": 2, - "title": "Overview", - "anchor": "overview" - }, - { - "depth": 2, - "title": "Understanding Resources in the Polkadot Hub", - "anchor": "understanding-resources-in-the-polkadot-hub" - }, - { - "depth": 2, - "title": "Gas vs Weight", - "anchor": "gas-vs-weight" - }, - { - "depth": 2, - "title": "How Gas Estimation Works", - "anchor": "how-gas-estimation-works" - }, - { - "depth": 2, - "title": "Dynamic Gas Pricing", - "anchor": "dynamic-gas-pricing" - }, - { - "depth": 2, - "title": "Transaction Execution Flow", - "anchor": "transaction-execution-flow" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - } - ], - "stats": { - "chars": 5234, - "words": 751, - "headings": 7, - "estimated_token_count_total": 1046 - }, - "hash": "sha256:dd29fab6e3c00d720b10effa4e50373a6fe9ab4b7bfd3aea892c7fa9c84318a2", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-for-eth-devs-json-rpc-apis", - "title": "JSON-RPC APIs", - "slug": "smart-contracts-for-eth-devs-json-rpc-apis", - "categories": [ - "Reference" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Available Methods", - "anchor": "available-methods" - }, - { - "depth": 3, - "title": "eth_accounts", - "anchor": "eth_accounts" - }, - { - "depth": 3, - "title": "eth_blockNumber", - "anchor": "eth_blocknumber" - }, - { - "depth": 3, - "title": "eth_call", - "anchor": "eth_call" - }, - { - "depth": 3, - "title": "eth_chainId", - "anchor": "eth_chainid" - }, - { - "depth": 3, - "title": "eth_estimateGas", - "anchor": "eth_estimategas" - }, - { - "depth": 3, - "title": "eth_gasPrice", - "anchor": "eth_gasprice" - }, - { - "depth": 3, - "title": "eth_getBalance", - "anchor": "eth_getbalance" - }, - { - "depth": 3, - "title": "eth_getBlockByHash", - "anchor": "eth_getblockbyhash" - }, - { - "depth": 3, - "title": "eth_getBlockByNumber", - "anchor": "eth_getblockbynumber" - }, - { - "depth": 3, - "title": "eth_getBlockTransactionCountByNumber", - "anchor": "eth_getblocktransactioncountbynumber" - }, - { - "depth": 3, - "title": "eth_getBlockTransactionCountByHash", - "anchor": "eth_getblocktransactioncountbyhash" - }, - { - "depth": 3, - "title": "eth_getCode", - "anchor": "eth_getcode" - }, - { - "depth": 3, - "title": "eth_getLogs", - "anchor": "eth_getlogs" - }, - { - "depth": 3, - "title": "eth_getStorageAt", - "anchor": "eth_getstorageat" - }, - { - "depth": 3, - "title": "eth_getTransactionCount", - "anchor": "eth_gettransactioncount" - }, - { - "depth": 3, - "title": "eth_getTransactionByHash", - "anchor": "eth_gettransactionbyhash" - }, - { - "depth": 3, - "title": "eth_getTransactionByBlockNumberAndIndex", - "anchor": "eth_gettransactionbyblocknumberandindex" - }, - { - "depth": 3, - "title": "eth_getTransactionByBlockHashAndIndex", - "anchor": "eth_gettransactionbyblockhashandindex" - }, - { - "depth": 3, - "title": "eth_getTransactionReceipt", - "anchor": "eth_gettransactionreceipt" - }, - { - "depth": 3, - "title": "eth_maxPriorityFeePerGas", - "anchor": "eth_maxpriorityfeepergas" - }, - { - "depth": 3, - "title": "eth_sendRawTransaction", - "anchor": "eth_sendrawtransaction" - }, - { - "depth": 3, - "title": "eth_sendTransaction", - "anchor": "eth_sendtransaction" - }, - { - "depth": 3, - "title": "eth_syncing", - "anchor": "eth_syncing" - }, - { - "depth": 3, - "title": "net_listening", - "anchor": "net_listening" - }, - { - "depth": 3, - "title": "net_peerCount", - "anchor": "net_peercount" - }, - { - "depth": 3, - "title": "net_version", - "anchor": "net_version" - }, - { - "depth": 3, - "title": "system_health", - "anchor": "system_health" - }, - { - "depth": 3, - "title": "web3_clientVersion", - "anchor": "web3_clientversion" - }, - { - "depth": 3, - "title": "debug_traceBlockByNumber", - "anchor": "debug_traceblockbynumber" - }, - { - "depth": 3, - "title": "debug_traceTransaction", - "anchor": "debug_tracetransaction" - }, - { - "depth": 3, - "title": "debug_traceCall", - "anchor": "debug_tracecall" - }, - { - "depth": 2, - "title": "Response Format", - "anchor": "response-format" - }, - { - "depth": 2, - "title": "Error Handling", - "anchor": "error-handling" - } - ], - "stats": { - "chars": 31444, - "words": 3848, - "headings": 35, - "estimated_token_count_total": 9562 - }, - "hash": "sha256:1fb7a20bc4a799a771954720428029419ec73afa640e589590c43dd041a7e307", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-for-eth-devs-migration", - "title": "Migration FAQs and Considerations", - "slug": "smart-contracts-for-eth-devs-migration", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md", - "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/", - "preview": "This guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Migration Considerations", - "anchor": "migration-considerations" - }, - { - "depth": 2, - "title": "Migration Checklist", - "anchor": "migration-checklist" - }, - { - "depth": 2, - "title": "Migration FAQs", - "anchor": "migration-faqs" - }, - { - "depth": 3, - "title": "Which backend should I choose?", - "anchor": "which-backend-should-i-choose" - }, - { - "depth": 3, - "title": "Do I need to rewrite my Solidity code?", - "anchor": "do-i-need-to-rewrite-my-solidity-code" - }, - { - "depth": 3, - "title": "What about factory contracts?", - "anchor": "what-about-factory-contracts" - }, - { - "depth": 3, - "title": "How do gas costs compare?", - "anchor": "how-do-gas-costs-compare" - }, - { - "depth": 3, - "title": "Which Solidity features are not supported?", - "anchor": "which-solidity-features-are-not-supported" - }, - { - "depth": 3, - "title": "How do I handle the existential deposit?", - "anchor": "how-do-i-handle-the-existential-deposit" - }, - { - "depth": 3, - "title": "Can I use my existing development tools?", - "anchor": "can-i-use-my-existing-development-tools" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - } - ], - "stats": { - "chars": 6247, - "words": 803, - "headings": 12, - "estimated_token_count_total": 1322 - }, - "hash": "sha256:bf9b21750158389c387b92f2165947e5f5cff752f5d163680ee37493710e81d7", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-get-started", - "title": "Get Started with Smart Contracts", - "slug": "smart-contracts-get-started", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md", - "html_url": "https://docs.polkadot.com/smart-contracts/get-started/", - "preview": "This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need.", - "outline": [ - { - "depth": 2, - "title": "Quick Starts", - "anchor": "quick-starts" - }, - { - "depth": 2, - "title": "Build and Test Locally", - "anchor": "build-and-test-locally" - }, - { - "depth": 2, - "title": "Ethereum Developer Resources", - "anchor": "ethereum-developer-resources" - }, - { - "depth": 2, - "title": "Cookbook: Hands‑on Tutorials", - "anchor": "cookbook-handson-tutorials" - }, - { - "depth": 2, - "title": "Libraries", - "anchor": "libraries" - }, - { - "depth": 2, - "title": "Integrations", - "anchor": "integrations" - }, - { - "depth": 2, - "title": "Precompiles", - "anchor": "precompiles" - } - ], - "stats": { - "chars": 10103, - "words": 937, - "headings": 7, - "estimated_token_count_total": 2888 - }, - "hash": "sha256:224a9f69d4613a5f1afdbc1f05379add8321fe159e32c71db003bbe08ff8e976", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-integrations-indexers", - "title": "smart-contracts-integrations-indexers", - "slug": "smart-contracts-integrations-indexers", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-indexers.md", - "html_url": "https://docs.polkadot.com/smart-contracts/integrations/indexers/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-integrations-oracles", - "title": "smart-contracts-integrations-oracles", - "slug": "smart-contracts-integrations-oracles", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-oracles.md", - "html_url": "https://docs.polkadot.com/smart-contracts/integrations/oracles/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-integrations-wallets", - "title": "Wallets for Polkadot Hub", - "slug": "smart-contracts-integrations-wallets", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md", - "html_url": "https://docs.polkadot.com/smart-contracts/integrations/wallets/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Connect Your Wallet", - "anchor": "connect-your-wallet" - }, - { - "depth": 3, - "title": "MetaMask", - "anchor": "metamask" - }, - { - "depth": 3, - "title": "SubWallet", - "anchor": "subwallet" - }, - { - "depth": 3, - "title": "Talisman", - "anchor": "talisman" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - } - ], - "stats": { - "chars": 7340, - "words": 1041, - "headings": 6, - "estimated_token_count_total": 1627 - }, - "hash": "sha256:65809486f62f60c6a6ac8109f9f027361683c23f639991a045ec5c057b665026", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-libraries-ethers-js", - "title": "Deploy Contracts to Polkadot Hub with Ethers.js", - "slug": "smart-contracts-libraries-ethers-js", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-ethers-js.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/ethers-js/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Project Structure", - "anchor": "project-structure" - }, - { - "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" - }, - { - "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" - }, - { - "depth": 2, - "title": "Set Up the Ethers.js Provider", - "anchor": "set-up-the-ethersjs-provider" - }, - { - "depth": 2, - "title": "Compile Contracts", - "anchor": "compile-contracts" - }, - { - "depth": 3, - "title": "Install the Revive Library", - "anchor": "install-the-revive-library" - }, - { - "depth": 3, - "title": "Sample Storage Smart Contract", - "anchor": "sample-storage-smart-contract" - }, - { - "depth": 3, - "title": "Compile the Smart Contract", - "anchor": "compile-the-smart-contract" - }, - { - "depth": 2, - "title": "Deploy the Compiled Contract", - "anchor": "deploy-the-compiled-contract" - }, - { - "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 20457, - "words": 2333, - "headings": 13, - "estimated_token_count_total": 4474 - }, - "hash": "sha256:c74a28d8d62369591c5734535136508db3d1f7380e486fd214f98d433cafd6e7", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-libraries-viem", - "title": "viem for Polkadot Hub Smart Contracts", - "slug": "smart-contracts-libraries-viem", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-viem.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/viem/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Project Structure", - "anchor": "project-structure" - }, - { - "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" - }, - { - "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" - }, - { - "depth": 2, - "title": "Initialize Project", - "anchor": "initialize-project" - }, - { - "depth": 2, - "title": "Set Up the Chain Configuration", - "anchor": "set-up-the-chain-configuration" - }, - { - "depth": 2, - "title": "Set Up the viem Client", - "anchor": "set-up-the-viem-client" - }, - { - "depth": 2, - "title": "Set Up a Wallet", - "anchor": "set-up-a-wallet" - }, - { - "depth": 2, - "title": "Sample Smart Contract", - "anchor": "sample-smart-contract" - }, - { - "depth": 2, - "title": "Compile the Contract", - "anchor": "compile-the-contract" - }, - { - "depth": 2, - "title": "Deploy the Contract", - "anchor": "deploy-the-contract" - }, - { - "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 16600, - "words": 1940, - "headings": 14, - "estimated_token_count_total": 3891 - }, - "hash": "sha256:e27657e4e4a14fe86f424b96631946ec36fb90d277e6010b6cbd64c4769aba8a", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-libraries-wagmi", - "title": "Wagmi for Polkadot Hub Smart Contracts", - "slug": "smart-contracts-libraries-wagmi", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-wagmi.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/wagmi/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" - }, - { - "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" - }, - { - "depth": 2, - "title": "Configure Wagmi for Polkadot Hub", - "anchor": "configure-wagmi-for-polkadot-hub" - }, - { - "depth": 2, - "title": "Set Up the Wagmi Provider", - "anchor": "set-up-the-wagmi-provider" - }, - { - "depth": 2, - "title": "Connect a Wallet", - "anchor": "connect-a-wallet" - }, - { - "depth": 2, - "title": "Fetch Blockchain Data", - "anchor": "fetch-blockchain-data" - }, - { - "depth": 2, - "title": "Interact with Deployed Contract", - "anchor": "interact-with-deployed-contract" - }, - { - "depth": 2, - "title": "Integrate Components", - "anchor": "integrate-components" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 13604, - "words": 1515, - "headings": 10, - "estimated_token_count_total": 3250 - }, - "hash": "sha256:bc771f912627fa09cad64adab1bc81c052f650d6c5a3b4f0c91883a98f6628da", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-libraries-web3-js", - "title": "Web3.js", - "slug": "smart-contracts-libraries-web3-js", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/web3-js/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. !!! warning Web3.js has been [sunset](https://blog.chainsafe.io/web3-js-sunset/){target=\\_blank}. You can find guides on using [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank} and [viem](/smart-contracts/libraries/viem/){target=\\_blank} in the Libraries section.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Project Structure", - "anchor": "project-structure" - }, - { - "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" - }, - { - "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" - }, - { - "depth": 2, - "title": "Set Up the Web3 Provider", - "anchor": "set-up-the-web3-provider" - }, - { - "depth": 2, - "title": "Compile Contracts", - "anchor": "compile-contracts" - }, - { - "depth": 2, - "title": "Contract Deployment", - "anchor": "contract-deployment" - }, - { - "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 13266, - "words": 1579, - "headings": 10, - "estimated_token_count_total": 3035 - }, - "hash": "sha256:f0d36333d0d3afff7f6374a61d0f6d1fb878c9ef4c4e4c24447745661dbe59d0", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-libraries-web3-py", - "title": "Web3.py", - "slug": "smart-contracts-libraries-web3-py", - "categories": [ - "Smart Contracts", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-py.md", - "html_url": "https://docs.polkadot.com/smart-contracts/libraries/web3-py/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" - }, - { - "depth": 2, - "title": "Set Up the Web3 Provider", - "anchor": "set-up-the-web3-provider" - }, - { - "depth": 2, - "title": "Contract Deployment", - "anchor": "contract-deployment" - }, - { - "depth": 2, - "title": "Interact with the Contract", - "anchor": "interact-with-the-contract" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 11627, - "words": 1333, - "headings": 6, - "estimated_token_count_total": 2509 - }, - "hash": "sha256:205892e350168b3d0da7ccc280c67c3217ad1e45e87a53d124fa1dd69661aa5e", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-overview", - "title": "Smart Contracts Overview", - "slug": "smart-contracts-overview", - "categories": [ - "Basics", - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md", - "html_url": "https://docs.polkadot.com/smart-contracts/overview/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Native Smart Contracts", - "anchor": "native-smart-contracts" - }, - { - "depth": 3, - "title": "Introduction", - "anchor": "introduction-2" - }, - { - "depth": 3, - "title": "Smart Contract Development", - "anchor": "smart-contract-development" - }, - { - "depth": 3, - "title": "Technical Architecture", - "anchor": "technical-architecture" - }, - { - "depth": 3, - "title": "Development Tools and Resources", - "anchor": "development-tools-and-resources" - }, - { - "depth": 3, - "title": "Cross-Chain Capabilities", - "anchor": "cross-chain-capabilities" - }, - { - "depth": 3, - "title": "Use Cases", - "anchor": "use-cases" - }, - { - "depth": 2, - "title": "Other Smart Contract Environments", - "anchor": "other-smart-contract-environments" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 6305, - "words": 804, - "headings": 10, - "estimated_token_count_total": 1122 - }, - "hash": "sha256:ee87115c828928c82937de26f5f938cecd4c3bb1225fdb61627e8092e6ea5951", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-precompiles-eth-native", - "title": "Ethereum-Native Precompiles", - "slug": "smart-contracts-precompiles-eth-native", - "categories": [ - "Smart Contracts" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-eth-native.md", - "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/eth-native/", - "preview": "Ethereum-native precompiles are special contract implementations that provide essential cryptographic and utility functions at the runtime level. These precompiles are available at predefined addresses and offer optimized, native implementations of commonly used operations that would be computationally expensive or impractical to implement in pure contract code.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "How to Use Precompiles", - "anchor": "how-to-use-precompiles" - }, - { - "depth": 2, - "title": "Standard Precompiles in Polkadot Hub", - "anchor": "standard-precompiles-in-polkadot-hub" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - } - ], - "stats": { - "chars": 5232, - "words": 532, - "headings": 4, - "estimated_token_count_total": 1192 - }, - "hash": "sha256:f17db5daca8feae70ce428e03a5a4870ef87dfc8571b07376327cd80d057b759", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-precompiles-xcm", - "title": "Interact with the XCM Precompile", - "slug": "smart-contracts-precompiles-xcm", + "id": "smart-contracts-dev-environments-local-dev-node", + "title": "Local Development Node", + "slug": "smart-contracts-dev-environments-local-dev-node", "categories": [ "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-xcm.md", - "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/xcm/", - "preview": "The [XCM (Cross-Consensus Message)](/parachains/interoperability/get-started/){target=\\_blank} precompile enables Polkadot Hub developers to access XCM functionality directly from their smart contracts using a Solidity interface.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-local-dev-node.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/local-dev-node/", + "preview": "A local development node provides an isolated blockchain environment where you can deploy, test, and debug smart contracts without incurring network fees or waiting for block confirmations. This guide demonstrates how to set up a local Polkadot SDK-based node with smart contract capabilities.", "outline": [ { "depth": 2, @@ -13452,105 +7509,65 @@ }, { "depth": 2, - "title": "Precompile Interface", - "anchor": "precompile-interface" - }, - { - "depth": 2, - "title": "Interact with the XCM Precompile", - "anchor": "interact-with-the-xcm-precompile" - }, - { - "depth": 3, - "title": "Weigh a Message", - "anchor": "weigh-a-message" - }, - { - "depth": 3, - "title": "Execute a Message", - "anchor": "execute-a-message" - }, - { - "depth": 3, - "title": "Send a Message", - "anchor": "send-a-message" - }, - { - "depth": 2, - "title": "Cross Contract Calls", - "anchor": "cross-contract-calls" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Install the Revive Dev Node and ETH-RPC Adapter", + "anchor": "install-the-revive-dev-node-and-eth-rpc-adapter" }, { "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" + "title": "Run the Local Node", + "anchor": "run-the-local-node" } ], "stats": { - "chars": 10705, - "words": 1436, - "headings": 9, - "estimated_token_count_total": 2325 + "chars": 8828, + "words": 1407, + "headings": 4, + "estimated_token_count_total": 2425 }, - "hash": "sha256:c084190ea7d676128e7e399e8fe88598ca150f88d684db279a687ee1c3956120", + "hash": "sha256:fd7f2422843d69ed5cf0268ff05044330087f6e9a2a6f93cef7d3d526fb5d8d4", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-precompiles", - "title": "Advanced Functionalities via Precompiles", - "slug": "smart-contracts-precompiles", + "id": "smart-contracts-dev-environments-remix-deploy-a-contract", + "title": "smart-contracts-dev-environments-remix-deploy-a-contract", + "slug": "smart-contracts-dev-environments-remix-deploy-a-contract", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles.md", - "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "What are Precompiles?", - "anchor": "what-are-precompiles" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - } - ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/", + "preview": "TODO", + "outline": [], "stats": { - "chars": 2525, - "words": 328, - "headings": 3, - "estimated_token_count_total": 412 + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 }, - "hash": "sha256:a40e3f34f70db22bfe39e40d68dc5a53a726ce47cb73b602d8605355c61ffd22", + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-dapps-remark-tutorial", - "title": "PAPI Account Watcher Tutorial", - "slug": "tutorials-dapps-remark-tutorial", + "id": "smart-contracts-dev-environments-remix-get-started", + "title": "Use the Polkadot Remix IDE", + "slug": "smart-contracts-dev-environments-remix-get-started", "categories": [ + "Smart Contracts", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-dapps-remark-tutorial.md", - "html_url": "https://docs.polkadot.com/tutorials/dapps/remark-tutorial/", - "preview": "This tutorial demonstrates how to build a simple command-line interface (CLI) application that monitors a user's account on the relay chain for the [`system.remarkWithEvent`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.remark_with_event){target=\\_blank} extrinsic, using the [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank}.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/get-started/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
- :octicons-code-16:{ .lg .middle } __Deploy NFTs Using Remix IDE__", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Overview", + "anchor": "overview" }, { "depth": 2, @@ -13559,126 +7576,173 @@ }, { "depth": 2, - "title": "Clone the Repository", - "anchor": "clone-the-repository" - }, - { - "depth": 2, - "title": "Explore the Template (Light Clients)", - "anchor": "explore-the-template-light-clients" + "title": "Accessing Remix IDE", + "anchor": "accessing-remix-ide" }, { "depth": 2, - "title": "Create the CLI", - "anchor": "create-the-cli" + "title": "Creating a New Contract", + "anchor": "creating-a-new-contract" }, { "depth": 2, - "title": "Watch for Remarks", - "anchor": "watch-for-remarks" + "title": "Compiling Your Contract", + "anchor": "compiling-your-contract" }, { "depth": 2, - "title": "Compile and Run", - "anchor": "compile-and-run" + "title": "Deploying Contracts", + "anchor": "deploying-contracts" }, { "depth": 2, - "title": "Test the CLI", - "anchor": "test-the-cli" + "title": "Interacting with Contracts", + "anchor": "interacting-with-contracts" }, { "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 8044, - "words": 1111, - "headings": 9, - "estimated_token_count_total": 2249 + "chars": 6664, + "words": 905, + "headings": 8, + "estimated_token_count_total": 1347 + }, + "hash": "sha256:ceef35da1647c5f10217ad5058a5a932f0931e1c83e624539f0b67fd075eacb4", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-dev-environments-remix-troubleshooting", + "title": "smart-contracts-dev-environments-remix-troubleshooting", + "slug": "smart-contracts-dev-environments-remix-troubleshooting", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 }, - "hash": "sha256:1368f6d49bccb7ba0e642cc58ea2c97ca95ae45e390cb9fa2ab11b0b41de52f4", + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-dapps", - "title": "Decentralized Application Tutorials", - "slug": "tutorials-dapps", + "id": "smart-contracts-dev-environments-remix-verify-a-contract", + "title": "smart-contracts-dev-environments-remix-verify-a-contract", + "slug": "smart-contracts-dev-environments-remix-verify-a-contract", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-dapps.md", - "html_url": "https://docs.polkadot.com/tutorials/dapps/", - "preview": "This section provides hands-on tutorials for building decentralized applications (dApps) using the Polkadot SDK and its developer toolkits. These guides help you leverage Polkadot's infrastructure to build scalable, secure, and interoperable dApps without relying solely on smart contracts.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/verify-a-contract/", + "preview": "TODO", + "outline": [], + "stats": { + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 + }, + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-explorers", + "title": "Block Explorers", + "slug": "smart-contracts-explorers", + "categories": [ + "Smart Contracts", + "Tooling" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-explorers.md", + "html_url": "https://docs.polkadot.com/smart-contracts/explorers/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Core Functionality", + "anchor": "core-functionality" + }, + { + "depth": 2, + "title": "Available Block Explorers", + "anchor": "available-block-explorers" + }, + { + "depth": 3, + "title": "BlockScout", + "anchor": "blockscout" } ], "stats": { - "chars": 1206, - "words": 169, - "headings": 2, - "estimated_token_count_total": 198 + "chars": 1793, + "words": 223, + "headings": 4, + "estimated_token_count_total": 309 }, - "hash": "sha256:467765777cace42ab4e3f1bb36c94f97e655c5d2cd570e00dd747c6a3db043f7", + "hash": "sha256:93e8a3043d65583e3d66f8f5f0ed6f4ef89a908ef85da2b6ca906a1100b7dded", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-interoperability-xcm-channels", - "title": "Tutorials for Managing XCM Channels", - "slug": "tutorials-interoperability-xcm-channels", + "id": "smart-contracts-faucet", + "title": "Faucet", + "slug": "smart-contracts-faucet", "categories": [ - "Uncategorized" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-interoperability-xcm-channels.md", - "html_url": "https://docs.polkadot.com/tutorials/interoperability/xcm-channels/", - "preview": "Establishing [XCM channels](/develop/interoperability/xcm-channels/) is essential to unlocking Polkadot's native interoperability. Before bridging assets or sending cross-chain contract calls, the necessary XCM channels must be established.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-faucet.md", + "html_url": "https://docs.polkadot.com/smart-contracts/faucet/", + "preview": "Test tokens allow you to experiment with smart contracts, test transactions, and validate your dApp functionality without using real cryptocurrency.", "outline": [ { "depth": 2, - "title": "Understand the Process of Opening Channels", - "anchor": "understand-the-process-of-opening-channels" + "title": "Get Test Tokens", + "anchor": "get-test-tokens" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Things to Consider", + "anchor": "things-to-consider" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Using Your Test Tokens", + "anchor": "using-your-test-tokens" } ], "stats": { - "chars": 1816, - "words": 236, + "chars": 1890, + "words": 279, "headings": 3, - "estimated_token_count_total": 208 + "estimated_token_count_total": 313 }, - "hash": "sha256:3a6704a6330c6e35aa98fe8d615e2e27beb870a48c68bda02c217e6ae77274d2", + "hash": "sha256:c609bc98cba5efa2d2a808548cf93ad9d0a06455b35a8fd9f534daf52824f506", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-interoperability-xcm-transfers-from-relaychain-to-parachain", - "title": "XCM Transfers from Relay Chain to Parachain", - "slug": "tutorials-interoperability-xcm-transfers-from-relaychain-to-parachain", + "id": "smart-contracts-for-eth-devs-accounts", + "title": "Accounts in Asset Hub Smart Contracts", + "slug": "smart-contracts-for-eth-devs-accounts", "categories": [ - "Parachains" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-interoperability-xcm-transfers-from-relaychain-to-parachain.md", - "html_url": "https://docs.polkadot.com/tutorials/interoperability/xcm-transfers/from-relaychain-to-parachain/", - "preview": "[Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\\_blank} facilitates asset transfers both within the same consensus system and between different ones, such as between a relay chain and its parachains. For cross-system transfers, two main methods are available:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-accounts.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/accounts/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -13687,126 +7751,127 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Setup", - "anchor": "setup" + "title": "Address Types and Mappings", + "anchor": "address-types-and-mappings" }, { - "depth": 2, - "title": "Use Polkadot.js Apps", - "anchor": "use-polkadotjs-apps" + "depth": 3, + "title": "Ethereum to Polkadot Mapping", + "anchor": "ethereum-to-polkadot-mapping" }, { "depth": 3, - "title": "From the Relay Chain Perspective", - "anchor": "from-the-relay-chain-perspective" + "title": "Polkadot to Ethereum Mapping", + "anchor": "polkadot-to-ethereum-mapping" }, { "depth": 3, - "title": "From the Parachain Perspective", - "anchor": "from-the-parachain-perspective" + "title": "Account Mapping for Native Polkadot Accounts", + "anchor": "account-mapping-for-native-polkadot-accounts" }, { "depth": 2, - "title": "Use PAPI", - "anchor": "use-papi" + "title": "Account Registration", + "anchor": "account-registration" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 12680, - "words": 1562, - "headings": 8, - "estimated_token_count_total": 2764 - }, - "hash": "sha256:a2bba0ba575bd7e3f7199282ea5994087acf2c62e828f316e6eb62c9a43449e1", - "token_estimator": "heuristic-v1" - }, - { - "id": "tutorials-interoperability-xcm-transfers", - "title": "XCM Transfers", - "slug": "tutorials-interoperability-xcm-transfers", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-interoperability-xcm-transfers.md", - "html_url": "https://docs.polkadot.com/tutorials/interoperability/xcm-transfers/", - "preview": "Discover comprehensive tutorials that guide you through performing asset transfers between distinct consensus systems. These tutorials leverage [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} technology, that enables cross-chain communication and asset exchanges across different blockchain networks. Whether you're working within the same ecosystem or bridging multiple systems, XCM ensures secure, efficient, and interoperable solutions.", - "outline": [ + "title": "Fallback Accounts", + "anchor": "fallback-accounts" + }, + { + "depth": 2, + "title": "Contract Address Generation", + "anchor": "contract-address-generation" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Security Considerations", + "anchor": "security-considerations" } ], "stats": { - "chars": 826, - "words": 102, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 8521, + "words": 1138, + "headings": 9, + "estimated_token_count_total": 1816 }, - "hash": "sha256:917ce0777f8ac5a4288e54ce4086432d320b127a7fc753ade5392d766a1f3c33", + "hash": "sha256:dc95833b74404d8630a13e8746df3962e2d9d4777e5f18ca9a25d8d9302ebd53", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-interoperability", - "title": "Interoperability Tutorials", - "slug": "tutorials-interoperability", + "id": "smart-contracts-for-eth-devs-blocks-transactions-fees", + "title": "Transactions and Fees on Asset Hub", + "slug": "smart-contracts-for-eth-devs-blocks-transactions-fees", "categories": [ - "Uncategorized" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-interoperability.md", - "html_url": "https://docs.polkadot.com/tutorials/interoperability/", - "preview": "This section introduces you to the core interoperability solutions within the Polkadot ecosystem through practical, hands-on tutorials. These resources are designed to help you master cross-chain communication techniques, from setting up messaging channels between parachains to leveraging Polkadot's advanced features of the [XCM protocol](/parachains/interoperability/get-started/){target=\\_blank}.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-blocks-transactions-fees.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/blocks-transactions-fees/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, - "title": "XCM (Cross-Consensus Messaging)", - "anchor": "xcm-cross-consensus-messaging" + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "For Parachain Integrators", - "anchor": "for-parachain-integrators" + "depth": 2, + "title": "Smart Contract Blocks", + "anchor": "smart-contract-blocks" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Smart Contract Transactions", + "anchor": "smart-contract-transactions" + }, + { + "depth": 3, + "title": "EVM Transaction Types", + "anchor": "evm-transaction-types" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Fees and Gas", + "anchor": "fees-and-gas" + }, + { + "depth": 3, + "title": "Gas Model Overview", + "anchor": "gas-model-overview" + }, + { + "depth": 3, + "title": "Fee Components", + "anchor": "fee-components" + }, + { + "depth": 3, + "title": "Gas Calculation and Conversion", + "anchor": "gas-calculation-and-conversion" } ], "stats": { - "chars": 2193, - "words": 266, - "headings": 4, - "estimated_token_count_total": 339 + "chars": 6366, + "words": 791, + "headings": 8, + "estimated_token_count_total": 1182 }, - "hash": "sha256:9559f240b9433b496bfea92b57394a75c28bc743bb756c231f0137dfdf077e4a", + "hash": "sha256:9542f40acae725e628f4c3155ad1e7e0e18b2eb518484856ad439a1d9f86d1f3", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-onchain-governance-fast-track-gov-proposal", - "title": "Fast Track a Governance Proposal", - "slug": "tutorials-onchain-governance-fast-track-gov-proposal", + "id": "smart-contracts-for-eth-devs-contract-deployment", + "title": "Contract Deployment", + "slug": "smart-contracts-for-eth-devs-contract-deployment", "categories": [ - "Tooling" + "Smart Contracts", + "Basics" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-onchain-governance-fast-track-gov-proposal.md", - "html_url": "https://docs.polkadot.com/tutorials/onchain-governance/fast-track-gov-proposal/", - "preview": "Polkadot's [OpenGov](/polkadot-protocol/onchain-governance/overview){target=\\_blank} is a sophisticated governance mechanism designed to allow the network to evolve gracefully over time, guided by its stakeholders. This system features multiple [tracks](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#origins-and-tracks-info){target=\\_blank} for different types of proposals, each with parameters for approval, support, and confirmation period. While this flexibility is powerful, it", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-contract-deployment.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/contract-deployment/", + "preview": "Polkadot's smart contract platform supports two distinct virtual machine backends: Rust Ethereum Virtual Machine (REVM) and PolkaVM. Each backend has its own deployment characteristics and optimization strategies. REVM provides full Ethereum compatibility with familiar single-step deployment, while the RISC-V-based PolkaVM uses a more structured two-step approach optimized for its architecture. Understanding these differences ensures smooth deployment regardless of which backend you choose for y", "outline": [ { "depth": 2, @@ -13815,111 +7880,80 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "REVM Deployment", + "anchor": "revm-deployment" }, { "depth": 2, - "title": "Set Up the Project", - "anchor": "set-up-the-project" + "title": "PolkaVM Deployment", + "anchor": "polkavm-deployment" }, { - "depth": 2, - "title": "Submit and Execute a Proposal Using Chopsticks", - "anchor": "submit-and-execute-a-proposal-using-chopsticks" + "depth": 3, + "title": "Standard Contract Deployment", + "anchor": "standard-contract-deployment" }, { "depth": 3, - "title": "Spin Up the Polkadot Fork", - "anchor": "spin-up-the-polkadot-fork" + "title": "Two-Step Deployment Model", + "anchor": "two-step-deployment-model" }, { "depth": 3, - "title": "Set Up Dependencies and Structure", - "anchor": "set-up-dependencies-and-structure" + "title": "Factory Pattern Considerations", + "anchor": "factory-pattern-considerations" }, { "depth": 3, - "title": "Connect to the Forked Chain", - "anchor": "connect-to-the-forked-chain" + "title": "Migration Strategy for Factory Contracts", + "anchor": "migration-strategy-for-factory-contracts" }, { "depth": 3, - "title": "Create and Submit the Proposal", - "anchor": "create-and-submit-the-proposal" + "title": "Architecture-Specific Limitations", + "anchor": "architecture-specific-limitations" }, { "depth": 3, - "title": "Force Proposal Execution", - "anchor": "force-proposal-execution" + "title": "On-Chain Constructors", + "anchor": "on-chain-constructors" }, { "depth": 2, - "title": "Execute the Proposal Script", - "anchor": "execute-the-proposal-script" + "title": "Gas Estimation vs Actual Consumption", + "anchor": "gas-estimation-vs-actual-consumption" }, { "depth": 2, - "title": "Summary", - "anchor": "summary" + "title": "Deployment Comparison", + "anchor": "deployment-comparison" }, { "depth": 2, - "title": "Full Code", - "anchor": "full-code" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 169845, - "words": 17558, + "chars": 5999, + "words": 766, "headings": 12, - "estimated_token_count_total": 34492 - }, - "hash": "sha256:bef820acfe429d4a847a8de82de6c70155ac6b3ad5ebdd574a2157923b45f688", - "token_estimator": "heuristic-v1" - }, - { - "id": "tutorials-onchain-governance", - "title": "On-Chain Governance Tutorials", - "slug": "tutorials-onchain-governance", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-onchain-governance.md", - "html_url": "https://docs.polkadot.com/tutorials/onchain-governance/", - "preview": "On-chain governance enables decentralized networks to grow and adapt through collective decision-making. For developers, understanding and implementing governance features is crucial for contributing to network improvements and supporting user interactions.", - "outline": [ - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - }, - { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 867, - "words": 112, - "headings": 2, - "estimated_token_count_total": 125 + "estimated_token_count_total": 1133 }, - "hash": "sha256:c675e4231537732f24d1dd93f2b248398248a77c9877860fe53926e255ed0710", + "hash": "sha256:0792e3956242eb8e08ab82e2d73964c381074cc8b1ea46f396d136856fa6cc07", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-build-custom-pallet", - "title": "Build a Custom Pallet", - "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-build-custom-pallet", + "id": "smart-contracts-for-eth-devs-dual-vm-stack", + "title": "Dual Virtual Machine Stack", + "slug": "smart-contracts-for-eth-devs-dual-vm-stack", "categories": [ "Basics", - "Parachains" + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-build-custom-pallet.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/", - "preview": "In Polkadot SDK-based blockchains, runtime functionality is built through modular components called [pallets](/polkadot-protocol/glossary#pallet){target=\\_blank}. These pallets are Rust-based runtime modules created using [FRAME (Framework for Runtime Aggregation of Modular Entities)](/develop/parachains/customize-parachain/overview/){target=\\_blank}, a powerful library that simplifies blockchain development by providing specialized macros and standardized patterns for building blockchain logic.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -13928,89 +7962,110 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Create a New Project", - "anchor": "create-a-new-project" + "title": "Migrate from EVM", + "anchor": "migrate-from-evm" }, { "depth": 2, - "title": "Add Dependencies", - "anchor": "add-dependencies" + "title": "Upgrade to PolkaVM", + "anchor": "upgrade-to-polkavm" }, { "depth": 2, - "title": "Implement the Pallet Logic", - "anchor": "implement-the-pallet-logic" + "title": "Architecture", + "anchor": "architecture" }, { "depth": 3, - "title": "Add Scaffold Pallet Structure", - "anchor": "add-scaffold-pallet-structure" + "title": "Revive Pallet", + "anchor": "revive-pallet" }, { "depth": 3, - "title": "Pallet Configuration", - "anchor": "pallet-configuration" + "title": "PolkaVM Design Fundamentals", + "anchor": "polkavm-design-fundamentals" }, { - "depth": 3, - "title": "Add Events", - "anchor": "add-events" + "depth": 2, + "title": "Where To Go Next", + "anchor": "where-to-go-next" + } + ], + "stats": { + "chars": 5383, + "words": 702, + "headings": 7, + "estimated_token_count_total": 986 + }, + "hash": "sha256:2d918017faecf489ec786f34de6cd4366a86e9f1cecfbb7722cc03079e6b64ea", + "token_estimator": "heuristic-v1" + }, + { + "id": "smart-contracts-for-eth-devs-gas-model", + "title": "Gas Model on the Polkadot Hub", + "slug": "smart-contracts-for-eth-devs-gas-model", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-gas-model.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/gas-model/", + "preview": "The Polkadot Hub implements a gas model that bridges Ethereum's familiar gas concept with Polkadot's more sophisticated resource metering system. This page explains how gas works in the Polkadot Hub and what developers need to know when building smart contracts.", + "outline": [ + { + "depth": 2, + "title": "Overview", + "anchor": "overview" }, { - "depth": 3, - "title": "Add Storage Items", - "anchor": "add-storage-items" + "depth": 2, + "title": "Understanding Resources in the Polkadot Hub", + "anchor": "understanding-resources-in-the-polkadot-hub" }, { - "depth": 3, - "title": "Implement Custom Errors", - "anchor": "implement-custom-errors" + "depth": 2, + "title": "Gas vs Weight", + "anchor": "gas-vs-weight" }, { - "depth": 3, - "title": "Implement Calls", - "anchor": "implement-calls" + "depth": 2, + "title": "How Gas Estimation Works", + "anchor": "how-gas-estimation-works" }, { "depth": 2, - "title": "Verify Compilation", - "anchor": "verify-compilation" + "title": "Dynamic Gas Pricing", + "anchor": "dynamic-gas-pricing" }, { "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" + "title": "Transaction Execution Flow", + "anchor": "transaction-execution-flow" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 26829, - "words": 2787, - "headings": 14, - "estimated_token_count_total": 5338 + "chars": 5234, + "words": 751, + "headings": 7, + "estimated_token_count_total": 1046 }, - "hash": "sha256:b3530f5fc5c9e916181dbc259a7fbae9c60100cb0450fc6d47bbb0d140afa075", + "hash": "sha256:dd29fab6e3c00d720b10effa4e50373a6fe9ab4b7bfd3aea892c7fa9c84318a2", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-deploy-to-testnet", - "title": "Deploy on Paseo TestNet", - "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-deploy-to-testnet", + "id": "smart-contracts-for-eth-devs-json-rpc-apis", + "title": "JSON-RPC APIs", + "slug": "smart-contracts-for-eth-devs-json-rpc-apis", "categories": [ - "Parachains" + "Reference" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-deploy-to-testnet.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/deploy-to-testnet/", - "preview": "Previously, you learned how to [build and run a blockchain locally](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to a public test network.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -14019,267 +8074,194 @@ }, { "depth": 2, - "title": "Get Started with an Account and Tokens", - "anchor": "get-started-with-an-account-and-tokens" - }, - { - "depth": 2, - "title": "Reserve a Parachain Identifier", - "anchor": "reserve-a-parachain-identifier" + "title": "Available Methods", + "anchor": "available-methods" }, { - "depth": 2, - "title": "Generate Customs Keys for Your Collator", - "anchor": "generate-customs-keys-for-your-collator" + "depth": 3, + "title": "eth_accounts", + "anchor": "eth_accounts" }, { - "depth": 2, - "title": "Generate the Chain Specification", - "anchor": "generate-the-chain-specification" + "depth": 3, + "title": "eth_blockNumber", + "anchor": "eth_blocknumber" }, { - "depth": 2, - "title": "Export Required Files", - "anchor": "export-required-files" + "depth": 3, + "title": "eth_call", + "anchor": "eth_call" }, { - "depth": 2, - "title": "Register a Parathread", - "anchor": "register-a-parathread" + "depth": 3, + "title": "eth_chainId", + "anchor": "eth_chainid" }, { - "depth": 2, - "title": "Start the Collator Node", - "anchor": "start-the-collator-node" + "depth": 3, + "title": "eth_estimateGas", + "anchor": "eth_estimategas" }, { - "depth": 2, - "title": "Producing Blocks", - "anchor": "producing-blocks" + "depth": 3, + "title": "eth_gasPrice", + "anchor": "eth_gasprice" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 21251, - "words": 2506, - "headings": 10, - "estimated_token_count_total": 4358 - }, - "hash": "sha256:87b19f6e881611329b7015e8d8187d7d85b2b2ef14b01e832c8b8e20897e3b40", - "token_estimator": "heuristic-v1" - }, - { - "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-obtain-coretime", - "title": "Obtain Coretime", - "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-obtain-coretime", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-obtain-coretime.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/obtain-coretime/", - "preview": "After deploying a parachain to the Paseo TestNet in the [Deploy to TestNet](/tutorials/polkadot-sdk/parachains/zero-to-hero/deploy-to-testnet/){target=\\_blank} tutorial, the focus shifts to understanding Coretime, which is the mechanism in which validation resources are allocated from the relay chain to the respective task, such as a parachain. A parachain could only produce blocks and finalize them on the relay chain by obtaining coretime.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "eth_getBalance", + "anchor": "eth_getbalance" }, { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "depth": 3, + "title": "eth_getBlockByHash", + "anchor": "eth_getblockbyhash" }, { - "depth": 2, - "title": "Order On Demand Coretime", - "anchor": "order-on-demand-coretime" + "depth": 3, + "title": "eth_getBlockByNumber", + "anchor": "eth_getblockbynumber" }, { - "depth": 2, - "title": "Purchase Bulk Coretime", - "anchor": "purchase-bulk-coretime" + "depth": 3, + "title": "eth_getBlockTransactionCountByNumber", + "anchor": "eth_getblocktransactioncountbynumber" }, { "depth": 3, - "title": "Get Coretime Funds", - "anchor": "get-coretime-funds" + "title": "eth_getBlockTransactionCountByHash", + "anchor": "eth_getblocktransactioncountbyhash" }, { "depth": 3, - "title": "Purchase a Core", - "anchor": "purchase-a-core" + "title": "eth_getCode", + "anchor": "eth_getcode" }, { "depth": 3, - "title": "Assign a Core", - "anchor": "assign-a-core" - } - ], - "stats": { - "chars": 8625, - "words": 1309, - "headings": 7, - "estimated_token_count_total": 2138 - }, - "hash": "sha256:ff2c267284959711782c0d6ecb4b439c3a6cc31f763d5e1ff2cc3b1f6efb62b2", - "token_estimator": "heuristic-v1" - }, - { - "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-benchmarking", - "title": "Pallet Benchmarking", - "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-benchmarking", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-benchmarking.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-benchmarking/", - "preview": "After validating your pallet through testing and integrating it into your runtime, the next crucial step is benchmarking. Testing procedures were detailed in the [Pallet Unit Testing](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/){target=\\_blank} tutorial, while runtime integration was covered in the [Add Pallets to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/){target=\\_blank} guide.", - "outline": [ + "title": "eth_getLogs", + "anchor": "eth_getlogs" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "eth_getStorageAt", + "anchor": "eth_getstorageat" }, { - "depth": 2, - "title": "Environment Setup", - "anchor": "environment-setup" + "depth": 3, + "title": "eth_getTransactionCount", + "anchor": "eth_gettransactioncount" }, { - "depth": 2, - "title": "Implement Benchmark Tests", - "anchor": "implement-benchmark-tests" + "depth": 3, + "title": "eth_getTransactionByHash", + "anchor": "eth_gettransactionbyhash" }, { - "depth": 2, - "title": "Execute the Benchmarking", - "anchor": "execute-the-benchmarking" + "depth": 3, + "title": "eth_getTransactionByBlockNumberAndIndex", + "anchor": "eth_gettransactionbyblocknumberandindex" }, { - "depth": 2, - "title": "Add Benchmarking Weights to the Pallet", - "anchor": "add-benchmarking-weights-to-the-pallet" + "depth": 3, + "title": "eth_getTransactionByBlockHashAndIndex", + "anchor": "eth_gettransactionbyblockhashandindex" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 12857, - "words": 1539, - "headings": 6, - "estimated_token_count_total": 2929 - }, - "hash": "sha256:df60044893f48dd7f37a11de275a16bf32adb31317ed70a789fd7fac64150e1a", - "token_estimator": "heuristic-v1" - }, - { - "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-unit-testing", - "title": "Pallet Unit Testing", - "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-unit-testing", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-pallet-unit-testing.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/", - "preview": "You have learned how to create a new pallet in the [Build a Custom Pallet](/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/){target=\\_blank} tutorial; now you will see how to test the pallet to ensure that it works as expected. As stated in the [Pallet Testing](/parachains/customize-runtime/pallet-development/pallet-testing/){target=\\_blank} article, unit testing is crucial for ensuring the reliability and correctness of pallets in Polkadot SDK-based blockchains. Comprehensiv", - "outline": [ + "depth": 3, + "title": "eth_getTransactionReceipt", + "anchor": "eth_gettransactionreceipt" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "eth_maxPriorityFeePerGas", + "anchor": "eth_maxpriorityfeepergas" }, { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "depth": 3, + "title": "eth_sendRawTransaction", + "anchor": "eth_sendrawtransaction" }, { - "depth": 2, - "title": "Set Up the Testing Environment", - "anchor": "set-up-the-testing-environment" + "depth": 3, + "title": "eth_sendTransaction", + "anchor": "eth_sendtransaction" }, { - "depth": 2, - "title": "Implement Mocked Runtime", - "anchor": "implement-mocked-runtime" + "depth": 3, + "title": "eth_syncing", + "anchor": "eth_syncing" }, { "depth": 3, - "title": "Full Mocked Runtime", - "anchor": "full-mocked-runtime" + "title": "net_listening", + "anchor": "net_listening" }, { - "depth": 2, - "title": "Implement Test Cases", - "anchor": "implement-test-cases" + "depth": 3, + "title": "net_peerCount", + "anchor": "net_peercount" }, { "depth": 3, - "title": "Successful Operations", - "anchor": "successful-operations" + "title": "net_version", + "anchor": "net_version" }, { "depth": 3, - "title": "Preventing Value Overflow", - "anchor": "preventing-value-overflow" + "title": "system_health", + "anchor": "system_health" }, { "depth": 3, - "title": "Origin and Access Control", - "anchor": "origin-and-access-control" + "title": "web3_clientVersion", + "anchor": "web3_clientversion" }, { "depth": 3, - "title": "Edge Case Handling", - "anchor": "edge-case-handling" + "title": "debug_traceBlockByNumber", + "anchor": "debug_traceblockbynumber" }, { "depth": 3, - "title": "Verify State Changes", - "anchor": "verify-state-changes" + "title": "debug_traceTransaction", + "anchor": "debug_tracetransaction" }, { "depth": 3, - "title": "Full Test Suite", - "anchor": "full-test-suite" + "title": "debug_traceCall", + "anchor": "debug_tracecall" }, { "depth": 2, - "title": "Run the Tests", - "anchor": "run-the-tests" + "title": "Response Format", + "anchor": "response-format" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Error Handling", + "anchor": "error-handling" } ], "stats": { - "chars": 23736, - "words": 2324, - "headings": 14, - "estimated_token_count_total": 4789 + "chars": 31444, + "words": 3848, + "headings": 35, + "estimated_token_count_total": 9562 }, - "hash": "sha256:81750202081ff24447f4e129c49230eedb315d1b44c740b677c3495a8f7adb9a", + "hash": "sha256:da1669344010a793a5296c9397b2d5a85240ff6fbe37b885bce0139298364423", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-runtime-upgrade", - "title": "Runtime Upgrades", - "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-runtime-upgrade", + "id": "smart-contracts-for-eth-devs-migration", + "title": "Migration FAQs and Considerations", + "slug": "smart-contracts-for-eth-devs-migration", "categories": [ - "Uncategorized" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-runtime-upgrade.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/runtime-upgrade/", - "preview": "Upgrading the runtime of your Polkadot SDK-based blockchain is a fundamental feature that allows you to add new functionality, fix bugs, or improve performance without requiring a hard fork. Runtime upgrades are performed by submitting a special extrinsic that replaces the existing on-chain WASM runtime code. This process is trustless, transparent, and can be executed either through governance or using sudo, depending on your chain's configuration.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md", + "html_url": "https://docs.polkadot.com/smart-contracts/for-eth-devs/migration/", + "preview": "This guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns.", "outline": [ { "depth": 2, @@ -14288,282 +8270,229 @@ }, { "depth": 2, - "title": "Update the Runtime", - "anchor": "update-the-runtime" + "title": "Migration Considerations", + "anchor": "migration-considerations" }, { - "depth": 3, - "title": "Start Your Chain", - "anchor": "start-your-chain" + "depth": 2, + "title": "Migration Checklist", + "anchor": "migration-checklist" }, { - "depth": 3, - "title": "Add a New Feature", - "anchor": "add-a-new-feature" + "depth": 2, + "title": "Migration FAQs", + "anchor": "migration-faqs" }, { "depth": 3, - "title": "Update Runtime Configuration", - "anchor": "update-runtime-configuration" + "title": "Which backend should I choose?", + "anchor": "which-backend-should-i-choose" }, { "depth": 3, - "title": "Bump the Runtime Version", - "anchor": "bump-the-runtime-version" + "title": "Do I need to rewrite my Solidity code?", + "anchor": "do-i-need-to-rewrite-my-solidity-code" }, { "depth": 3, - "title": "Build the New Runtime", - "anchor": "build-the-new-runtime" + "title": "What about factory contracts?", + "anchor": "what-about-factory-contracts" }, { - "depth": 2, - "title": "Submit the Runtime Upgrade", - "anchor": "submit-the-runtime-upgrade" + "depth": 3, + "title": "How do gas costs compare?", + "anchor": "how-do-gas-costs-compare" }, { - "depth": 2, - "title": "Verify the Upgrade", - "anchor": "verify-the-upgrade" + "depth": 3, + "title": "Which Solidity features are not supported?", + "anchor": "which-solidity-features-are-not-supported" }, { "depth": 3, - "title": "Check Runtime Version", - "anchor": "check-runtime-version" + "title": "How do I handle the existential deposit?", + "anchor": "how-do-i-handle-the-existential-deposit" }, { "depth": 3, - "title": "Test New Functionality", - "anchor": "test-new-functionality" + "title": "Can I use my existing development tools?", + "anchor": "can-i-use-my-existing-development-tools" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 10233, - "words": 1378, + "chars": 6067, + "words": 777, "headings": 12, - "estimated_token_count_total": 2452 + "estimated_token_count_total": 1275 }, - "hash": "sha256:1eb463c6b2732ebed0d16165425cde438688d21cc302f759b40250850c2a5e83", + "hash": "sha256:d6cbd026bd22d3362fffe6bdab0ce3d1688482b6d1eec26368b46fd03eb82a5f", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-polkadot-sdk-parachains-zero-to-hero-set-up-a-template", - "title": "Set Up a Template", - "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero-set-up-a-template", + "id": "smart-contracts-get-started", + "title": "Get Started with Smart Contracts", + "slug": "smart-contracts-get-started", "categories": [ "Basics", - "Parachains" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero-set-up-a-template.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/set-up-a-template/", - "preview": "[Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} offers a versatile and extensible blockchain development framework, enabling you to create custom blockchains tailored to your specific application or business requirements.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md", + "html_url": "https://docs.polkadot.com/smart-contracts/get-started/", + "preview": "This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Quick Starts", + "anchor": "quick-starts" }, { "depth": 2, - "title": "Utility Tools", - "anchor": "utility-tools" + "title": "Build and Test Locally", + "anchor": "build-and-test-locally" }, { "depth": 2, - "title": "Compile the Runtime", - "anchor": "compile-the-runtime" + "title": "Ethereum Developer Resources", + "anchor": "ethereum-developer-resources" }, { "depth": 2, - "title": "Start the Local Chain", - "anchor": "start-the-local-chain" + "title": "Cookbook: Hands‑on Tutorials", + "anchor": "cookbook-handson-tutorials" }, { "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" + "title": "Libraries", + "anchor": "libraries" }, { "depth": 2, - "title": "Stop the Node", - "anchor": "stop-the-node" + "title": "Integrations", + "anchor": "integrations" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Precompiles", + "anchor": "precompiles" } ], "stats": { - "chars": 12524, - "words": 1873, - "headings": 8, - "estimated_token_count_total": 3255 + "chars": 10103, + "words": 937, + "headings": 7, + "estimated_token_count_total": 2888 }, - "hash": "sha256:fe94de6f97fb588552f6cbc6b1a4c7399e91f5f31585f61a0dee66f5f50ff8a0", + "hash": "sha256:8ec1a9444ba7ec4a35361f14bb0268be87d1ebee8079bb9740f47f69c90f877a", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-polkadot-sdk-parachains-zero-to-hero", - "title": "Zero To Hero Parachain Tutorial Series", - "slug": "tutorials-polkadot-sdk-parachains-zero-to-hero", + "id": "smart-contracts-integrations-indexers", + "title": "smart-contracts-integrations-indexers", + "slug": "smart-contracts-integrations-indexers", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains-zero-to-hero.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/zero-to-hero/", - "preview": "The **Parachain Zero To Hero Tutorials** provide developers with a series of step-by-step guides to building, testing, and deploying custom pallets and runtimes using the Polkadot SDK. These tutorials are designed to help you gain hands-on experience and understand the core concepts necessary to create efficient and scalable blockchains.", - "outline": [ - { - "depth": 2, - "title": "Parachain Development Cycle", - "anchor": "parachain-development-cycle" - } - ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-indexers.md", + "html_url": "https://docs.polkadot.com/smart-contracts/integrations/indexers/", + "preview": "TODO", + "outline": [], "stats": { - "chars": 828, - "words": 132, - "headings": 1, - "estimated_token_count_total": 42 + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 }, - "hash": "sha256:06acc146698c1d3224544987d7ee52da498e3179228f98a494e385c5786a3a2c", + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-polkadot-sdk-parachains", - "title": "Parachain Tutorials", - "slug": "tutorials-polkadot-sdk-parachains", + "id": "smart-contracts-integrations-oracles", + "title": "smart-contracts-integrations-oracles", + "slug": "smart-contracts-integrations-oracles", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-parachains.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/parachains/", - "preview": "The Polkadot SDK enables you to build custom blockchains that can operate as part of the Polkadot network. These tutorials guide you through the essential steps of developing, testing, and deploying your own parachain.", - "outline": [ - { - "depth": 2, - "title": "Parachain Zero To Hero Tutorials", - "anchor": "parachain-zero-to-hero-tutorials" - }, - { - "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" - }, - { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-oracles.md", + "html_url": "https://docs.polkadot.com/smart-contracts/integrations/oracles/", + "preview": "TODO", + "outline": [], "stats": { - "chars": 924, - "words": 122, - "headings": 3, - "estimated_token_count_total": 107 + "chars": 5, + "words": 1, + "headings": 0, + "estimated_token_count_total": 0 }, - "hash": "sha256:fdd391227992c966de25b9240f5492135a9993859ec42b77952c1aa3d2e39ed9", + "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-polkadot-sdk-system-chains-asset-hub", - "title": "Asset Hub Tutorials", - "slug": "tutorials-polkadot-sdk-system-chains-asset-hub", + "id": "smart-contracts-integrations-wallets", + "title": "Wallets for Polkadot Hub", + "slug": "smart-contracts-integrations-wallets", "categories": [ - "Uncategorized" + "Smart Contracts", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-system-chains-asset-hub.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/system-chains/asset-hub/", - "preview": "Polkadot SDK-based relay chains focus on security and consensus, leaving asset management to an external component, such as a [system chain](/polkadot-protocol/architecture/system-chains/){target=\\_blank}. The [Asset Hub](/reference/polkadot-hub/assets-and-smart-contracts/){target=\\_blank} is one example of a system chain and is vital to managing tokens which aren't native to the Polkadot ecosystem. Developers opting to integrate with Asset Hub can expect the following benefits:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md", + "html_url": "https://docs.polkadot.com/smart-contracts/integrations/wallets/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, - "title": "Benefits of Asset Hub", - "anchor": "benefits-of-asset-hub" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Connect Your Wallet", + "anchor": "connect-your-wallet" }, { - "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "depth": 3, + "title": "MetaMask", + "anchor": "metamask" }, { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1768, - "words": 250, - "headings": 4, - "estimated_token_count_total": 400 - }, - "hash": "sha256:2fc6f513fd8b269e586b754b2bdbd2af9df5178624a028fab940a385f3fee577", - "token_estimator": "heuristic-v1" - }, - { - "id": "tutorials-polkadot-sdk-system-chains", - "title": "System Chains Tutorials", - "slug": "tutorials-polkadot-sdk-system-chains", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-system-chains.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/system-chains/", - "preview": "In this section, you'll gain hands-on experience building solutions that integrate with [system chains](/polkadot-protocol/architecture/system-chains/){target=\\_blank} on Polkadot using the Polkadot SDK. System chains like the [Asset Hub](/reference/polkadot-hub/assets-and-smart-contracts/){target=\\_blank} provide essential infrastructure for enabling cross-chain interoperability and asset management across the Polkadot ecosystem.", - "outline": [ - { - "depth": 2, - "title": "For Parachain Integrators", - "anchor": "for-parachain-integrators" + "depth": 3, + "title": "SubWallet", + "anchor": "subwallet" }, { - "depth": 2, - "title": "For Developers Leveraging System Chains", - "anchor": "for-developers-leveraging-system-chains" + "depth": 3, + "title": "Talisman", + "anchor": "talisman" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 1560, - "words": 211, - "headings": 3, - "estimated_token_count_total": 211 + "chars": 7340, + "words": 1041, + "headings": 6, + "estimated_token_count_total": 1627 }, - "hash": "sha256:5d45ec9f8efda8c4bc2d0c21399a036d017a03540e7efab60d4710cb7eb33eb3", + "hash": "sha256:65809486f62f60c6a6ac8109f9f027361683c23f639991a045ec5c057b665026", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-polkadot-sdk-testing-fork-live-chains", - "title": "Fork a Chain with Chopsticks", - "slug": "tutorials-polkadot-sdk-testing-fork-live-chains", + "id": "smart-contracts-libraries-ethers-js", + "title": "Deploy Contracts to Polkadot Hub with Ethers.js", + "slug": "smart-contracts-libraries-ethers-js", "categories": [ - "Basics", - "dApps", + "Smart Contracts", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-testing-fork-live-chains.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/testing/fork-live-chains/", - "preview": "Chopsticks is an innovative tool that simplifies the process of forking live Polkadot SDK chains. This guide provides step-by-step instructions to configure and fork chains, enabling developers to:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-ethers-js.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/ethers-js/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -14577,61 +8506,80 @@ }, { "depth": 2, - "title": "Configuration File", - "anchor": "configuration-file" + "title": "Project Structure", + "anchor": "project-structure" + }, + { + "depth": 2, + "title": "Set Up the Project", + "anchor": "set-up-the-project" + }, + { + "depth": 2, + "title": "Install Dependencies", + "anchor": "install-dependencies" }, { "depth": 2, - "title": "Create a Fork", - "anchor": "create-a-fork" + "title": "Set Up the Ethers.js Provider", + "anchor": "set-up-the-ethersjs-provider" }, { "depth": 2, - "title": "Interact with a Fork", - "anchor": "interact-with-a-fork" + "title": "Compile Contracts", + "anchor": "compile-contracts" + }, + { + "depth": 3, + "title": "Install the Revive Library", + "anchor": "install-the-revive-library" }, { "depth": 3, - "title": "Use Polkadot.js Apps", - "anchor": "use-polkadotjs-apps" + "title": "Sample Storage Smart Contract", + "anchor": "sample-storage-smart-contract" }, { "depth": 3, - "title": "Use Polkadot.js Library", - "anchor": "use-polkadotjs-library" + "title": "Compile the Smart Contract", + "anchor": "compile-the-smart-contract" + }, + { + "depth": 2, + "title": "Deploy the Compiled Contract", + "anchor": "deploy-the-compiled-contract" }, { "depth": 2, - "title": "Replay Blocks", - "anchor": "replay-blocks" + "title": "Interact with the Contract", + "anchor": "interact-with-the-contract" }, { "depth": 2, - "title": "XCM Testing", - "anchor": "xcm-testing" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 22265, - "words": 1326, - "headings": 9, - "estimated_token_count_total": 2702 + "chars": 20457, + "words": 2333, + "headings": 13, + "estimated_token_count_total": 4474 }, - "hash": "sha256:1f8ab387f721d865a7ca75eaa2528f1f2ebd4528a7d65ffeb27c68953100a3cb", + "hash": "sha256:c74a28d8d62369591c5734535136508db3d1f7380e486fd214f98d433cafd6e7", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-polkadot-sdk-testing-spawn-basic-chain", - "title": "Spawn a Basic Chain with Zombienet", - "slug": "tutorials-polkadot-sdk-testing-spawn-basic-chain", + "id": "smart-contracts-libraries-viem", + "title": "viem for Polkadot Hub Smart Contracts", + "slug": "smart-contracts-libraries-viem", "categories": [ - "Basics", - "dApps", + "Smart Contracts", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-testing-spawn-basic-chain.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/testing/spawn-basic-chain/", - "preview": "Zombienet simplifies blockchain development by enabling developers to create temporary, customizable networks for testing and validation. These ephemeral chains are ideal for experimenting with configurations, debugging applications, and validating functionality in a controlled environment.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-viem.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/viem/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, @@ -14645,152 +8593,84 @@ }, { "depth": 2, - "title": "Set Up Local Provider", - "anchor": "set-up-local-provider" + "title": "Project Structure", + "anchor": "project-structure" }, { "depth": 2, - "title": "Define the Network", - "anchor": "define-the-network" + "title": "Set Up the Project", + "anchor": "set-up-the-project" }, { "depth": 2, - "title": "Spawn the Network", - "anchor": "spawn-the-network" + "title": "Install Dependencies", + "anchor": "install-dependencies" }, { "depth": 2, - "title": "Interact with the Spawned Network", - "anchor": "interact-with-the-spawned-network" + "title": "Initialize Project", + "anchor": "initialize-project" }, { - "depth": 3, - "title": "Connect to the Nodes", - "anchor": "connect-to-the-nodes" + "depth": 2, + "title": "Set Up the Chain Configuration", + "anchor": "set-up-the-chain-configuration" }, { - "depth": 3, - "title": "Check Metrics", - "anchor": "check-metrics" + "depth": 2, + "title": "Set Up the viem Client", + "anchor": "set-up-the-viem-client" }, - { - "depth": 3, - "title": "Check Logs", - "anchor": "check-logs" - } - ], - "stats": { - "chars": 9496, - "words": 1395, - "headings": 9, - "estimated_token_count_total": 2564 - }, - "hash": "sha256:97dadddf4c27f469f552875461fc54d331fa151e4656401e15d6d4173115eecf", - "token_estimator": "heuristic-v1" - }, - { - "id": "tutorials-polkadot-sdk-testing", - "title": "Blockchain Testing Tutorials", - "slug": "tutorials-polkadot-sdk-testing", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk-testing.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/testing/", - "preview": "Polkadot offers specialized tools that make it simple to create realistic testing environments, particularly for cross-chain interactions. These purpose-built tools enable developers to quickly spin up test networks that accurately simulate real-world scenarios. Learn to create controlled testing environments using powerful tools designed for Polkadot SDK development.", - "outline": [ { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Set Up a Wallet", + "anchor": "set-up-a-wallet" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" - } - ], - "stats": { - "chars": 843, - "words": 106, - "headings": 2, - "estimated_token_count_total": 80 - }, - "hash": "sha256:1dfbb8c3cfa27f92e982b4ce705415e117c50eb38f641691129863b474741da7", - "token_estimator": "heuristic-v1" - }, - { - "id": "tutorials-polkadot-sdk", - "title": "Polkadot SDK Tutorials", - "slug": "tutorials-polkadot-sdk", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-polkadot-sdk.md", - "html_url": "https://docs.polkadot.com/tutorials/polkadot-sdk/", - "preview": "The Polkadot SDK is a versatile framework for building custom blockchains, whether as standalone networks or as part of the Polkadot ecosystem. With its modular design and extensible tools, libraries, and runtime components, the SDK simplifies the process of creating parachains, system chains, and solochains.", - "outline": [ + "title": "Sample Smart Contract", + "anchor": "sample-smart-contract" + }, { "depth": 2, - "title": "Build and Deploy a Parachain", - "anchor": "build-and-deploy-a-parachain" + "title": "Compile the Contract", + "anchor": "compile-the-contract" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Deploy the Contract", + "anchor": "deploy-the-contract" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 1481, - "words": 214, - "headings": 3, - "estimated_token_count_total": 256 - }, - "hash": "sha256:d63121126e51c785f0dfd4ae4ecd49cb71640515d39df69a0689f30a7ab8122f", - "token_estimator": "heuristic-v1" - }, - { - "id": "tutorials-smart-contracts-demo-aplications", - "title": "Demo Applications", - "slug": "tutorials-smart-contracts-demo-aplications", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-demo-aplications.md", - "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/demo-aplications/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. This section highlights demo applications that can be deployed to Polkadot Hub. These examples illustrate practical use cases and provide guidance for developers looking to launch and test applications within the Polkadot ecosystem.", - "outline": [ + "title": "Interact with the Contract", + "anchor": "interact-with-the-contract" + }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 474, - "words": 60, - "headings": 1, - "estimated_token_count_total": 12 + "chars": 16600, + "words": 1940, + "headings": 14, + "estimated_token_count_total": 3891 }, - "hash": "sha256:94dbafb2d78b87d5f0f0c75de002501b8210ac8d66072bc07989f685837cbac5", + "hash": "sha256:e27657e4e4a14fe86f424b96631946ec36fb90d277e6010b6cbd64c4769aba8a", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-smart-contracts-launch-your-first-project-create-contracts", - "title": "Create a Smart Contract", - "slug": "tutorials-smart-contracts-launch-your-first-project-create-contracts", + "id": "smart-contracts-libraries-wagmi", + "title": "Wagmi for Polkadot Hub Smart Contracts", + "slug": "smart-contracts-libraries-wagmi", "categories": [ - "Basics", - "Smart Contracts" + "Smart Contracts", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project-create-contracts.md", - "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/create-contracts/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-wagmi.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/wagmi/", "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { @@ -14800,23 +8680,43 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Set Up the Project", + "anchor": "set-up-the-project" + }, + { + "depth": 2, + "title": "Install Dependencies", + "anchor": "install-dependencies" + }, + { + "depth": 2, + "title": "Configure Wagmi for Polkadot Hub", + "anchor": "configure-wagmi-for-polkadot-hub" + }, + { + "depth": 2, + "title": "Set Up the Wagmi Provider", + "anchor": "set-up-the-wagmi-provider" }, { "depth": 2, - "title": "Understanding Smart Contract Structure", - "anchor": "understanding-smart-contract-structure" + "title": "Connect a Wallet", + "anchor": "connect-a-wallet" + }, + { + "depth": 2, + "title": "Fetch Blockchain Data", + "anchor": "fetch-blockchain-data" }, { "depth": 2, - "title": "Create the Smart Contract", - "anchor": "create-the-smart-contract" + "title": "Interact with Deployed Contract", + "anchor": "interact-with-deployed-contract" }, { "depth": 2, - "title": "Understanding the Code", - "anchor": "understanding-the-code" + "title": "Integrate Components", + "anchor": "integrate-components" }, { "depth": 2, @@ -14825,25 +8725,25 @@ } ], "stats": { - "chars": 8665, - "words": 1178, - "headings": 6, - "estimated_token_count_total": 1760 + "chars": 13604, + "words": 1515, + "headings": 10, + "estimated_token_count_total": 3250 }, - "hash": "sha256:9cf70459e921b8b231a3f2e7a7c1d47a4917e45f0c4d0fe873ad4062fd540a9a", + "hash": "sha256:bc771f912627fa09cad64adab1bc81c052f650d6c5a3b4f0c91883a98f6628da", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-smart-contracts-launch-your-first-project-create-dapp-ethers-js", - "title": "Create a dApp With Ethers.js", - "slug": "tutorials-smart-contracts-launch-your-first-project-create-dapp-ethers-js", + "id": "smart-contracts-libraries-web3-js", + "title": "Web3.js", + "slug": "smart-contracts-libraries-web3-js", "categories": [ - "dApp", + "Smart Contracts", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project-create-dapp-ethers-js.md", - "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/create-dapp-ethers-js/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-js.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/web3-js/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. !!! warning Web3.js has been [sunset](https://blog.chainsafe.io/web3-js-sunset/){target=\\_blank}. You can find guides on using [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank} and [viem](/smart-contracts/libraries/viem/){target=\\_blank} in the Libraries section.", "outline": [ { "depth": 2, @@ -14857,8 +8757,8 @@ }, { "depth": 2, - "title": "Project Overview", - "anchor": "project-overview" + "title": "Project Structure", + "anchor": "project-structure" }, { "depth": 2, @@ -14867,65 +8767,60 @@ }, { "depth": 2, - "title": "Connect to Polkadot Hub", - "anchor": "connect-to-polkadot-hub" + "title": "Install Dependencies", + "anchor": "install-dependencies" }, { "depth": 2, - "title": "Set Up the Smart Contract Interface", - "anchor": "set-up-the-smart-contract-interface" + "title": "Set Up the Web3 Provider", + "anchor": "set-up-the-web3-provider" }, { "depth": 2, - "title": "Create the Wallet Connection Component", - "anchor": "create-the-wallet-connection-component" + "title": "Compile Contracts", + "anchor": "compile-contracts" }, { "depth": 2, - "title": "Read Data from the Blockchain", - "anchor": "read-data-from-the-blockchain" + "title": "Contract Deployment", + "anchor": "contract-deployment" }, { "depth": 2, - "title": "Write Data to the Blockchain", - "anchor": "write-data-to-the-blockchain" + "title": "Interact with the Contract", + "anchor": "interact-with-the-contract" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 2525, - "words": 328, - "headings": 3, - "estimated_token_count_total": 412 + "chars": 13266, + "words": 1579, + "headings": 10, + "estimated_token_count_total": 3035 }, - "hash": "sha256:de7fde61d4cac9c28634ee496dcabe116fe44b1b87408f202103290d78247c05", + "hash": "sha256:f0d36333d0d3afff7f6374a61d0f6d1fb878c9ef4c4e4c24447745661dbe59d0", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-smart-contracts-launch-your-first-project-create-dapp-viem", - "title": "Create a dApp With Viem", - "slug": "tutorials-smart-contracts-launch-your-first-project-create-dapp-viem", + "id": "smart-contracts-libraries-web3-py", + "title": "Web3.py", + "slug": "smart-contracts-libraries-web3-py", "categories": [ - "dApp", + "Smart Contracts", "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project-create-dapp-viem.md", - "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/create-dapp-viem/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Decentralized applications (dApps) are a key component of the Web3 ecosystem, enabling developers to build applications that communicate directly with blockchain networks. Polkadot Hub, a blockchain with smart contract support, serves as a robust platform for deploying and interacting with dApps.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-py.md", + "html_url": "https://docs.polkadot.com/smart-contracts/libraries/web3-py/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Project Overview", - "anchor": "project-overview" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, @@ -14934,43 +8829,18 @@ }, { "depth": 2, - "title": "Install Dependencies", - "anchor": "install-dependencies" - }, - { - "depth": 2, - "title": "Connect to Polkadot Hub", - "anchor": "connect-to-polkadot-hub" - }, - { - "depth": 2, - "title": "Set Up the Smart Contract Interface", - "anchor": "set-up-the-smart-contract-interface" - }, - { - "depth": 2, - "title": "Create the Wallet Connection Component", - "anchor": "create-the-wallet-connection-component" - }, - { - "depth": 2, - "title": "Create the Read Contract Component", - "anchor": "create-the-read-contract-component" - }, - { - "depth": 2, - "title": "Create the Write Contract Component", - "anchor": "create-the-write-contract-component" + "title": "Set Up the Web3 Provider", + "anchor": "set-up-the-web3-provider" }, { "depth": 2, - "title": "How It Works", - "anchor": "how-it-works" + "title": "Contract Deployment", + "anchor": "contract-deployment" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Interact with the Contract", + "anchor": "interact-with-the-contract" }, { "depth": 2, @@ -14979,24 +8849,24 @@ } ], "stats": { - "chars": 27924, - "words": 3201, - "headings": 12, - "estimated_token_count_total": 6206 + "chars": 11627, + "words": 1333, + "headings": 6, + "estimated_token_count_total": 2509 }, - "hash": "sha256:cb8ddb4a61f6a62182420b69382f1c7ab2adc2f4ae643f7f68c6867680afe81f", + "hash": "sha256:205892e350168b3d0da7ccc280c67c3217ad1e45e87a53d124fa1dd69661aa5e", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-smart-contracts-launch-your-first-project-test-and-deploy-with-hardhat", - "title": "Test and Deploy with Hardhat", - "slug": "tutorials-smart-contracts-launch-your-first-project-test-and-deploy-with-hardhat", + "id": "smart-contracts-overview", + "title": "Smart Contracts Overview", + "slug": "smart-contracts-overview", "categories": [ - "dApp", - "Tooling" + "Basics", + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project-test-and-deploy-with-hardhat.md", - "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/test-and-deploy-with-hardhat/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md", + "html_url": "https://docs.polkadot.com/smart-contracts/overview/", "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { @@ -15006,155 +8876,200 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Native Smart Contracts", + "anchor": "native-smart-contracts" }, { - "depth": 2, - "title": "Setting Up the Development Environment", - "anchor": "setting-up-the-development-environment" + "depth": 3, + "title": "Introduction", + "anchor": "introduction-2" }, { - "depth": 2, - "title": "Adding the Smart Contract", - "anchor": "adding-the-smart-contract" + "depth": 3, + "title": "Smart Contract Development", + "anchor": "smart-contract-development" }, { - "depth": 2, - "title": "Writing Tests", - "anchor": "writing-tests" + "depth": 3, + "title": "Technical Architecture", + "anchor": "technical-architecture" }, { - "depth": 2, - "title": "Deploying with Ignition", - "anchor": "deploying-with-ignition" + "depth": 3, + "title": "Development Tools and Resources", + "anchor": "development-tools-and-resources" + }, + { + "depth": 3, + "title": "Cross-Chain Capabilities", + "anchor": "cross-chain-capabilities" + }, + { + "depth": 3, + "title": "Use Cases", + "anchor": "use-cases" }, { "depth": 2, - "title": "Interacting with Your Deployed Contract", - "anchor": "interacting-with-your-deployed-contract" + "title": "Other Smart Contract Environments", + "anchor": "other-smart-contract-environments" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 18699, - "words": 2238, - "headings": 8, - "estimated_token_count_total": 4135 + "chars": 6305, + "words": 804, + "headings": 10, + "estimated_token_count_total": 1122 }, - "hash": "sha256:ca1d65d450f086a0eb7b81e9589e9894e04b217fe9709a1b464f09beb3ca9dc2", + "hash": "sha256:ee87115c828928c82937de26f5f938cecd4c3bb1225fdb61627e8092e6ea5951", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-smart-contracts-launch-your-first-project", - "title": "Launch Your First Project", - "slug": "tutorials-smart-contracts-launch-your-first-project", + "id": "smart-contracts-precompiles-eth-native", + "title": "Ethereum-Native Precompiles", + "slug": "smart-contracts-precompiles-eth-native", "categories": [ - "Uncategorized" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts-launch-your-first-project.md", - "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/launch-your-first-project/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Kickstart your journey into smart contract development with this comprehensive guide. Learn how to create, deploy, and interact with contracts on Polkadot. Whether you're new to smart contracts or refining your skills, these guides provide a structured approach to launching your project.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-eth-native.md", + "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/eth-native/", + "preview": "Ethereum-native precompiles are special contract implementations that provide essential cryptographic and utility functions at the runtime level. These precompiles are available at predefined addresses and offer optimized, native implementations of commonly used operations that would be computationally expensive or impractical to implement in pure contract code.", "outline": [ { "depth": 2, - "title": "Development Pathway", - "anchor": "development-pathway" + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "How to Use Precompiles", + "anchor": "how-to-use-precompiles" + }, + { + "depth": 2, + "title": "Standard Precompiles in Polkadot Hub", + "anchor": "standard-precompiles-in-polkadot-hub" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 1211, - "words": 161, - "headings": 2, - "estimated_token_count_total": 77 + "chars": 5232, + "words": 532, + "headings": 4, + "estimated_token_count_total": 1192 }, - "hash": "sha256:8d8fc5f794d4c793586cd3d412627f5e2fe76f182c75c3687abcf33deed5d65e", + "hash": "sha256:f17db5daca8feae70ce428e03a5a4870ef87dfc8571b07376327cd80d057b759", "token_estimator": "heuristic-v1" }, { - "id": "tutorials-smart-contracts", - "title": "Smart Contracts", - "slug": "tutorials-smart-contracts", + "id": "smart-contracts-precompiles-xcm", + "title": "Interact with the XCM Precompile", + "slug": "smart-contracts-precompiles-xcm", "categories": [ - "Uncategorized" + "Smart Contracts" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials-smart-contracts.md", - "html_url": "https://docs.polkadot.com/tutorials/smart-contracts/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. Get started with deploying and interacting with smart contracts on Polkadot through practical, hands-on tutorials. Whether you're a beginner or an experienced developer, these guides will help you navigate the entire development lifecycle.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles-xcm.md", + "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/xcm/", + "preview": "The [XCM (Cross-Consensus Message)](/parachains/interoperability/get-started/){target=\\_blank} precompile enables Polkadot Hub developers to access XCM functionality directly from their smart contracts using a Solidity interface.", "outline": [ { "depth": 2, - "title": "What to Expect from These Tutorials", - "anchor": "what-to-expect-from-these-tutorials" + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Precompile Interface", + "anchor": "precompile-interface" + }, + { + "depth": 2, + "title": "Interact with the XCM Precompile", + "anchor": "interact-with-the-xcm-precompile" + }, + { + "depth": 3, + "title": "Weigh a Message", + "anchor": "weigh-a-message" + }, + { + "depth": 3, + "title": "Execute a Message", + "anchor": "execute-a-message" + }, + { + "depth": 3, + "title": "Send a Message", + "anchor": "send-a-message" + }, + { + "depth": 2, + "title": "Cross Contract Calls", + "anchor": "cross-contract-calls" }, { "depth": 2, - "title": "Start Building", - "anchor": "start-building" + "title": "Conclusion", + "anchor": "conclusion" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 1057, - "words": 145, - "headings": 3, - "estimated_token_count_total": 130 + "chars": 10705, + "words": 1436, + "headings": 9, + "estimated_token_count_total": 2325 }, - "hash": "sha256:66bc34a12c50539dde2ffc69fe66891f73d3e1a2da5833ada15e26744ff32209", + "hash": "sha256:c084190ea7d676128e7e399e8fe88598ca150f88d684db279a687ee1c3956120", "token_estimator": "heuristic-v1" }, { - "id": "tutorials", - "title": "Tutorials", - "slug": "tutorials", + "id": "smart-contracts-precompiles", + "title": "Advanced Functionalities via Precompiles", + "slug": "smart-contracts-precompiles", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/tutorials.md", - "html_url": "https://docs.polkadot.com/tutorials/", - "preview": "Welcome to the Polkadot Tutorials hub! Whether you’re building parachains, integrating system chains, or developing decentralized applications, these step-by-step guides are designed to help you achieve your goals efficiently and effectively.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles.md", + "html_url": "https://docs.polkadot.com/smart-contracts/precompiles/", + "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", "outline": [ { "depth": 2, - "title": "Polkadot Zero to Hero", - "anchor": "polkadot-zero-to-hero" - }, - { - "depth": 3, - "title": "Parachain Developers", - "anchor": "parachain-developers" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Featured Tutorials", - "anchor": "featured-tutorials" + "title": "What are Precompiles?", + "anchor": "what-are-precompiles" }, { "depth": 2, - "title": "In This Section", - "anchor": "in-this-section" + "title": "Conclusion", + "anchor": "conclusion" } ], "stats": { - "chars": 2501, - "words": 355, - "headings": 4, - "estimated_token_count_total": 590 + "chars": 2525, + "words": 328, + "headings": 3, + "estimated_token_count_total": 412 }, - "hash": "sha256:a1d7789d44e4653e98ed41b8a13ea69e7733803c598ca850c9e2fc8f27a2b410", + "hash": "sha256:a40e3f34f70db22bfe39e40d68dc5a53a726ce47cb73b602d8605355c61ffd22", "token_estimator": "heuristic-v1" } ] \ No newline at end of file diff --git a/llms-full.jsonl b/llms-full.jsonl index 010a38dbe..48f4c797d 100644 --- a/llms-full.jsonl +++ b/llms-full.jsonl @@ -431,9 +431,9 @@ {"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 5, "depth": 2, "title": "Compile the Runtime", "anchor": "compile-the-runtime", "start_char": 5097, "end_char": 6061, "estimated_token_count": 189, "token_estimator": "heuristic-v1", "text": "## Compile the Runtime\n\nNow that you understand the template structure, let's compile the runtime to ensure everything is working correctly.\n\n1. Compile the runtime:\n\n ```bash\n cargo build --release --locked\n ```\n\n !!!tip\n Initial compilation may take several minutes, depending on your machine specifications. Use the `--release` flag for improved runtime performance compared to the default `--debug` build. If you need to troubleshoot issues, the `--debug` build provides better diagnostics.\n \n For production deployments, consider using a dedicated `--profile production` flag - this can provide an additional 15-30% performance improvement over the standard `--release` profile.\n\n2. Upon successful compilation, you should see output indicating the build was successful. The compiled runtime will be located at:\n \n `./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm`"} {"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 6, "depth": 2, "title": "Verify the Build", "anchor": "verify-the-build", "start_char": 6061, "end_char": 6394, "estimated_token_count": 71, "token_estimator": "heuristic-v1", "text": "## Verify the Build\n\nAfter compilation completes, verify that the runtime was created successfully by checking for the Wasm blob:\n\n```bash\nls -la ./target/release/wbuild/parachain-template-runtime/\n```\n\nYou should see the `parachain_template_runtime.compact.compressed.wasm` file in the output, confirming the build was successful."} {"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 7, "depth": 2, "title": "Run the Node Locally", "anchor": "run-the-node-locally", "start_char": 6394, "end_char": 8108, "estimated_token_count": 343, "token_estimator": "heuristic-v1", "text": "## Run the Node Locally\n\nAfter successfully compiling your runtime, you can spin up a local chain and produce blocks. This process will start your local parachain using the Polkadot Omni Node and allow you to interact with it. You'll first need to generate a chain specification that defines your network's identity, initial connections, and genesis state, providing the foundational configuration for how your nodes connect and what initial state they agree upon.\n\nFollow these steps to launch your node in development mode:\n\n1. Generate the chain specification file of your parachain:\n\n ```bash\n chain-spec-builder create -t development \\\n --relay-chain paseo \\\n --para-id 1000 \\\n --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \\\n named-preset development\n ```\n\n2. Start the Omni Node with the generated chain spec. You'll start it in development mode (without a relay chain config), producing and finalizing blocks:\n\n ```bash\n polkadot-omni-node --chain ./chain_spec.json --dev\n ```\n\n The `--dev` option does the following:\n\n - Deletes all active data (keys, blockchain database, networking information) when stopped.\n - Ensures a clean working state each time you restart the node.\n\n3. Verify that your node is running by reviewing the terminal output. You should see log messages indicating block production and finalization.\n\n4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output.\n\nThe details of the log output will be explored in a later tutorial. For now, knowing that your node is running and producing blocks is sufficient."} -{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 8, "depth": 2, "title": "Interact with the Node", "anchor": "interact-with-the-node", "start_char": 8108, "end_char": 9677, "estimated_token_count": 414, "token_estimator": "heuristic-v1", "text": "## Interact with the Node\n\nWhen running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} interface, follow these steps:\n\n1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner:\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp)\n\n2. Connect to your local node:\n\n 1. Scroll to the bottom and select **Development**.\n 2. Choose **Custom**.\n 3. Enter `ws**: //localhost:9944` in the **custom endpoint** input field.\n 4. Click the **Switch** button.\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp)\n\n3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain.\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp)\n\nYou are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\\_blank} available on the Polkadot Wiki."} -{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 9, "depth": 2, "title": "Stop the Node", "anchor": "stop-the-node", "start_char": 9677, "end_char": 10183, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "## Stop the Node\n\nWhen you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time.\n\nTo stop the local node:\n\n1. Return to the terminal window where the node output is displayed.\n2. Press `Control-C` to stop the running process.\n3. Verify that your terminal returns to the prompt in the `parachain-template` directory."} -{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 10, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 10183, "end_char": 10591, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Tutorial __Deploy to Polkadot__\n\n ---\n\n Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks.\n\n [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md)\n\n
"} +{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 8, "depth": 2, "title": "Interact with the Node", "anchor": "interact-with-the-node", "start_char": 8108, "end_char": 9674, "estimated_token_count": 412, "token_estimator": "heuristic-v1", "text": "## Interact with the Node\n\nWhen running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} interface, follow these steps:\n\n1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner:\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp)\n\n2. Connect to your local node:\n\n 1. Scroll to the bottom and select **Development**.\n 2. Choose **Custom**.\n 3. Enter `ws://localhost:9944` in the **custom endpoint** input field.\n 4. Click the **Switch** button.\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp)\n\n3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain.\n \n ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp)\n\nYou are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\\_blank} available on the Polkadot Wiki."} +{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 9, "depth": 2, "title": "Stop the Node", "anchor": "stop-the-node", "start_char": 9674, "end_char": 10180, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "## Stop the Node\n\nWhen you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time.\n\nTo stop the local node:\n\n1. Return to the terminal window where the node output is displayed.\n2. Press `Control-C` to stop the running process.\n3. Verify that your terminal returns to the prompt in the `parachain-template` directory."} +{"page_id": "parachains-launch-a-parachain-set-up-the-parachain-template", "page_title": "Set Up the Polkadot SDK Parachain Template", "index": 10, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 10180, "end_char": 10588, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Tutorial __Deploy to Polkadot__\n\n ---\n\n Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks.\n\n [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md)\n\n
"} {"page_id": "parachains-runtime-maintenance-runtime-upgrades", "page_title": "Runtime Upgrades", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 20, "end_char": 926, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nOne of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.\n\nForkless upgrades are achieved through WebAssembly (Wasm) runtimes stored on-chain, which can be securely swapped and upgraded as part of the blockchain's state. By leveraging decentralized consensus, runtime updates can happen trustlessly, ensuring continuous improvement and evolution without halting operations.\n\nThis guide explains how Polkadot's runtime versioning, Wasm deployment, and storage migrations enable these upgrades, ensuring the blockchain evolves smoothly and securely. You'll also learn how different upgrade processes apply to solo chains and parachains, depending on the network setup."} {"page_id": "parachains-runtime-maintenance-runtime-upgrades", "page_title": "Runtime Upgrades", "index": 1, "depth": 2, "title": "How Runtime Upgrades Work", "anchor": "how-runtime-upgrades-work", "start_char": 926, "end_char": 1650, "estimated_token_count": 165, "token_estimator": "heuristic-v1", "text": "## How Runtime Upgrades Work\n\nIn FRAME, the [`system`](https://paritytech.github.io/polkadot-sdk/master/frame_system/index.html){target=\\_blank} pallet uses the [`set_code`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/enum.Call.html#variant.set_code){target=\\_blank} extrinsic to update the Wasm code for the runtime. This method allows solo chains to upgrade without disruption. \n\nFor parachains, upgrades are more complex. Parachains must first call `authorize_upgrade`, followed by `apply_authorized_upgrade`, to ensure the relay chain approves and applies the changes. Additionally, changes to current functionality that impact storage often require a [storage migration](#storage-migrations)."} {"page_id": "parachains-runtime-maintenance-runtime-upgrades", "page_title": "Runtime Upgrades", "index": 2, "depth": 3, "title": "Runtime Versioning", "anchor": "runtime-versioning", "start_char": 1650, "end_char": 4915, "estimated_token_count": 664, "token_estimator": "heuristic-v1", "text": "### Runtime Versioning\n\nThe executor is the component that selects the runtime execution environment to communicate with. Although you can override the default execution strategies for custom scenarios, in most cases, the executor selects the appropriate binary to use by evaluating and comparing key parameters from the native and Wasm runtime binaries.\n\nThe runtime includes a [runtime version struct](https://paritytech.github.io/polkadot-sdk/master/sp_version/struct.RuntimeVersion.html){target=\\_blank} to provide the needed parameter information to the executor process. A sample runtime version struct might look as follows:\n\n```rust\npub const VERSION: RuntimeVersion = RuntimeVersion {\n spec_name: create_runtime_str!(\"node-template\"),\n impl_name: create_runtime_str!(\"node-template\"),\n authoring_version: 1,\n spec_version: 1,\n impl_version: 1,\n apis: RUNTIME_API_VERSIONS,\n transaction_version: 1,\n};\n```\n\nThe struct provides the following parameter information to the executor:\n\n- **`spec_name`**: The identifier for the different runtimes.\n- **`impl_name`**: The name of the implementation of the spec. Serves only to differentiate code of different implementation teams.\n- **`authoring_version`**: The version of the authorship interface. An authoring node won't attempt to author blocks unless this is equal to its native runtime.\n- **`spec_version`**: The version of the runtime specification. A full node won't attempt to use its native runtime in substitute for the on-chain Wasm runtime unless the `spec_name`, `spec_version`, and `authoring_version` are all the same between the Wasm and native binaries. Updates to the `spec_version` can be automated as a CI process. This parameter is typically incremented when there's an update to the `transaction_version`.\n- **`impl_version`**: The version of the implementation of the specification. Nodes can ignore this. It is only used to indicate that the code is different. As long as the `authoring_version` and the `spec_version` are the same, the code might have changed, but the native and Wasm binaries do the same thing. In general, only non-logic-breaking optimizations would result in a change of the `impl_version`.\n- **`transaction_version`**: The version of the interface for handling transactions. This parameter can be useful to synchronize firmware updates for hardware wallets or other signing devices to verify that runtime transactions are valid and safe to sign. This number must be incremented if there is a change in the index of the pallets in the `construct_runtime!` macro or if there are any changes to dispatchable functions, such as the number of parameters or parameter types. If `transaction_version` is updated, then the `spec_version` must also be updated.\n- **`apis`**: A list of supported [runtime APIs](https://paritytech.github.io/polkadot-sdk/master/sp_api/macro.impl_runtime_apis.html){target=\\_blank} along with their versions.\n\nThe executor follows the same consensus-driven logic for both the native runtime and the Wasm runtime before deciding which to execute. Because runtime versioning is a manual process, there is a risk that the executor could make incorrect decisions if the runtime version is misrepresented or incorrectly defined."} @@ -858,6 +858,13 @@ {"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 4, "depth": 3, "title": "Astar XCM Tools", "anchor": "astar-xcm-tools", "start_char": 2667, "end_char": 4207, "estimated_token_count": 369, "token_estimator": "heuristic-v1", "text": "### Astar XCM Tools\n\nThe [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks:\n\n- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command.\n- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments.\n- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs.\n\nTo start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\\_blank} and compile the xcm-tools package:\n\n```bash\ngit clone https://github.com/AstarNetwork/Astar &&\ncd Astar &&\ncargo build --release -p xcm-tools\n```\n\nAfter compiling, verify the setup with the following command:\n\n```bash\n./target/release/xcm-tools --help\n```\nFor more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\\_blank}."} {"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 5, "depth": 3, "title": "Chopsticks", "anchor": "chopsticks", "start_char": 4207, "end_char": 4517, "estimated_token_count": 65, "token_estimator": "heuristic-v1", "text": "### Chopsticks\n\nThe Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\\_blank} about XCM."} {"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 6, "depth": 3, "title": "Moonbeam XCM SDK", "anchor": "moonbeam-xcm-sdk", "start_char": 4517, "end_char": 6146, "estimated_token_count": 385, "token_estimator": "heuristic-v1", "text": "### Moonbeam XCM SDK\n\nThe [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\\_blank} of the origin or destination assets or which extrinsics are used on which networks.\n\nThe SDK consists of two main packages:\n\n- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem.\n- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum.\n\nKey features include:\n\n- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection.\n- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems.\n- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality.\n- **Comprehensive documentation**: Includes usage guides and API references for both packages.\n\nFor detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\\_blank}."} +{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 0, "end_char": 1097, "estimated_token_count": 199, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need.\n\nPolkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\\_blank} to the [governance](/reference/glossary#governance){target=\\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants.\n\nThis guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem."} +{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 1, "depth": 2, "title": "Polkadot Hub", "anchor": "polkadot-hub", "start_char": 1097, "end_char": 2378, "estimated_token_count": 247, "token_estimator": "heuristic-v1", "text": "## Polkadot Hub\n\n[Polkadot Hub](/reference/polkadot-hub/){target=\\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain.\n\nThe Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include:\n\n- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications.\n- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem.\n- **Staking**: Participate in network security and earn rewards by staking DOT.\n- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov.\n- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities.\n- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem.\n- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations."} +{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 2, "depth": 2, "title": "Parachains", "anchor": "parachains", "start_char": 2378, "end_char": 3697, "estimated_token_count": 293, "token_estimator": "heuristic-v1", "text": "## Parachains\n\n[Parachains](/reference/parachains/){target=\\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers:\n\n- **Accounts**: Deep dive into account types, storage, and management on parachains.\n- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms.\n- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus.\n- **Chain data**: Explore data structures, storage layouts, and state management.\n- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains.\n- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility.\n- **Networks**: Learn about networking protocols and peer-to-peer communication.\n- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\\_blank}, the standard for cross-chain communication.\n- **Randomness**: Understand how randomness is generated and used in Polkadot chains.\n- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}."} +{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 3, "depth": 2, "title": "On-Chain Governance", "anchor": "on-chain-governance", "start_char": 3697, "end_char": 4577, "estimated_token_count": 170, "token_estimator": "heuristic-v1", "text": "## On-Chain Governance\n\n[On-Chain governance](/reference/governance/){target=\\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details:\n\n- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums.\n- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity.\n- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance.\n- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system."} +{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 4, "depth": 2, "title": "Glossary", "anchor": "glossary", "start_char": 4577, "end_char": 5018, "estimated_token_count": 90, "token_estimator": "heuristic-v1", "text": "## Glossary\n\nThe [Glossary](/reference/glossary/){target=\\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include:\n\n- Blockchain concepts (blocks, transactions, state)\n- Consensus mechanisms (validators, collators, finality)\n- Polkadot-specific terms (relay chain, parachain, XCM, FRAME)\n- Network components (nodes, runtimes, storage)\n- Governance terminology (origins, tracks, referendums)"} +{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 5, "depth": 2, "title": "Tools", "anchor": "tools", "start_char": 5018, "end_char": 6285, "estimated_token_count": 349, "token_estimator": "heuristic-v1", "text": "## Tools\n\nThe [Tools](/reference/tools/){target=\\_blank} section documents essential development and interaction tools for the Polkadot ecosystem:\n\n- **Light clients**: Lightweight solutions for interacting with the network without running full nodes.\n- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\\_blank} and [PAPI](/reference/tools/papi/){target=\\_blank} for building applications.\n- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\\_blank} and other Rust-based libraries for SDK development.\n- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\\_blank} for Python developers.\n- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\\_blank}, and [Omninode](/reference/tools/omninode/){target=\\_blank} for smart contract and parachain testing.\n- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\\_blank} for substrate interaction.\n- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\\_blank} for XCM integration and asset transfers."} +{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 6, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 6285, "end_char": 7648, "estimated_token_count": 334, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor detailed exploration of specific areas, proceed to any of the main sections:\n\n
\n\n- Learn **Polkadot Hub**\n\n ---\n\n Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance.\n\n [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/)\n\n- Learn **Parachains**\n\n ---\n\n Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains.\n\n [:octicons-arrow-right-24: Reference](/reference/parachains/)\n\n- Learn **On-Chain Governance**\n\n ---\n\n Explore Polkadot's decentralized governance framework and how to participate in network decision-making.\n\n [:octicons-arrow-right-24: Reference](/reference/governance/)\n\n- Guide **Glossary**\n\n ---\n\n Quick reference for Polkadot-specific terminology and concepts used throughout the documentation.\n\n [:octicons-arrow-right-24: Reference](/reference/glossary/)\n\n- Guide **Tools**\n\n ---\n\n Discover development tools, libraries, and frameworks for building and interacting with Polkadot.\n\n [:octicons-arrow-right-24: Reference](/reference/tools/)\n\n
"} {"page_id": "smart-contracts-connect", "page_title": "Connect to Polkadot", "index": 0, "depth": 2, "title": "Networks Details", "anchor": "networks-details", "start_char": 951, "end_char": 1604, "estimated_token_count": 137, "token_estimator": "heuristic-v1", "text": "## Networks Details\n\nDevelopers can leverage smart contracts across diverse networks, from TestNets to MainNet. This section outlines the network specifications and connection details for each environment.\n\n=== \"Polkadot Hub TestNet\"\n\n Network name\n\n ```text\n Polkadot Hub TestNet\n ```\n\n ---\n\n Currency symbol\n \n ```text\n PAS\n ```\n\n ---\n \n Chain ID\n \n ```text\n 420420422\n ```\n\n ---\n \n RPC URL\n \n ```text\n https://testnet-passet-hub-eth-rpc.polkadot.io\n ```\n\n ---\n \n Block explorer URL\n \n ```text\n https://blockscout-passet-hub.parity-testnet.parity.io/\n ```"} {"page_id": "smart-contracts-connect", "page_title": "Connect to Polkadot", "index": 1, "depth": 2, "title": "Test Tokens", "anchor": "test-tokens", "start_char": 1604, "end_char": 2618, "estimated_token_count": 233, "token_estimator": "heuristic-v1", "text": "## Test Tokens\n\nYou will need testnet tokens to perform transactions and engage with smart contracts on any chain. Here's how to obtain Paseo (PAS) tokens for testing purposes:\n\n1. Navigate to the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank}. If the desired network is not already selected, choose it from the Network drop-down.\n\n2. Copy your address linked to the TestNet and paste it into the designated field.\n\n ![](/images/smart-contracts/connect/connect-to-polkadot-01.webp)\n\n3. Click the **Get Some PASs** button to request free test PAS tokens. These tokens will be sent to your wallet shortly.\n\n ![](/images/smart-contracts/connect/connect-to-polkadot-02.webp)\n\nNow that you have obtained PAS tokens in your wallet, you’re ready to deploy and interact with smart contracts on Polkadot Hub TestNet! These tokens will allow you to pay for gas fees when executing transactions, deploying contracts, and testing your dApp functionality in a secure testnet environment."} {"page_id": "smart-contracts-connect", "page_title": "Connect to Polkadot", "index": 2, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 2618, "end_char": 3459, "estimated_token_count": 188, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor your next steps, explore the various smart contract guides demonstrating how to use and integrate different tools and development environments into your workflow.\n\n
\n\n- Guide __Deploy your first contract with Remix__\n\n ---\n\n Explore the smart contract development and deployment process on Polkadot Hub using the Remix IDE.\n\n [:octicons-arrow-right-24: Build with Remix IDE](/smart-contracts/dev-environments/remix/get-started/)\n\n- Guide __Interact with the blockchain with viem__\n\n ---\n\n Use viem for interacting with Ethereum-compatible chains, to deploy and interact with smart contracts on Polkadot Hub.\n\n [:octicons-arrow-right-24: Build with viem](/smart-contracts/libraries/viem/)\n\n
"} @@ -975,34 +982,18 @@ {"page_id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", "page_title": "Deploy an NFT to Polkadot Hub with Remix", "index": 4, "depth": 2, "title": "Compile", "anchor": "compile", "start_char": 2209, "end_char": 2528, "estimated_token_count": 88, "token_estimator": "heuristic-v1", "text": "## Compile\n\n1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar).\n2. Click **Compile MyNFT.sol** or press `Ctrl+S`.\n\n![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-02.webp)\n\nCompilation errors and warnings appear in the terminal panel at the bottom of the screen."} {"page_id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", "page_title": "Deploy an NFT to Polkadot Hub with Remix", "index": 5, "depth": 2, "title": "Deploy", "anchor": "deploy", "start_char": 2528, "end_char": 3157, "estimated_token_count": 163, "token_estimator": "heuristic-v1", "text": "## Deploy\n\n1. Navigate to the **Deploy & Run Transactions** tab.\n2. Click the **Environment** dropdown, select **Browser Extension**, and click on **Injected Provider - MetaMask**.\n\n ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-03.webp)\n\n3. In the deploy section, enter the initial owner address in the constructor parameter field.\n4. Click **Deploy**.\n\n ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-04.webp)\n\n5. Approve the transaction in your MetaMask wallet.\n\nYour deployed contract will appear in the **Deployed Contracts** section, ready for interaction."} {"page_id": "smart-contracts-cookbook-smart-contracts-deploy-nft-remix", "page_title": "Deploy an NFT to Polkadot Hub with Remix", "index": 6, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 3157, "end_char": 3754, "estimated_token_count": 163, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
\n\n- Guide __Verify Your Contract__\n\n ---\n\n Now that you've deployed an NFT contract, learn how to verify it with Remix.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/verify-a-contract/)\n\n- Guide __Deploy an ERC-20__\n\n ---\n\n Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Remix.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/)\n\n
"} -{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 0, "depth": 2, "title": "Get Tokens from the Faucet", "anchor": "get-tokens-from-the-faucet", "start_char": 222, "end_char": 521, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Get Tokens from the Faucet\n\n| Title | Difficulty | Tools | Description |\n|-------|:----------:|-------|-------------|\n| [Faucet](/smart-contracts/faucet) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. |"} -{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 1, "depth": 2, "title": "EVM/PVM Smart Contracts", "anchor": "evmpvm-smart-contracts", "start_char": 521, "end_char": 1227, "estimated_token_count": 193, "token_estimator": "heuristic-v1", "text": "## EVM/PVM Smart Contracts\n\n| Title | Difficulty | Tools | Description |\n|-------|:----------:|-------|-------------|\n| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. |\n| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. |"} -{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 2, "depth": 2, "title": "Port Ethereum DApps", "anchor": "port-ethereum-dapps", "start_char": 1227, "end_char": 1586, "estimated_token_count": 114, "token_estimator": "heuristic-v1", "text": "## Port Ethereum DApps\n\n| Title | Difficulty | Tools | Description |\n|-------|:----------:|-------|-------------|\n| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. |"} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 0, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 182, "end_char": 918, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "## Overview\n\nFoundry is a fast, modular, and extensible toolkit for Ethereum application development written in Rust. It provides a suite of command-line tools, including `forge` for compiling, testing, and deploying smart contracts and `cast` for interacting with blockchains.\n\n[`foundry-polkadot`](https://github.com/paritytech/foundry-polkadot/){target=\\_blank} is an adaptation explicitly engineered for the Polkadot Hub, tailored for developers already familiar with Foundry who seek to leverage its capabilities within the Polkadot ecosystem. Additionally, this guide offers detailed information on the `forge` and `cast` commands supported within `foundry-polkadot`, complete with simple, runnable examples for quick reference."} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 1, "depth": 2, "title": "Installation", "anchor": "installation", "start_char": 918, "end_char": 1764, "estimated_token_count": 175, "token_estimator": "heuristic-v1", "text": "## Installation\n\nThe installation process is tailored for the Polkadot variant:\n\n- `foundry-polkadot` is installed via `foundryup-polkadot`, its dedicated installer. To get started, open your terminal and execute:\n\n ```bash\n curl -L https://raw.githubusercontent.com/paritytech/foundry-polkadot/refs/heads/master/foundryup/install | bash\n ```\n\n This command starts the installation of `foundryup-polkadot`. After installation, run the following command to download the precompiled `foundry-polkadot` binaries:\n\n ```bash\n foundryup-polkadot\n ```\n\n This command will install the `forge` and `cast` binaries, which are explained below. Windows users must use a Unix-like terminal environment such as Git BASH or Windows Subsystem for Linux (WSL), as PowerShell and Command Prompt are not currently supported by `foundryup`."} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 2, "depth": 2, "title": "Compiler Integration", "anchor": "compiler-integration", "start_char": 1764, "end_char": 3194, "estimated_token_count": 317, "token_estimator": "heuristic-v1", "text": "## Compiler Integration\n\nA core divergence lies in the underlying Solidity compiler.\n\n- `foundry` is built to interface with the `solc` compiler, which targets Ethereum's Ethereum Virtual Machine (EVM).\n- `foundry-polkadot`, in contrast, introduces and primarily utilizes the `resolc` compiler to compile down Solidity contracts into PolkaVM bytecode. \n\n - **Command-Line Flag**: For commands that involve compilation (e.g., `forge build`), you can use the `--resolc` flag to enable `resolc` compilation. For example:\n\n ```bash\n forge build --resolc\n ```\n\n This command instructs Forge to use `resolc` instead of `solc`, generating bytecode compatible with PolkaVM.\n\n - **Configuration File**: Alternatively, you can configure `resolc` usage in the `foundry.toml` file. Add the following:\n\n ```toml\n [profile.default.resolc]\n resolc_compile = true\n ```\n\n Setting `resolc_compile = false` reverts to using `solc`, ensuring compatibility with Ethereum projects. By default, `foundry-polkadot` uses `solc` unless `resolc` is explicitly enabled. `resolc` also exposes specific options for fine-tuning the compilation process, such as `--use-resolc ` for specifying a compiler version or path, `-O, --resolc-optimizer-mode ` for setting optimization levels, and `--heap-size ` and `--stack-size ` for configuring contract memory."} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 3, "depth": 2, "title": "Command-Line Interface (CLI)", "anchor": "command-line-interface-cli", "start_char": 3194, "end_char": 3571, "estimated_token_count": 85, "token_estimator": "heuristic-v1", "text": "## Command-Line Interface (CLI)\n\n`foundry-polkadot` preserves the familiar `forge` and `cast` subcommand structure. However, it's crucial to note that commands which involve compilation (such as `create`, `bind`, `build`, and `inspect`) will yield different output when `resolc` is utilized, as the generated bytecode is specifically designed for PolkaVM rather than the EVM."} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 4, "depth": 2, "title": "Unsupported or Modified Features", "anchor": "unsupported-or-modified-features", "start_char": 3571, "end_char": 4537, "estimated_token_count": 189, "token_estimator": "heuristic-v1", "text": "## Unsupported or Modified Features\n\nNot all functionalities from the original Foundry are present or behave identically in `foundry-polkadot`:\n\n- **Currently unsupported**:\n - Compilation of Yul code is not yet supported.\n - Support for factory contracts deployment is a known issue that is currently unresolved.\n- **Broader feature limitations**: Integration with `Anvil` and `Chisel` (Foundry's local blockchain and EVM toolkit, respectively) is not available. This limitation directly impacts the support for several key commands, including `forge test` for running tests, `forge snapshot` for creating blockchain state snapshots, and `forge script` for complex deployment and interaction scripts.\n- **Modified feature**: The most notable modification is in the **compilation output**. When ``resolc`` is employed, the resulting bytecode will fundamentally differ from that generated by ``solc``, reflecting PolkaVM's distinct architectural requirements."} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 5, "depth": 2, "title": "Set up a Project", "anchor": "set-up-a-project", "start_char": 4537, "end_char": 5517, "estimated_token_count": 223, "token_estimator": "heuristic-v1", "text": "## Set up a Project\n\nInitialize a new project using `forge init`:\n\n```bash\nforge init my-polkadot-project\ncd my-polkadot-project\n```\n\nThis command creates a complete project structure with the following components:\n\n- **`src/`**: Contains the Solidity smart contracts (includes a sample `Counter.sol` contract by default).\n- **`lib/`**: Houses external dependencies and libraries (`forge-std` testing library is included).\n- **`script/`**: Stores deployment and interaction scripts (includes `Counter.s.sol` deployment script by default).\n- **`test/`**: Contains your contract tests (includes `Counter.t.sol` test file by default).\n- **`foundry.toml`**: Main configuration file for compiler settings, network configurations, and project preferences.\n\nThe default project includes a simple `Counter` contract that demonstrates basic state management through increment and decrement functions, along with corresponding tests and deployment scripts to help you get started quickly."} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 6, "depth": 2, "title": "Compile a Project", "anchor": "compile-a-project", "start_char": 5517, "end_char": 6260, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "## Compile a Project\n\nCompile contracts using `forge build`:\n\n```bash\nforge build --resolc\n```\n\n!!!note \n You can still use `forge build` for compiling to regular EVM bytecode.\n\nPolkaVM bytecode starts with `0x505` prefix. Inspect compiled artifacts with:\n\n```bash\nforge inspect Counter bytecode --resolc\n```\n\nIf successful, you will see the following output:\n\n
\n forge inspect Counter bytecode --resolc\n 0x50564d00008213000000000000010700c13000c0008004808f08000000000e0000001c0000002a0000003500000040000000520000005d00000063616c6c5f646174615f636f707963616c6c5f646174615f6c6f616463616c6c5f646174615f73697a65676574...\n
"} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 7, "depth": 2, "title": "Deploy a Contract", "anchor": "deploy-a-contract", "start_char": 6260, "end_char": 7390, "estimated_token_count": 329, "token_estimator": "heuristic-v1", "text": "## Deploy a Contract\n\nDeploy contracts using `forge create`:\n\n```bash\nforge create Counter \\\n --rpc-url \\\n --private-key \\\n --resolc\n```\n\nIf the operation completes successfully, you'll see the following output (for example, to deploy to the Passet Hub chain):\n\n
\n forge create Counter \\n   --rpc-url https://testnet-passet-hub-eth-rpc.polkadot.io \\n   --private-key <INSERT_PRIVATE_KEY> \\n   --resolc\n
\n [:] Compiling...\n Compiler run successful!\n
\n\nFor contracts with constructor arguments:\n\n```bash\nforge create MyToken \\\n --rpc-url \\\n --private-key \\\n --constructor-args \"MyToken\" \"MTK\" 1000000 \\\n --resolc\n```\n\n!!! note \"Network Compatibility\"\n Use the `--resolc` flag when deploying to PolkaVM-compatible networks. Omit it for Ethereum-compatible networks."} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 8, "depth": 2, "title": "Supported `foundry-polkadot` Commands", "anchor": "supported-foundry-polkadot-commands", "start_char": 7390, "end_char": 7544, "estimated_token_count": 33, "token_estimator": "heuristic-v1", "text": "## Supported `foundry-polkadot` Commands\n\nThis section provides a detailed breakdown of the `forge` and `cast` commands supported in `foundry-polkadot`."} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 9, "depth": 3, "title": "Forge Commands", "anchor": "forge-commands", "start_char": 7544, "end_char": 13032, "estimated_token_count": 1502, "token_estimator": "heuristic-v1", "text": "### Forge Commands\n\n- **`init`**:\n - **Command**: `forge init `.\n - **Description**: Initializes a new Foundry project in the current directory, setting up the basic project structure and installing standard libraries.\n\n- **`bind`**:\n - **Command**: `forge bind [--resolc]`.\n - **Description**: Generates type-safe Rust bindings for your Solidity contracts. Use `--resolc` to ensure compilation with the `resolc` compiler for PolkaVM compatibility.\n\n- **`bind-json`**:\n - **Command**: `forge bind-json [--resolc]`.\n - **Description**: Generates JSON bindings for your Solidity contracts. Use `--resolc` for `resolc`-based compilation.\n\n- **`build`**:\n - **Command**: `forge build [--resolc]`.\n - **Description**: Compiles all Solidity contracts in your project. Specify `--resolc` to compile for PolkaVM.\n\n- **`cache clean`**:\n - **Command**: `forge cache clean`.\n - **Description**: Clears the Foundry cache directory.\n\n- **`cache ls`**:\n - **Command**: `forge cache ls`.\n - **Description**: Lists the contents of the Foundry cache.\n\n- **`clean`**:\n - **Command**: `forge clean`.\n - **Description**: Removes all build artifacts from the project's `out` directory.\n\n- **`compiler resolve`**:\n - **Command**: `forge compiler resolve [--resolc]`.\n - **Description**: Resolves and displays the versions of Solidity compilers Foundry is using. Use `--resolc` to also check for `resolc`.\n\n- **`config`**:\n - **Command**: `forge config`.\n - **Description**: Displays the current Foundry project configuration, including settings from `foundry.toml`.\n\n- **`create`**:\n - **Command**: `forge create [OPTIONS] `.\n - **Required Parameters**: `` (the name of the contract to deploy).\n - **Description**: Deploys a new contract to a specified blockchain network. The `--resolc` flag ensures it's compiled for PolkaVM. You'll typically need to provide an RPC URL, a private key for the deployer account, and potentially constructor arguments.\n\n- **`doc`**:\n - **Command**: `forge doc`.\n - **Description**: Generates documentation for your Solidity contracts.\n\n- **`flatten`**:\n - **Command**: `forge flatten [OPTIONS] `.\n - **Required Parameters**: `` (the path to the Solidity file).\n - **Description**: Combines all imports of a Solidity file into a single file, useful for deployment or verification.\n\n- **`fmt`**:\n - **Command**: `forge fmt`.\n - **Description**: Formats Solidity code according to a predefined style.\n\n- **`geiger`**:\n - **Command**: `forge geiger `.\n - **Required Parameters**: `` (the path to the Solidity file).\n - **Description**: Analyzes Solidity code for potential security vulnerabilities and gas inefficiencies.\n\n- **`generate test`**:\n - **Command**: `forge generate test --contract-name `.\n - **Required Parameters**: `--contract-name ` (the name of the contract for which to generate a test).\n - **Description**: Creates a new test file with boilerplate code for a specified contract.\n\n- **`generate-fig-spec`**:\n - **Command**: `forge generate-fig-spec`.\n - **Description**: Generates a Fig specification for CLI autocompletion tools.\n\n- **`inspect`**:\n - **Command**: `forge inspect [--resolc]`.\n - **Required Parameters**: `` (the contract to inspect), `` (e.g., `bytecode`, `abi`, `methods`, `events`).\n - **Description**: Displays various artifacts of a compiled contract. Use `--resolc` to inspect `resolc`-compiled artifacts; the bytecode will start with `0x505`.\n\n- **`install`**:\n - **Command**: `forge install `.\n - **Description**: Installs a Solidity library or dependency from a Git repository.\n\n- **`update`**:\n - **Command**: `forge update []`.\n - **Description**: Updates installed dependencies. If a repository is specified, only that one is updated.\n\n- **`remappings`**:\n - **Command**: `forge remappings`.\n - **Description**: Lists the currently configured Solidity compiler remappings.\n\n- **`remove`**:\n - **Command**: `forge remove `.\n - **Description**: Removes an installed Solidity dependency. Use `--force` to remove without confirmation.\n\n- **`selectors upload`**:\n - **Command**: `forge selectors upload [--all]`.\n - **Description**: Uploads function selectors from compiled contracts to OpenChain. Use `--all` to upload for all contracts.\n\n- **`selectors list`**:\n - **Command**: `forge selectors list`.\n - **Description**: Lists all known function selectors for contracts in the project.\n\n- **`selectors find`**:\n - **Command**: `forge selectors find `.\n - **Description**: Searches for a function signature given its 4-byte selector.\n\n- **`selectors cache`**:\n - **Command**: `forge selectors cache`.\n - **Description**: Caches function selectors for faster lookup.\n\n- **`tree`**:\n - **Command**: `forge tree`.\n - **Description**: Displays the dependency tree of your Solidity contracts.\n\n!!!warning \"Non-working Commands\"\n\n Consider that some foundry commands are not yet supported in `foundry-polkadot`:\n\n - **`clone`**: This command is not supported in `foundry-polkadot`.\n - **`coverage`**: Code coverage analysis is not supported.\n - **`snapshot`**: Creating blockchain state snapshots is not supported.\n - **`test`**: Running Solidity tests is not supported."} -{"page_id": "smart-contracts-dev-environments-foundry-get-started", "page_title": "Use Foundry with Polkadot Hub", "index": 10, "depth": 3, "title": "Cast Commands", "anchor": "cast-commands", "start_char": 13032, "end_char": 23398, "estimated_token_count": 3084, "token_estimator": "heuristic-v1", "text": "### Cast Commands\n\n- **`4byte`**:\n - **Command**: `cast 4byte [OPTIONS] [TOPIC_0]`.\n - **Description**: Decodes a 4-byte function selector into its human-readable function signature.\n\n- **`4byte-event`**:\n - **Command**: `cast 4byte-event [OPTIONS] [TOPIC_0]`.\n - **Description**: Decodes a 4-byte event topic into its human-readable event signature.\n\n- **`abi-encode`**:\n - **Command**: `cast abi-encode [ARGS]...`.\n - **Required Parameters**: `` (the function signature), `[ARGS]` (arguments to encode).\n - **Description**: ABI-encodes function arguments according to a given signature.\n\n- **`address-zero`**:\n - **Command**: `cast address-zero`.\n - **Description**: Returns the zero address (0x00...00).\n\n- **`age`**:\n - **Command**: `cast age [OPTIONS] [BLOCK]`.\n - **Description**: Converts a block number or tag (e.g., `latest`) into its timestamp.\n\n- **`balance`**:\n - **Command**: `cast balance [OPTIONS] `.\n - **Required Parameters**: `` (the address to check).\n - **Description**: Retrieves the native token balance of a given address on the specified RPC network.\n\n- **`base-fee`**:\n - **Command**: `cast base-fee [OPTIONS] [BLOCK]`.\n - **Description**: Retrieves the base fee per gas for a specific block (defaults to `latest`).\n\n- **`block`**:\n - **Command**: `cast block [OPTIONS] [BLOCK]`.\n - **Description**: Retrieves comprehensive details about a specific block (defaults to `latest`).\n\n- **`block-number`**:\n - **Command**: `cast block-number [OPTIONS] [BLOCK]`.\n - **Description**: Retrieves the number of the latest or a specified block.\n\n- **`call`**:\n - **Command**: `cast call [OPTIONS] [ARGS]...`.\n - **Description**: Executes a read-only (constant) function call on a contract. No transaction is sent to the network.\n\n- **`chain`**:\n - **Command**: `cast chain [OPTIONS]`.\n - **Description**: Displays the human-readable name of the connected blockchain.\n\n- **`chain-id`**:\n - **Command**: `cast chain-id [OPTIONS]`.\n - **Description**: Displays the chain ID of the connected blockchain.\n\n- **`client`**:\n - **Command**: `cast client [OPTIONS]`.\n - **Description**: Retrieves information about the connected RPC client (node software).\n\n- **`code`**:\n - **Command**: `cast code [OPTIONS] `.\n - **Required Parameters**: `` (the contract address).\n - **Description**: Retrieves the bytecode deployed at a given contract address.\n\n- **`codesize`**:\n - **Command**: `cast codesize [OPTIONS] `.\n - **Required Parameters**: `` (the contract address).\n - **Description**: Retrieves the size of the bytecode deployed at a given contract address.\n\n- **`compute-address`**:\n - **Command**: `cast compute-address [OPTIONS] `.\n - **Required Parameters**: `` (the deployer's address).\n - **Description**: Computes the predicted contract address based on the deployer's address and nonce.\n\n- **`decode-abi`**:\n - **Command**: `cast decode-abi `.\n - **Required Parameters**: `` (the function signature), `` (the ABI-encoded data).\n - **Description**: Decodes ABI-encoded output data from a contract call given its signature.\n\n- **`decode-calldata`**:\n - **Command**: `cast decode-calldata `.\n - **Required Parameters**: `` (the function signature), `` (the raw calldata).\n - **Description**: Decodes raw calldata into human-readable arguments using a function signature.\n\n- **`decode-error`**:\n - **Command**: `cast decode-error [--sig ]`.\n - **Required Parameters**: `` (the error data).\n - **Description**: Decodes a custom error message from a transaction revert. You may need to provide the error signature.\n\n- **`decode-event`**:\n - **Command**: `cast decode-event [--sig ]`.\n - **Required Parameters**: `` (the event data).\n - **Description**: Decodes event data from a transaction log.\n\n- **`estimate`**:\n - **Command**: `cast estimate [OPTIONS] [TO] [SIG] [ARGS]...`.\n - **Required Parameters**: `[TO]` (the recipient address or contract), `[SIG]` (function signature), `[ARGS]` (arguments).\n - **Description**: Estimates the gas cost for a transaction or function call.\n\n- **`find-block`**:\n - **Command**: `cast find-block [OPTIONS] `.\n - **Required Parameters**: `` (a Unix timestamp).\n - **Description**: Finds the closest block number to a given Unix timestamp.\n\n- **`gas-price`**:\n - **Command**: `cast gas-price [OPTIONS]`.\n - **Description**: Retrieves the current average gas price on the network.\n\n- **`generate-fig-spec`**:\n - **Command**: `cast generate-fig-spec`.\n - **Description**: Generates a Fig specification for CLI autocompletion.\n\n- **`index-string`**:\n - **Command**: `cast index-string `.\n - **Description**: Computes the Keccak-256 hash of a string, useful for event topics.\n\n- **`index-erc7201`**:\n - **Command**: `cast index-erc7201 `.\n - **Description**: Computes the hash for an ERC-7201 identifier.\n\n- **`logs`**:\n - **Command**: `cast logs [OPTIONS] [SIG_OR_TOPIC] [TOPICS_OR_ARGS]...`.\n - **Required Parameters**: `[SIG_OR_TOPIC]` (a signature or topic hash).\n - **Description**: Filters and displays event logs from transactions.\n\n- **`max-int`**:\n - **Command**: `cast max-int`.\n - **Description**: Displays the maximum value for a signed 256-bit integer.\n\n- **`max-uint`**:\n - **Command**: `cast max-uint`.\n - **Description**: Displays the maximum value for an unsigned 256-bit integer.\n\n- **`min-int`**:\n - **Command**: `cast min-int`.\n - **Description**: Displays the minimum value for a signed 256-bit integer.\n\n- **`mktx`**:\n - **Command**: `cast mktx [OPTIONS] [TO] [SIG] [ARGS]...`.\n - **Required Parameters**: `[TO]` (the recipient address or contract).\n - **Description**: Creates a raw, signed transaction that can be broadcast later.\n\n- **`decode-transaction`**:\n - **Command**: `cast decode-transaction [OPTIONS] [TX]`.\n - **Required Parameters**: `[TX]` (the raw transaction hex string).\n - **Description**: Decodes a raw transaction hex string into its human-readable components.\n\n- **`namehash increment`**:\n - **Command**: `cast namehash `.\n - **Description**: Computes the ENS (Ethereum Name Service) namehash for a given name.\n\n- **`nonce`**:\n - **Command**: `cast nonce [OPTIONS] `.\n - **Required Parameters**: `` (the address to check).\n - **Description**: Retrieves the transaction count (nonce) for a given address.\n\n- **`parse-bytes32-address`**:\n - **Command**: `cast parse-bytes32-address `.\n - **Description**: Parses a 32-byte hex string (e.g., from `bytes32`) into an Ethereum address.\n\n- **`parse-bytes32-string`**:\n - **Command**: `cast parse-bytes32-string `.\n - **Description**: Parses a 32-byte hex string into a human-readable string.\n\n- **`parse-units`**:\n - **Command**: `cast parse-units [UNIT]`.\n - **Description**: Converts a human-readable amount into its smallest unit (e.g., Ether to Wei). Defaults to `ether`.\n\n- **`pretty-calldata`**:\n - **Command**: `cast pretty-calldata [OPTIONS] `.\n - **Required Parameters**: `` (the calldata hex string).\n - **Description**: Attempts to pretty-print and decode a raw calldata string into possible function calls.\n\n- **`publish`**:\n - **Command**: `cast publish [OPTIONS] `.\n - **Description**: Broadcasts a raw, signed transaction to the network.\n\n- **`receipt`**:\n - **Command**: `cast receipt [OPTIONS] `.\n - **Description**: Retrieves the transaction receipt for a given transaction hash, including status, gas usage, and logs.\n\n- **`rpc`**:\n - **Command**: `cast rpc [OPTIONS] [PARAMS]...`.\n - **Required Parameters**: `` (the RPC method to call), `[PARAMS]` (parameters for the method).\n - **Description**: Makes a direct RPC call to the connected blockchain node.\n\n- **`send`**:\n - **Command**: `cast send [OPTIONS] [ARGS]...`.\n - **Required Parameters**: `` (the recipient address or contract).\n - **Description**: Sends a transaction to a contract or address, executing a function or transferring value.\n\n- **`sig`**:\n - **Command**: `cast sig `.\n - **Required Parameters**: `` (the full function signature string).\n - **Description**: Computes the 4-byte function selector for a given function signature.\n\n- **`sig-event`**:\n - **Command**: `cast sig-event `.\n - **Required Parameters**: `` (the full event signature string).\n - **Description**: Computes the Keccak-256 hash (topic) for a given event signature.\n\n- **`storage`**:\n - **Command**: `cast storage [OPTIONS]
[SLOT]`.\n - **Required Parameters**: `
` (the contract address).\n - **Description**: Retrieves the raw value stored at a specific storage slot of a contract.\n\n- **`tx`**:\n - **Command**: `cast tx [OPTIONS] `.\n - **Description**: Retrieves comprehensive details about a specific transaction.\n\n- **`upload-signature`**:\n - **Command**: `cast upload-signature [OPTIONS] `.\n - **Required Parameters**: `` (the function or event signature).\n - **Description**: Uploads a function or event signature to the OpenChain registry.\n\n- **`wallet`**:\n - **Command**: `cast wallet new`.\n - **Description**: Generates a new random Ethereum keypair (private key and address).\n\n- **`wallet new-mnemonic`**:\n - **Command**: `cast wallet new-mnemonic`.\n - **Description**: Generates a new BIP-39 mnemonic phrase and derives the first account from it.\n\n- **`wallet address`**:\n - **Command**: `cast wallet address [OPTIONS]`.\n - **Description**: Derives and displays the Ethereum address from a private key or mnemonic (if provided).\n\n!!!warning \"Non-working Commands\"\n\n Consider that some foundry commands are not yet supported in `foundry-polkadot`:\n\n - **`proof`**: This command, used for generating Merkle proofs, is not supported.\n - **`storage-root`**: This command, used for retrieving the storage root of a contract, is not supported."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 0, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 11, "end_char": 506, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "## Overview\n\nBuilding on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer.\n\nHardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit including compilation, local testing nodes, debugging tools, and deployment automation."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 1, "depth": 2, "title": "Hardhat Workflow", "anchor": "hardhat-workflow", "start_char": 506, "end_char": 1247, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "## Hardhat Workflow\n\nFrom the first sketch of a contract to ongoing operations, Hardhat encourages a repeatable cycle: define the functionality you need, scaffold the workspace, write and refine Solidity code, compile it into deployable artifacts, validate behavior with automated tests, deploy confidently to the target network, and keep iterating with scripts that monitor and interact with what you shipped.\n\n```mermaid\nflowchart LR\n plan[Plan Contract]\n scaffold[Scaffold Project]\n develop[Write & Update Contracts]\n compile[Compile Sources]\n test[Run Automated Tests]\n deploy[Deploy to Target Network]\n operate[Interact & Monitor]\n\n plan --> scaffold --> develop --> compile --> test --> deploy --> operate\n```"} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 2, "depth": 2, "title": "Project Anatomy", "anchor": "project-anatomy", "start_char": 1247, "end_char": 1913, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Project Anatomy\n\nA freshly initialized Hardhat project keeps code, configuration, and automation neatly separated:\n\n```\n.\n├── contracts/\n│ └── MyContract.sol\n├── ignition/\n│ └── modules/\n├── scripts/\n│ └── interact.js\n├── test/\n│ └── MyContract.test.js\n└── hardhat.config.js\n```\n\n- `contracts/`: Solidity sources that define your smart contracts.\n- `test/`: Automated tests written in JavaScript or TypeScript.\n- `ignition/`: Deployment modules that orchestrate repeatable rollouts.\n- `scripts/`: Utility scripts for deploying, validating, or interacting with contracts.\n- `hardhat.config.js`: Central configuration for networks, compilers, and tooling."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 3, "depth": 2, "title": "Core Functionalities", "anchor": "core-functionalities", "start_char": 1913, "end_char": 1938, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Core Functionalities"} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 4, "depth": 3, "title": "Project Setup", "anchor": "project-setup", "start_char": 1938, "end_char": 2313, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "### Project Setup\n\nHardhat provides a structured project initialization with organized folders for contracts, tests, deployment scripts, and automation. Scaffold a workspace quickly and keep configuration in a single `hardhat.config.js` file.\n\n- Learn more in the [Install and Configure](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank} guide."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 5, "depth": 3, "title": "Contract Compilation", "anchor": "contract-compilation", "start_char": 2313, "end_char": 2708, "estimated_token_count": 79, "token_estimator": "heuristic-v1", "text": "### Contract Compilation\n\nCompile your Solidity smart contracts with configurable compiler versions and optimization settings. Hardhat captures build artifacts—ABI, bytecode, metadata—so you can deploy or interact with contracts from scripts and frontends.\n\n- Deep dive into compilation in [Compile Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 6, "depth": 3, "title": "Testing Environment", "anchor": "testing-environment", "start_char": 2708, "end_char": 3096, "estimated_token_count": 80, "token_estimator": "heuristic-v1", "text": "### Testing Environment\n\nRun automated tests against a local Hardhat node, simulate transactions, and debug contract behavior before deploying to public networks. The built-in testing stack uses familiar JavaScript tooling such as Mocha and Chai.\n\n- Master testing capabilities in [Test Your Smart Contracts](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 7, "depth": 3, "title": "Deployment", "anchor": "deployment", "start_char": 3096, "end_char": 3424, "estimated_token_count": 66, "token_estimator": "heuristic-v1", "text": "### Deployment\n\nShip your contracts with reusable deployment scripts or Hardhat Ignition modules. Manage credentials securely, target multiple networks, and repeat deployments with confidence.\n\n- Follow deployment steps in [Deploy Smart Contracts](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank}."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 8, "depth": 3, "title": "Contract Interaction", "anchor": "contract-interaction", "start_char": 3424, "end_char": 3738, "estimated_token_count": 67, "token_estimator": "heuristic-v1", "text": "### Contract Interaction\n\nCreate scripts to interact with deployed contracts, read state, execute transactions, and automate maintenance tasks using your generated ABI.\n\n- See practical tips in [Interact with Smart Contracts](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\\_blank}."} -{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 9, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 3738, "end_char": 5817, "estimated_token_count": 518, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nReady to explore the specifics? Dive into these guides to continue your Hardhat journey:\n\n
\n\n- Guide __Install and Configure Hardhat__\n\n ---\n\n Initialize your workspace and adjust project settings for this toolchain.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank}\n\n- Guide __Compile Smart Contracts__\n\n ---\n\n Configure compiler options and generate deployable artifacts.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}\n\n- Guide __Test Your Smart Contracts__\n\n ---\n\n Build automated tests and run them against a local node.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}\n\n- Guide __Deploy Smart Contracts__\n\n ---\n\n Roll out contracts to local, test, or production networks with repeatable scripts.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank}\n\n- Guide __Interact with Smart Contracts__\n\n ---\n\n Script on-chain interactions and automate maintenance tasks.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\\_blank}\n\n- External __Hardhat Documentation__\n\n ---\n\n Explore Hardhat's official documentation for advanced features and best practices.\n\n [:octicons-arrow-right-24: Learn More](https://hardhat.org/docs){target=\\_blank}\n\n- External __OpenZeppelin Contracts__\n\n ---\n\n Use prebuilt, audited contract templates to bootstrap your projects.\n\n [:octicons-arrow-right-24: Explore](https://www.openzeppelin.com/solidity-contracts){target=\\_blank}\n\n
"} -{"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 196, "end_char": 699, "estimated_token_count": 97, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nA local development node provides an isolated blockchain environment where you can deploy, test, and debug smart contracts without incurring network fees or waiting for block confirmations. This guide demonstrates how to set up a local Polkadot SDK-based node with smart contract capabilities.\n\nBy the end of this guide, you'll have:\n\n- A running node with smart contract support.\n- An ETH-RPC adapter for Ethereum-compatible tooling integration accessible at `http://localhost:8545`."} -{"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 699, "end_char": 1028, "estimated_token_count": 76, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore getting started, ensure you have done the following:\n\n- Completed the [Install Polkadot SDK Dependencies](/parachains/install-polkadot-sdk/){target=\\_blank} guide and successfully installed [Rust](https://rust-lang.org/){target=\\_blank} and the required packages to set up your development environment."} -{"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 2, "depth": 2, "title": "Install the Revive Dev Node and ETH-RPC Adapter", "anchor": "install-the-revive-dev-node-and-eth-rpc-adapter", "start_char": 1028, "end_char": 2561, "estimated_token_count": 343, "token_estimator": "heuristic-v1", "text": "## Install the Revive Dev Node and ETH-RPC Adapter\n\nThe Polkadot SDK repository contains both the [Revive Dev node](https://github.com/paritytech/polkadot-sdk/tree/8e2b6f742a38bb13688e12abacded0aab2dbbb23/substrate/frame/revive/dev-node){target=\\_blank} implementation and the [ETH-RPC adapter](https://github.com/paritytech/polkadot-sdk/tree/8e2b6f742a38bb13688e12abacded0aab2dbbb23/substrate/frame/revive/rpc){target=\\_blank} required for Ethereum compatibility. Start by cloning the repository and navigating to the project directory:\n\n```bash\ngit clone https://github.com/paritytech/polkadot-sdk.git\ncd polkadot-sdk\ngit checkout 8e2b6f742a38bb13688e12abacded0aab2dbbb23\n```\n\nNext, you need to compile the two essential components for your development environment. The Substrate node provides the core blockchain runtime with smart contract support, while the ETH-RPC adapter enables Ethereum JSON-RPC compatibility for existing tooling:\n\n```bash\ncargo build -p revive-dev-node --bin revive-dev-node --release\ncargo build -p pallet-revive-eth-rpc --bin eth-rpc --release\n```\n\nThe compilation process may take some time depending on your system specifications, potentially up to 30 minutes. Release builds are optimized for performance but take longer to compile than debug builds. After successful compilation, you can verify the binaries are available in the `target/release` directory:\n\n- **Revive Dev node path**: `polkadot-sdk/target/release/revive-dev-node`\n- **ETH-RPC adapter path**: `polkadot-sdk/target/release/eth-rpc`"} -{"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 3, "depth": 2, "title": "Run the Local Node", "anchor": "run-the-local-node", "start_char": 2561, "end_char": 9052, "estimated_token_count": 1912, "token_estimator": "heuristic-v1", "text": "## Run the Local Node\n\nWith the binaries compiled, you can now start your local development environment. The setup requires running two processes.\n\nStart the node first, which will initialize a local blockchain with the `dev` chain specification. This configuration includes `pallet-revive` for smart contract functionality and uses pre-funded development accounts for testing:\n\n```bash\n./target/release/revive-dev-node --dev\n```\n\nThe node will begin producing blocks immediately and display initialization logs:\n\n
\n ./target/release/revive-dev-node --dev\n
\n 2025-05-29 10:42:35 Substrate Node\n 2025-05-29 10:42:35 ✌️ version 3.0.0-dev-38b7581fc04\n 2025-05-29 10:42:35 ❤️ by Parity Technologies <admin@parity.io>, 2017-2025\n 2025-05-29 10:42:35 📋 Chain specification: Development\n 2025-05-29 10:42:35 🏷 Node name: annoyed-aunt-3163\n 2025-05-29 10:42:35 👤 Role: AUTHORITY\n 2025-05-29 10:42:35 💾 Database: RocksDb at /var/folders/x0/xl_kjddj3ql3bx7752yr09hc0000gn/T/substrate2P85EF/chains/dev/db/full\n 2025-05-29 10:42:40 🔨 Initializing Genesis block/state (state: 0xfc05…482e, header-hash: 0x1ae1…b8b4)\n 2025-05-29 10:42:40 Creating transaction pool txpool_type=SingleState ready=Limit { count: 8192, total_bytes: 20971520 } future=Limit { count: 819, total_bytes: 2097152 }\n 2025-05-29 10:42:40 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.\n 2025-05-29 10:42:40 👶 Creating empty BABE epoch changes on what appears to be first startup.\n 2025-05-29 10:42:40 Using default protocol ID \"sup\" because none is configured in the chain specs\n 2025-05-29 10:42:40 🏷 Local node identity is: 12D3KooWAH8fgJv3hce7Yv4yKG4YXQiRqESFu6755DBnfZQU8Znm\n 2025-05-29 10:42:40 Running libp2p network backend\n 2025-05-29 10:42:40 local_peer_id=12D3KooWAH8fgJv3hce7Yv4yKG4YXQiRqESFu6755DBnfZQU8Znm\n 2025-05-29 10:42:40 💻 Operating system: macos\n 2025-05-29 10:42:40 💻 CPU architecture: aarch64\n 2025-05-29 10:42:40 📦 Highest known block at #0\n 2025-05-29 10:42:40 Error binding to '127.0.0.1:9615': Os { code: 48, kind: AddrInUse, message: \"Address already in use\" }\n 2025-05-29 10:42:40 Running JSON-RPC server: addr=127.0.0.1:63333,[::1]:63334\n 2025-05-29 10:42:40 🏁 CPU single core score: 1.24 GiBs, parallelism score: 1.08 GiBs with expected cores: 8\n 2025-05-29 10:42:40 🏁 Memory score: 49.42 GiBs\n 2025-05-29 10:42:40 🏁 Disk score (seq. writes): 1.91 GiBs\n 2025-05-29 10:42:40 🏁 Disk score (rand. writes): 529.02 MiBs\n 2025-05-29 10:42:40 👶 Starting BABE Authorship worker\n 2025-05-29 10:42:40 🥩 BEEFY gadget waiting for BEEFY pallet to become available...\n 2025-05-29 10:42:40 Failed to trigger bootstrap: No known peers.\n 2025-05-29 10:42:42 🙌 Starting consensus session on top of parent 0x1ae19030b13592b5e6fd326f26efc7b31a4f588303d348ef89ae9ebca613b8b4 (#0)\n 2025-05-29 10:42:42 🎁 Prepared block for proposing at 1 (5 ms) hash: 0xe046f22307fba58a3bd0cc21b1a057843d4342da8876fd44aba206f124528df0; parent_hash: 0x1ae1…b8b4; end: NoMoreTransactions; extrinsics_count: 2\n 2025-05-29 10:42:42 🔖 Pre-sealed block for proposal at 1. Hash now 0xa88d36087e7bf8ee59c1b17e0003092accf131ff8353a620410d7283657ce36a, previously 0xe046f22307fba58a3bd0cc21b1a057843d4342da8876fd44aba206f124528df0.\n 2025-05-29 10:42:42 👶 New epoch 0 launching at block 0xa88d…e36a (block slot 582842054 >= start slot 582842054).\n 2025-05-29 10:42:42 👶 Next epoch starts at slot 582842254\n 2025-05-29 10:42:42 🏆 Imported #1 (0x1ae1…b8b4 → 0xa88d…e36a)\n
\n\nFor debugging purposes or to monitor low-level operations, you can enable detailed logging by setting environment variables before running the command:\n\n```bash\nRUST_LOG=\"error,evm=debug,sc_rpc_server=info,runtime::revive=debug\" ./target/release/revive-dev-node --dev\n```\n\nOnce the node is running, open a new terminal window and start the ETH-RPC adapter. This component translates Ethereum JSON-RPC calls into Substrate-compatible requests, allowing you to use familiar Ethereum tools like MetaMask, Hardhat, or Ethers.js:\n\n```bash\n./target/release/eth-rpc --dev\n```\n\nYou should see logs indicating that the adapter is ready to accept connections:\n\n
\n ./target/release/eth-rpc --dev\n
\n 2025-05-29 10:48:48 Running in --dev mode, RPC CORS has been disabled.\n 2025-05-29 10:48:48 Running in --dev mode, RPC CORS has been disabled.\n 2025-05-29 10:48:48 🌐 Connecting to node at: ws://127.0.0.1:9944 ...\n 2025-05-29 10:48:48 🌟 Connected to node at: ws://127.0.0.1:9944\n 2025-05-29 10:48:48 💾 Using in-memory database, keeping only 256 blocks in memory\n 2025-05-29 10:48:48 〽️ Prometheus exporter started at 127.0.0.1:9616\n 2025-05-29 10:48:48 Running JSON-RPC server: addr=127.0.0.1:8545,[::1]:8545\n 2025-05-29 10:48:48 🔌 Subscribing to new blocks (BestBlocks)\n 2025-05-29 10:48:48 🔌 Subscribing to new blocks (FinalizedBlocks)\n
\n\nSimilar to the Revive Dev node, you can enable detailed logging for the ETH-RPC adapter to troubleshoot issues:\n\n```bash\nRUST_LOG=\"info,eth-rpc=debug\" ./target/release/eth-rpc --dev\n```\n\nYour local development environment is now active and accessible at `http://localhost:8545`. This endpoint accepts standard Ethereum JSON-RPC requests, enabling seamless integration with existing Ethereum development tools and workflows. \n\nYou can connect wallets, deploy contracts using Remix or Hardhat, and interact with your smart contracts as you would on any Ethereum-compatible network."} +{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 0, "depth": 2, "title": "Get Tokens from the Faucet", "anchor": "get-tokens-from-the-faucet", "start_char": 222, "end_char": 796, "estimated_token_count": 236, "token_estimator": "heuristic-v1", "text": "## Get Tokens from the Faucet\n\n| Title | Difficulty | Tools | Description |\n|------------------------------------|:-----------:|-------|-----------------------------------------------------------------------------------------------------------------------|\n| [Faucet](/smart-contracts/faucet/) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. |"} +{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 1, "depth": 2, "title": "EVM/PVM Smart Contracts", "anchor": "evmpvm-smart-contracts", "start_char": 796, "end_char": 2051, "estimated_token_count": 461, "token_estimator": "heuristic-v1", "text": "## EVM/PVM Smart Contracts\n\n| Title | Difficulty | Tools | Description |\n|---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. |\n| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. |"} +{"page_id": "smart-contracts-cookbook", "page_title": "Smart Contracts Cookbook Index", "index": 2, "depth": 2, "title": "Port Ethereum DApps", "anchor": "port-ethereum-dapps", "start_char": 2051, "end_char": 2815, "estimated_token_count": 317, "token_estimator": "heuristic-v1", "text": "## Port Ethereum DApps\n\n| Title | Difficulty | Tools | Description |\n|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------|\n| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. |"} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 0, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 11, "end_char": 507, "estimated_token_count": 82, "token_estimator": "heuristic-v1", "text": "## Overview\n\nBuilding on Polkadot Hub often starts with a Solidity codebase, and Hardhat keeps that workflow familiar while giving teams repeatable scripts, rich debugging, and CLI automation suited to the network's Ethereum-compatible execution layer.\n\nHardhat is a comprehensive development environment for building, testing, and deploying smart contracts. It provides developers with a complete toolkit, including compilation, local testing nodes, debugging tools, and deployment automation."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 1, "depth": 2, "title": "Hardhat Workflow", "anchor": "hardhat-workflow", "start_char": 507, "end_char": 1248, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "## Hardhat Workflow\n\nFrom the first sketch of a contract to ongoing operations, Hardhat encourages a repeatable cycle: define the functionality you need, scaffold the workspace, write and refine Solidity code, compile it into deployable artifacts, validate behavior with automated tests, deploy confidently to the target network, and keep iterating with scripts that monitor and interact with what you shipped.\n\n```mermaid\nflowchart LR\n plan[Plan Contract]\n scaffold[Scaffold Project]\n develop[Write & Update Contracts]\n compile[Compile Sources]\n test[Run Automated Tests]\n deploy[Deploy to Target Network]\n operate[Interact & Monitor]\n\n plan --> scaffold --> develop --> compile --> test --> deploy --> operate\n```"} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 2, "depth": 2, "title": "Project Anatomy", "anchor": "project-anatomy", "start_char": 1248, "end_char": 1914, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Project Anatomy\n\nA freshly initialized Hardhat project keeps code, configuration, and automation neatly separated:\n\n```\n.\n├── contracts/\n│ └── MyContract.sol\n├── ignition/\n│ └── modules/\n├── scripts/\n│ └── interact.js\n├── test/\n│ └── MyContract.test.js\n└── hardhat.config.js\n```\n\n- `contracts/`: Solidity sources that define your smart contracts.\n- `test/`: Automated tests written in JavaScript or TypeScript.\n- `ignition/`: Deployment modules that orchestrate repeatable rollouts.\n- `scripts/`: Utility scripts for deploying, validating, or interacting with contracts.\n- `hardhat.config.js`: Central configuration for networks, compilers, and tooling."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 3, "depth": 2, "title": "Core Functionalities", "anchor": "core-functionalities", "start_char": 1914, "end_char": 2716, "estimated_token_count": 151, "token_estimator": "heuristic-v1", "text": "## Core Functionalities\n\n- **Project structure**: Organizes contracts, tests, scripts, and configuration into a consistent workspace. Provides a clear folder layout and a single configuration file (`hardhat.config.js`) to manage compilers, networks, and tooling.\n- **Compilation**: Compiles Solidity sources, supports multiple compiler versions, and generates ABI and bytecode artifacts.\n- **Local testing**: Runs tests written in JavaScript or TypeScript against an integrated local network, enabling fast feedback when validating contract behavior.\n- **Task automation**: Automates deployments, maintenance operations, and recurring workflows through custom scripts and Hardhat tasks.\n- **Contract interaction**: Enables reading contract state, sending transactions, and calling contract functions."} +{"page_id": "smart-contracts-dev-environments-hardhat-get-started", "page_title": "Use Hardhat with Polkadot Hub", "index": 4, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 2716, "end_char": 4795, "estimated_token_count": 518, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nReady to explore the specifics? Dive into these guides to continue your Hardhat journey:\n\n
\n\n- Guide __Install and Configure Hardhat__\n\n ---\n\n Initialize your workspace and adjust project settings for this toolchain.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank}\n\n- Guide __Compile Smart Contracts__\n\n ---\n\n Configure compiler options and generate deployable artifacts.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}\n\n- Guide __Test Your Smart Contracts__\n\n ---\n\n Build automated tests and run them against a local node.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank}\n\n- Guide __Deploy Smart Contracts__\n\n ---\n\n Roll out contracts to local, test, or production networks with repeatable scripts.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank}\n\n- Guide __Interact with Smart Contracts__\n\n ---\n\n Script on-chain interactions and automate maintenance tasks.\n\n [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/interact-with-a-contract/){target=\\_blank}\n\n- External __Hardhat Documentation__\n\n ---\n\n Explore Hardhat's official documentation for advanced features and best practices.\n\n [:octicons-arrow-right-24: Learn More](https://hardhat.org/docs){target=\\_blank}\n\n- External __OpenZeppelin Contracts__\n\n ---\n\n Use prebuilt, audited contract templates to bootstrap your projects.\n\n [:octicons-arrow-right-24: Explore](https://www.openzeppelin.com/solidity-contracts){target=\\_blank}\n\n
"} +{"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 26, "end_char": 529, "estimated_token_count": 97, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nA local development node provides an isolated blockchain environment where you can deploy, test, and debug smart contracts without incurring network fees or waiting for block confirmations. This guide demonstrates how to set up a local Polkadot SDK-based node with smart contract capabilities.\n\nBy the end of this guide, you'll have:\n\n- A running node with smart contract support.\n- An ETH-RPC adapter for Ethereum-compatible tooling integration accessible at `http://localhost:8545`."} +{"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 529, "end_char": 858, "estimated_token_count": 76, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore getting started, ensure you have done the following:\n\n- Completed the [Install Polkadot SDK Dependencies](/parachains/install-polkadot-sdk/){target=\\_blank} guide and successfully installed [Rust](https://rust-lang.org/){target=\\_blank} and the required packages to set up your development environment."} +{"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 2, "depth": 2, "title": "Install the Revive Dev Node and ETH-RPC Adapter", "anchor": "install-the-revive-dev-node-and-eth-rpc-adapter", "start_char": 858, "end_char": 2337, "estimated_token_count": 340, "token_estimator": "heuristic-v1", "text": "## Install the Revive Dev Node and ETH-RPC Adapter\n\nThe Polkadot SDK repository contains both the [Revive Dev node](https://github.com/paritytech/polkadot-sdk/tree/8e2b6f742a38bb13688e12abacded0aab2dbbb23/substrate/frame/revive/dev-node){target=\\_blank} implementation and the [ETH-RPC adapter](https://github.com/paritytech/polkadot-sdk/tree/8e2b6f742a38bb13688e12abacded0aab2dbbb23/substrate/frame/revive/rpc){target=\\_blank} required for Ethereum compatibility. Start by cloning the repository and navigating to the project directory:\n\n```bash\ngit clone https://github.com/paritytech/polkadot-sdk.git\ncd polkadot-sdk\n```\n\nNext, you need to compile the two essential components for your development environment. The Substrate node provides the core blockchain runtime with smart contract support, while the ETH-RPC adapter enables Ethereum JSON-RPC compatibility for existing tooling:\n\n```bash\ncargo build -p revive-dev-node --bin revive-dev-node --release\ncargo build -p pallet-revive-eth-rpc --bin eth-rpc --release\n```\n\nThe compilation process may take some time depending on your system specifications, potentially up to 30 minutes. Release builds are optimized for performance but take longer to compile than debug builds. After successful compilation, you can verify the binaries are available in the `target/release` directory:\n\n- **Revive Dev node path**: `polkadot-sdk/target/release/revive-dev-node`\n- **ETH-RPC adapter path**: `polkadot-sdk/target/release/eth-rpc`"} +{"page_id": "smart-contracts-dev-environments-local-dev-node", "page_title": "Local Development Node", "index": 3, "depth": 2, "title": "Run the Local Node", "anchor": "run-the-local-node", "start_char": 2337, "end_char": 8828, "estimated_token_count": 1912, "token_estimator": "heuristic-v1", "text": "## Run the Local Node\n\nWith the binaries compiled, you can now start your local development environment. The setup requires running two processes.\n\nStart the node first, which will initialize a local blockchain with the `dev` chain specification. This configuration includes `pallet-revive` for smart contract functionality and uses pre-funded development accounts for testing:\n\n```bash\n./target/release/revive-dev-node --dev\n```\n\nThe node will begin producing blocks immediately and display initialization logs:\n\n
\n ./target/release/revive-dev-node --dev\n
\n 2025-05-29 10:42:35 Substrate Node\n 2025-05-29 10:42:35 ✌️ version 3.0.0-dev-38b7581fc04\n 2025-05-29 10:42:35 ❤️ by Parity Technologies <admin@parity.io>, 2017-2025\n 2025-05-29 10:42:35 📋 Chain specification: Development\n 2025-05-29 10:42:35 🏷 Node name: annoyed-aunt-3163\n 2025-05-29 10:42:35 👤 Role: AUTHORITY\n 2025-05-29 10:42:35 💾 Database: RocksDb at /var/folders/x0/xl_kjddj3ql3bx7752yr09hc0000gn/T/substrate2P85EF/chains/dev/db/full\n 2025-05-29 10:42:40 🔨 Initializing Genesis block/state (state: 0xfc05…482e, header-hash: 0x1ae1…b8b4)\n 2025-05-29 10:42:40 Creating transaction pool txpool_type=SingleState ready=Limit { count: 8192, total_bytes: 20971520 } future=Limit { count: 819, total_bytes: 2097152 }\n 2025-05-29 10:42:40 👴 Loading GRANDPA authority set from genesis on what appears to be first startup.\n 2025-05-29 10:42:40 👶 Creating empty BABE epoch changes on what appears to be first startup.\n 2025-05-29 10:42:40 Using default protocol ID \"sup\" because none is configured in the chain specs\n 2025-05-29 10:42:40 🏷 Local node identity is: 12D3KooWAH8fgJv3hce7Yv4yKG4YXQiRqESFu6755DBnfZQU8Znm\n 2025-05-29 10:42:40 Running libp2p network backend\n 2025-05-29 10:42:40 local_peer_id=12D3KooWAH8fgJv3hce7Yv4yKG4YXQiRqESFu6755DBnfZQU8Znm\n 2025-05-29 10:42:40 💻 Operating system: macos\n 2025-05-29 10:42:40 💻 CPU architecture: aarch64\n 2025-05-29 10:42:40 📦 Highest known block at #0\n 2025-05-29 10:42:40 Error binding to '127.0.0.1:9615': Os { code: 48, kind: AddrInUse, message: \"Address already in use\" }\n 2025-05-29 10:42:40 Running JSON-RPC server: addr=127.0.0.1:63333,[::1]:63334\n 2025-05-29 10:42:40 🏁 CPU single core score: 1.24 GiBs, parallelism score: 1.08 GiBs with expected cores: 8\n 2025-05-29 10:42:40 🏁 Memory score: 49.42 GiBs\n 2025-05-29 10:42:40 🏁 Disk score (seq. writes): 1.91 GiBs\n 2025-05-29 10:42:40 🏁 Disk score (rand. writes): 529.02 MiBs\n 2025-05-29 10:42:40 👶 Starting BABE Authorship worker\n 2025-05-29 10:42:40 🥩 BEEFY gadget waiting for BEEFY pallet to become available...\n 2025-05-29 10:42:40 Failed to trigger bootstrap: No known peers.\n 2025-05-29 10:42:42 🙌 Starting consensus session on top of parent 0x1ae19030b13592b5e6fd326f26efc7b31a4f588303d348ef89ae9ebca613b8b4 (#0)\n 2025-05-29 10:42:42 🎁 Prepared block for proposing at 1 (5 ms) hash: 0xe046f22307fba58a3bd0cc21b1a057843d4342da8876fd44aba206f124528df0; parent_hash: 0x1ae1…b8b4; end: NoMoreTransactions; extrinsics_count: 2\n 2025-05-29 10:42:42 🔖 Pre-sealed block for proposal at 1. Hash now 0xa88d36087e7bf8ee59c1b17e0003092accf131ff8353a620410d7283657ce36a, previously 0xe046f22307fba58a3bd0cc21b1a057843d4342da8876fd44aba206f124528df0.\n 2025-05-29 10:42:42 👶 New epoch 0 launching at block 0xa88d…e36a (block slot 582842054 >= start slot 582842054).\n 2025-05-29 10:42:42 👶 Next epoch starts at slot 582842254\n 2025-05-29 10:42:42 🏆 Imported #1 (0x1ae1…b8b4 → 0xa88d…e36a)\n
\n\nFor debugging purposes or to monitor low-level operations, you can enable detailed logging by setting environment variables before running the command:\n\n```bash\nRUST_LOG=\"error,evm=debug,sc_rpc_server=info,runtime::revive=debug\" ./target/release/revive-dev-node --dev\n```\n\nOnce the node is running, open a new terminal window and start the ETH-RPC adapter. This component translates Ethereum JSON-RPC calls into Substrate-compatible requests, allowing you to use familiar Ethereum tools like MetaMask, Hardhat, or Ethers.js:\n\n```bash\n./target/release/eth-rpc --dev\n```\n\nYou should see logs indicating that the adapter is ready to accept connections:\n\n
\n ./target/release/eth-rpc --dev\n
\n 2025-05-29 10:48:48 Running in --dev mode, RPC CORS has been disabled.\n 2025-05-29 10:48:48 Running in --dev mode, RPC CORS has been disabled.\n 2025-05-29 10:48:48 🌐 Connecting to node at: ws://127.0.0.1:9944 ...\n 2025-05-29 10:48:48 🌟 Connected to node at: ws://127.0.0.1:9944\n 2025-05-29 10:48:48 💾 Using in-memory database, keeping only 256 blocks in memory\n 2025-05-29 10:48:48 〽️ Prometheus exporter started at 127.0.0.1:9616\n 2025-05-29 10:48:48 Running JSON-RPC server: addr=127.0.0.1:8545,[::1]:8545\n 2025-05-29 10:48:48 🔌 Subscribing to new blocks (BestBlocks)\n 2025-05-29 10:48:48 🔌 Subscribing to new blocks (FinalizedBlocks)\n
\n\nSimilar to the Revive Dev node, you can enable detailed logging for the ETH-RPC adapter to troubleshoot issues:\n\n```bash\nRUST_LOG=\"info,eth-rpc=debug\" ./target/release/eth-rpc --dev\n```\n\nYour local development environment is now active and accessible at `http://localhost:8545`. This endpoint accepts standard Ethereum JSON-RPC requests, enabling seamless integration with existing Ethereum development tools and workflows. \n\nYou can connect wallets, deploy contracts using Remix or Hardhat, and interact with your smart contracts as you would on any Ethereum-compatible network."} {"page_id": "smart-contracts-dev-environments-remix-get-started", "page_title": "Use the Polkadot Remix IDE", "index": 0, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 1098, "end_char": 1411, "estimated_token_count": 67, "token_estimator": "heuristic-v1", "text": "## Overview\n\nRemix IDE is a robust browser-based development environment for smart contracts. This guide will walk you through the essentials of the [Polkadot Remix IDE](https://remix.polkadot.io/){target=\\_blank} to understand the processes of compiling, developing, and deploying smart contracts on Asset Hub."} {"page_id": "smart-contracts-dev-environments-remix-get-started", "page_title": "Use the Polkadot Remix IDE", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 1411, "end_char": 1775, "estimated_token_count": 88, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore getting started, ensure you have:\n\n- A web browser with [Talisman](https://talisman.xyz/){target=\\_blank} extension installed.\n- Basic understanding of Solidity programming.\n- Some WND test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/westend?parachain=1000){target=\\_blank})."} {"page_id": "smart-contracts-dev-environments-remix-get-started", "page_title": "Use the Polkadot Remix IDE", "index": 2, "depth": 2, "title": "Accessing Remix IDE", "anchor": "accessing-remix-ide", "start_char": 1775, "end_char": 2177, "estimated_token_count": 104, "token_estimator": "heuristic-v1", "text": "## Accessing Remix IDE\n\nNavigate to [https://remix.polkadot.io/](https://remix.polkadot.io/){target=\\_blank}. The interface will load with a default workspace containing sample contracts.\n\n![](/images/smart-contracts/dev-environments/remix/get-started/remix-1.webp)\n\nIn this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal."} @@ -1061,41 +1052,41 @@ {"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 4, "depth": 2, "title": "Dynamic Gas Pricing", "anchor": "dynamic-gas-pricing", "start_char": 2547, "end_char": 3440, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Dynamic Gas Pricing\n\nPallet revive uses dynamic pricing through a \"fee multiplier\" that adjusts based on network congestion:\n\n- When blocks are full, the multiplier increases, making transactions more expensive.\n- When blocks are empty, the multiplier decreases, making transactions cheaper.\n- The multiplier updates after every block based on utilization.\n\nThis creates a market-based pricing mechanism similar to Ethereum's base fee, helping to manage network resources efficiently.\n\nThe gas price returned during estimation is simply the current fee multiplier value.\n\n!!! warning \"Important for Users\"\n Because the fee multiplier can change between when you estimate gas and when your transaction executes, you can add a safety buffer (10-20%) to both your gas limit and gas price. This ensures your transaction will execute successfully even if network conditions change slightly."} {"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 5, "depth": 2, "title": "Transaction Execution Flow", "anchor": "transaction-execution-flow", "start_char": 3440, "end_char": 4936, "estimated_token_count": 353, "token_estimator": "heuristic-v1", "text": "## Transaction Execution Flow\n\nThe following diagram illustrates the complete lifecycle of a transaction from submission to settlement:\n\n```mermaid\ngraph TD\n U[User/Wallet] --> M[Transaction pool]\n M --> P[Pre-dispatch convert gas to weight and create hold]\n P --> C{Sufficient funds}\n C -->|No| R[Rejected]\n C -->|Yes| X[Execute contract within limits]\n X --> S[Settle fee from actual weight and length; refund]\n S --> B[Included in block]\n```\n\nThe transaction execution flow is as follows:\n\n- **Pool and pre-dispatch**: The transaction enters the pool, `gas` is mapped to `weight`, and a temporary hold is created for the maximum fee exposure. Weight is a two-dimensional tuple (`ref_time`, `proof_size`). Each dimension is tracked independently. The [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\\_blank} conversion takes the maximum of the two dimensions (after applying their respective coefficients) to determine the fee.\n- **Funds check**: If the hold is insufficient, the transaction is rejected before any execution.\n- **Execution**: If sufficient, the contract runs within the derived weight limits; a `storage_deposit` may be reserved when new storage is created.\n- **Settlement**: Fees are charged from the actual `weight` used plus the length fee; any unused hold is refunded.\n- **Inclusion**: After settlement, the transaction is included in the block."} {"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 6, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 4936, "end_char": 5234, "estimated_token_count": 51, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nThe Polkadot Hub's gas model is designed to be Ethereum-compatible while providing the flexibility and efficiency of Polkadot's resource metering system. Developers can build on Ethereum tooling while leveraging Polkadot's advanced features like multi-dimensional resource tracking."} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 187, "end_char": 682, "estimated_token_count": 117, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/en/developers/docs/apis/json-rpc/#json-rpc-methods){target=\\_blank} and provides examples of how to use them.\n\nThis guide uses the Polkadot Hub TestNet endpoint:\n\n```text\nhttps://testnet-passet-hub-eth-rpc.polkadot.io\n```"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 1, "depth": 2, "title": "Available Methods", "anchor": "available-methods", "start_char": 682, "end_char": 704, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Available Methods"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 2, "depth": 3, "title": "eth_accounts", "anchor": "eth_accounts", "start_char": 704, "end_char": 1138, "estimated_token_count": 148, "token_estimator": "heuristic-v1", "text": "### eth_accounts\n\nReturns a list of addresses owned by the client. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_accounts){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_accounts\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_accounts\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 3, "depth": 3, "title": "eth_blockNumber", "anchor": "eth_blocknumber", "start_char": 1138, "end_char": 1580, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "### eth_blockNumber\n\nReturns the number of the most recent block. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_blocknumber){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_blockNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_blockNumber\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 4, "depth": 3, "title": "eth_call", "anchor": "eth_call", "start_char": 1580, "end_char": 3831, "estimated_token_count": 725, "token_estimator": "heuristic-v1", "text": "### eth_call\n\nExecutes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_call){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_call\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_call\",\n \"params\":[{\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_CALL\"\n }, \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 5, "depth": 3, "title": "eth_chainId", "anchor": "eth_chainid", "start_char": 3831, "end_char": 4264, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "### eth_chainId\n\nReturns the chain ID used for signing transactions. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_chainid){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_chainId\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_chainId\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 6, "depth": 3, "title": "eth_estimateGas", "anchor": "eth_estimategas", "start_char": 4264, "end_char": 6477, "estimated_token_count": 712, "token_estimator": "heuristic-v1", "text": "### eth_estimateGas\n\nEstimates gas required for a transaction. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_estimategas){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_estimateGas\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_estimateGas\",\n \"params\":[{\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_FUNCTION_CALL\"\n }],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 7, "depth": 3, "title": "eth_gasPrice", "anchor": "eth_gasprice", "start_char": 6477, "end_char": 6900, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "### eth_gasPrice\n\nReturns the current gas price in Wei. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gasprice){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_gasPrice\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_gasPrice\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 8, "depth": 3, "title": "eth_getBalance", "anchor": "eth_getbalance", "start_char": 6900, "end_char": 7954, "estimated_token_count": 338, "token_estimator": "heuristic-v1", "text": "### eth_getBalance\n\nReturns the balance of a given address. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getbalance){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_getBalance\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBalance\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 9, "depth": 3, "title": "eth_getBlockByHash", "anchor": "eth_getblockbyhash", "start_char": 7954, "end_char": 8855, "estimated_token_count": 270, "token_estimator": "heuristic-v1", "text": "### eth_getBlockByHash\n\nReturns information about a block by its hash. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`fullTransactions` ++\"boolean\"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes.\n\n**Example**:\n\n```bash title=\"eth_getBlockByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockByHash\",\n \"params\":[\"INSERT_BLOCK_HASH\", INSERT_BOOLEAN],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 10, "depth": 3, "title": "eth_getBlockByNumber", "anchor": "eth_getblockbynumber", "start_char": 8855, "end_char": 9883, "estimated_token_count": 307, "token_estimator": "heuristic-v1", "text": "### eth_getBlockByNumber\n\nReturns information about a block by its number. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`fullTransactions` ++\"boolean\"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes.\n\n**Example**:\n\n```bash title=\"eth_getBlockByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\", INSERT_BOOLEAN],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 11, "depth": 3, "title": "eth_getBlockTransactionCountByNumber", "anchor": "eth_getblocktransactioncountbynumber", "start_char": 9883, "end_char": 10815, "estimated_token_count": 266, "token_estimator": "heuristic-v1", "text": "### eth_getBlockTransactionCountByNumber\n\nReturns the number of transactions in a block from a block number. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_getBlockTransactionCountByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockTransactionCountByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 12, "depth": 3, "title": "eth_getBlockTransactionCountByHash", "anchor": "eth_getblocktransactioncountbyhash", "start_char": 10815, "end_char": 11631, "estimated_token_count": 232, "token_estimator": "heuristic-v1", "text": "### eth_getBlockTransactionCountByHash\n\nReturns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getBlockTransactionCountByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockTransactionCountByHash\",\n \"params\":[\"INSERT_BLOCK_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 13, "depth": 3, "title": "eth_getCode", "anchor": "eth_getcode", "start_char": 11631, "end_char": 12671, "estimated_token_count": 335, "token_estimator": "heuristic-v1", "text": "### eth_getCode\n\nReturns the code at a given address. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getcode){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getCode\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getCode\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 14, "depth": 3, "title": "eth_getLogs", "anchor": "eth_getlogs", "start_char": 12671, "end_char": 14646, "estimated_token_count": 646, "token_estimator": "heuristic-v1", "text": "### eth_getLogs\n\nReturns an array of all logs matching a given filter object. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getlogs){target=\\_blank}.\n\n**Parameters**:\n\n- **`filter` ++\"object\"++**: The filter object.\n - **`fromBlock` ++\"string\"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n - **`toBlock` ++\"string\"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n - **`address` ++\"string\" or \"array of strings\"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`topics` ++\"array of strings\"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string or an array of such strings (meaning OR).\n - **`blockhash` ++\"string\"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getLogs\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getLogs\",\n \"params\":[{\n \"fromBlock\": \"latest\",\n \"toBlock\": \"latest\"\n }],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 15, "depth": 3, "title": "eth_getStorageAt", "anchor": "eth_getstorageat", "start_char": 14646, "end_char": 15973, "estimated_token_count": 412, "token_estimator": "heuristic-v1", "text": "### eth_getStorageAt\n\nReturns the value from a storage position at a given address. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_getstorageat){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`storageKey` ++\"string\"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getStorageAt\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getStorageAt\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_STORAGE_KEY\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 16, "depth": 3, "title": "eth_getTransactionCount", "anchor": "eth_gettransactioncount", "start_char": 15973, "end_char": 17072, "estimated_token_count": 337, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionCount\n\nReturns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getTransactionCount\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionCount\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 17, "depth": 3, "title": "eth_getTransactionByHash", "anchor": "eth_gettransactionbyhash", "start_char": 17072, "end_char": 17848, "estimated_token_count": 226, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByHash\n\nReturns information about a transaction by its hash. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByHash\",\n \"params\":[\"INSERT_TRANSACTION_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 18, "depth": 3, "title": "eth_getTransactionByBlockNumberAndIndex", "anchor": "eth_gettransactionbyblocknumberandindex", "start_char": 17848, "end_char": 19066, "estimated_token_count": 338, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByBlockNumberAndIndex\n\nReturns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`transactionIndex` ++\"string\"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByBlockNumberAndIndex\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByBlockNumberAndIndex\",\n \"params\":[\"INSERT_BLOCK_VALUE\", \"INSERT_TRANSACTION_INDEX\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 19, "depth": 3, "title": "eth_getTransactionByBlockHashAndIndex", "anchor": "eth_gettransactionbyblockhashandindex", "start_char": 19066, "end_char": 20156, "estimated_token_count": 302, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByBlockHashAndIndex\n\nReturns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`transactionIndex` ++\"string\"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByBlockHashAndIndex\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByBlockHashAndIndex\",\n \"params\":[\"INSERT_BLOCK_HASH\", \"INSERT_TRANSACTION_INDEX\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 20, "depth": 3, "title": "eth_getTransactionReceipt", "anchor": "eth_gettransactionreceipt", "start_char": 20156, "end_char": 20941, "estimated_token_count": 227, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionReceipt\n\nReturns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\\_blank}.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionReceipt\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionReceipt\",\n \"params\":[\"INSERT_TRANSACTION_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 21, "depth": 3, "title": "eth_maxPriorityFeePerGas", "anchor": "eth_maxpriorityfeepergas", "start_char": 20941, "end_char": 21356, "estimated_token_count": 125, "token_estimator": "heuristic-v1", "text": "### eth_maxPriorityFeePerGas\n\nReturns an estimate of the current priority fee per gas, in Wei, to be included in a block.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_maxPriorityFeePerGas\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_maxPriorityFeePerGas\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 22, "depth": 3, "title": "eth_sendRawTransaction", "anchor": "eth_sendrawtransaction", "start_char": 21356, "end_char": 22065, "estimated_token_count": 218, "token_estimator": "heuristic-v1", "text": "### eth_sendRawTransaction\n\nSubmits a raw transaction. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\\_blank}.\n\n**Parameters**:\n\n- **`callData` ++\"string\"++**: Signed transaction data. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_sendRawTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_sendRawTransaction\",\n \"params\":[\"INSERT_CALL_DATA\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_CALL_DATA` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 23, "depth": 3, "title": "eth_sendTransaction", "anchor": "eth_sendtransaction", "start_char": 22065, "end_char": 24444, "estimated_token_count": 730, "token_estimator": "heuristic-v1", "text": "### eth_sendTransaction\n\nCreates and sends a new transaction. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction object.\n - **`from` ++\"string\"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`to` ++\"string\"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`nonce` ++\"string\"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_sendTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_sendTransaction\",\n \"params\":[{\n \"from\": \"INSERT_SENDER_ADDRESS\",\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"gas\": \"INSERT_GAS_LIMIT\",\n \"gasPrice\": \"INSERT_GAS_PRICE\",\n \"value\": \"INSERT_VALUE\",\n \"input\": \"INSERT_INPUT_DATA\",\n \"nonce\": \"INSERT_NONCE\"\n }],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 24, "depth": 3, "title": "eth_syncing", "anchor": "eth_syncing", "start_char": 24444, "end_char": 24888, "estimated_token_count": 152, "token_estimator": "heuristic-v1", "text": "### eth_syncing\n\nReturns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_syncing){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_syncing\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_syncing\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 25, "depth": 3, "title": "net_listening", "anchor": "net_listening", "start_char": 24888, "end_char": 25373, "estimated_token_count": 157, "token_estimator": "heuristic-v1", "text": "### net_listening\n\nReturns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#net_listening){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_listening\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_listening\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 26, "depth": 3, "title": "net_peerCount", "anchor": "net_peercount", "start_char": 25373, "end_char": 25726, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "### net_peerCount\n\nReturns the number of peers currently connected to the client.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_peerCount\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_peerCount\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 27, "depth": 3, "title": "net_version", "anchor": "net_version", "start_char": 25726, "end_char": 26151, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "### net_version\n\nReturns the current network ID as a string. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#net_version){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_version\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_version\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 28, "depth": 3, "title": "system_health", "anchor": "system_health", "start_char": 26151, "end_char": 26493, "estimated_token_count": 113, "token_estimator": "heuristic-v1", "text": "### system_health\n\nReturns information about the health of the system.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"system_health\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"system_health\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 29, "depth": 3, "title": "web3_clientVersion", "anchor": "web3_clientversion", "start_char": 26493, "end_char": 26938, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "### web3_clientVersion\n\nReturns the current client version. [Reference](https://ethereum.org/en/developers/docs/apis/json-rpc/#web3_clientversion){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"web3_clientVersion\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"web3_clientVersion\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 30, "depth": 3, "title": "debug_traceBlockByNumber", "anchor": "debug_traceblockbynumber", "start_char": 26938, "end_char": 28020, "estimated_token_count": 328, "token_estimator": "heuristic-v1", "text": "### debug_traceBlockByNumber \n\nTraces a block's execution by its number and returns a detailed execution trace for each transaction.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options.\n - **`tracer` ++\"string\"++**: The name of the tracer to use (e.g., `\"callTracer\"`, `\"opTracer\"`).\n - Other tracer-specific options may be supported.\n\n**Example**:\n\n```bash title=\"debug_traceBlockByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceBlockByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 31, "depth": 3, "title": "debug_traceTransaction", "anchor": "debug_tracetransaction", "start_char": 28020, "end_char": 28867, "estimated_token_count": 251, "token_estimator": "heuristic-v1", "text": "### debug_traceTransaction\n\nTraces the execution of a single transaction by its hash and returns a detailed execution trace.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options (e.g., `tracer: \"callTracer\"`).\n\n**Example**:\n\n```bash title=\"debug_traceTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceTransaction\",\n \"params\":[\"INSERT_TRANSACTION_HASH\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper value.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 32, "depth": 3, "title": "debug_traceCall", "anchor": "debug_tracecall", "start_char": 28867, "end_char": 31324, "estimated_token_count": 767, "token_estimator": "heuristic-v1", "text": "### debug_traceCall\n\nExecutes a new message call and returns a detailed execution trace without creating a transaction on the blockchain.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object, similar to `eth_call` parameters.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/en/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/en/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options (e.g., `tracer: \"callTracer\"`).\n\n**Example**:\n\n```bash title=\"debug_traceCall\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceCall\",\n \"params\":[{\n \"from\": \"INSERT_SENDER_ADDRESS\",\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_CALL\"\n }, \"INSERT_BLOCK_VALUE\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value.\n\n---"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 33, "depth": 2, "title": "Response Format", "anchor": "response-format", "start_char": 31324, "end_char": 31507, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "## Response Format\n\nAll responses follow the standard JSON-RPC 2.0 format:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"result\": ... // The return value varies by method\n}\n```"} -{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 34, "depth": 2, "title": "Error Handling", "anchor": "error-handling", "start_char": 31507, "end_char": 31726, "estimated_token_count": 64, "token_estimator": "heuristic-v1", "text": "## Error Handling\n\nIf an error occurs, the response will include an error object:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"error\": {\n \"code\": -32000,\n \"message\": \"Error message here\"\n }\n}\n```"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 187, "end_char": 679, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\\_blank} and provides examples of how to use them.\n\nThis guide uses the Polkadot Hub TestNet endpoint:\n\n```text\nhttps://testnet-passet-hub-eth-rpc.polkadot.io\n```"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 1, "depth": 2, "title": "Available Methods", "anchor": "available-methods", "start_char": 679, "end_char": 701, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Available Methods"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 2, "depth": 3, "title": "eth_accounts", "anchor": "eth_accounts", "start_char": 701, "end_char": 1132, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "### eth_accounts\n\nReturns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_accounts\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_accounts\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 3, "depth": 3, "title": "eth_blockNumber", "anchor": "eth_blocknumber", "start_char": 1132, "end_char": 1571, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "### eth_blockNumber\n\nReturns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_blockNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_blockNumber\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 4, "depth": 3, "title": "eth_call", "anchor": "eth_call", "start_char": 1571, "end_char": 3795, "estimated_token_count": 707, "token_estimator": "heuristic-v1", "text": "### eth_call\n\nExecutes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_call\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_call\",\n \"params\":[{\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_CALL\"\n }, \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 5, "depth": 3, "title": "eth_chainId", "anchor": "eth_chainid", "start_char": 3795, "end_char": 4225, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "### eth_chainId\n\nReturns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_chainId\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_chainId\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 6, "depth": 3, "title": "eth_estimateGas", "anchor": "eth_estimategas", "start_char": 4225, "end_char": 6411, "estimated_token_count": 694, "token_estimator": "heuristic-v1", "text": "### eth_estimateGas\n\nEstimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_estimateGas\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_estimateGas\",\n \"params\":[{\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_FUNCTION_CALL\"\n }],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 7, "depth": 3, "title": "eth_gasPrice", "anchor": "eth_gasprice", "start_char": 6411, "end_char": 6831, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "### eth_gasPrice\n\nReturns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_gasPrice\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_gasPrice\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 8, "depth": 3, "title": "eth_getBalance", "anchor": "eth_getbalance", "start_char": 6831, "end_char": 7873, "estimated_token_count": 330, "token_estimator": "heuristic-v1", "text": "### eth_getBalance\n\nReturns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_getBalance\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBalance\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 9, "depth": 3, "title": "eth_getBlockByHash", "anchor": "eth_getblockbyhash", "start_char": 7873, "end_char": 8768, "estimated_token_count": 266, "token_estimator": "heuristic-v1", "text": "### eth_getBlockByHash\n\nReturns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`fullTransactions` ++\"boolean\"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes.\n\n**Example**:\n\n```bash title=\"eth_getBlockByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockByHash\",\n \"params\":[\"INSERT_BLOCK_HASH\", INSERT_BOOLEAN],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 10, "depth": 3, "title": "eth_getBlockByNumber", "anchor": "eth_getblockbynumber", "start_char": 8768, "end_char": 9787, "estimated_token_count": 301, "token_estimator": "heuristic-v1", "text": "### eth_getBlockByNumber\n\nReturns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`fullTransactions` ++\"boolean\"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes.\n\n**Example**:\n\n```bash title=\"eth_getBlockByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\", INSERT_BOOLEAN],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 11, "depth": 3, "title": "eth_getBlockTransactionCountByNumber", "anchor": "eth_getblocktransactioncountbynumber", "start_char": 9787, "end_char": 10710, "estimated_token_count": 260, "token_estimator": "heuristic-v1", "text": "### eth_getBlockTransactionCountByNumber\n\nReturns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n\n**Example**:\n\n```bash title=\"eth_getBlockTransactionCountByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockTransactionCountByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 12, "depth": 3, "title": "eth_getBlockTransactionCountByHash", "anchor": "eth_getblocktransactioncountbyhash", "start_char": 10710, "end_char": 11520, "estimated_token_count": 228, "token_estimator": "heuristic-v1", "text": "### eth_getBlockTransactionCountByHash\n\nReturns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getBlockTransactionCountByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getBlockTransactionCountByHash\",\n \"params\":[\"INSERT_BLOCK_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 13, "depth": 3, "title": "eth_getCode", "anchor": "eth_getcode", "start_char": 11520, "end_char": 12548, "estimated_token_count": 327, "token_estimator": "heuristic-v1", "text": "### eth_getCode\n\nReturns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getCode\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getCode\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 14, "depth": 3, "title": "eth_getLogs", "anchor": "eth_getlogs", "start_char": 12548, "end_char": 14499, "estimated_token_count": 630, "token_estimator": "heuristic-v1", "text": "### eth_getLogs\n\nReturns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\\_blank}.\n\n**Parameters**:\n\n- **`filter` ++\"object\"++**: The filter object.\n - **`fromBlock` ++\"string\"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n - **`toBlock` ++\"string\"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n - **`address` ++\"string\" or \"array of strings\"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`topics` ++\"array of strings\"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string or an array of such strings (meaning OR).\n - **`blockhash` ++\"string\"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getLogs\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getLogs\",\n \"params\":[{\n \"fromBlock\": \"latest\",\n \"toBlock\": \"latest\"\n }],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 15, "depth": 3, "title": "eth_getStorageAt", "anchor": "eth_getstorageat", "start_char": 14499, "end_char": 15811, "estimated_token_count": 402, "token_estimator": "heuristic-v1", "text": "### eth_getStorageAt\n\nReturns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`storageKey` ++\"string\"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getStorageAt\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getStorageAt\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_STORAGE_KEY\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 16, "depth": 3, "title": "eth_getTransactionCount", "anchor": "eth_gettransactioncount", "start_char": 15811, "end_char": 16898, "estimated_token_count": 329, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionCount\n\nReturns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\\_blank}.\n\n**Parameters**:\n\n- **`address` ++\"string\"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block).\n\n**Example**:\n\n```bash title=\"eth_getTransactionCount\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionCount\",\n \"params\":[\"INSERT_ADDRESS\", \"INSERT_BLOCK_VALUE\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 17, "depth": 3, "title": "eth_getTransactionByHash", "anchor": "eth_gettransactionbyhash", "start_char": 16898, "end_char": 17668, "estimated_token_count": 222, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByHash\n\nReturns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\\_blank}.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByHash\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByHash\",\n \"params\":[\"INSERT_TRANSACTION_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 18, "depth": 3, "title": "eth_getTransactionByBlockNumberAndIndex", "anchor": "eth_gettransactionbyblocknumberandindex", "start_char": 17668, "end_char": 18874, "estimated_token_count": 330, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByBlockNumberAndIndex\n\nReturns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`transactionIndex` ++\"string\"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByBlockNumberAndIndex\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByBlockNumberAndIndex\",\n \"params\":[\"INSERT_BLOCK_VALUE\", \"INSERT_TRANSACTION_INDEX\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 19, "depth": 3, "title": "eth_getTransactionByBlockHashAndIndex", "anchor": "eth_gettransactionbyblockhashandindex", "start_char": 18874, "end_char": 19955, "estimated_token_count": 296, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionByBlockHashAndIndex\n\nReturns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\\_blank}.\n\n**Parameters**:\n\n- **`blockHash` ++\"string\"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`transactionIndex` ++\"string\"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionByBlockHashAndIndex\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionByBlockHashAndIndex\",\n \"params\":[\"INSERT_BLOCK_HASH\", \"INSERT_TRANSACTION_INDEX\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 20, "depth": 3, "title": "eth_getTransactionReceipt", "anchor": "eth_gettransactionreceipt", "start_char": 19955, "end_char": 20734, "estimated_token_count": 223, "token_estimator": "heuristic-v1", "text": "### eth_getTransactionReceipt\n\nReturns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\\_blank}.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_getTransactionReceipt\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_getTransactionReceipt\",\n \"params\":[\"INSERT_TRANSACTION_HASH\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 21, "depth": 3, "title": "eth_maxPriorityFeePerGas", "anchor": "eth_maxpriorityfeepergas", "start_char": 20734, "end_char": 21149, "estimated_token_count": 125, "token_estimator": "heuristic-v1", "text": "### eth_maxPriorityFeePerGas\n\nReturns an estimate of the current priority fee per gas, in Wei, to be included in a block.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_maxPriorityFeePerGas\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_maxPriorityFeePerGas\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 22, "depth": 3, "title": "eth_sendRawTransaction", "anchor": "eth_sendrawtransaction", "start_char": 21149, "end_char": 21852, "estimated_token_count": 214, "token_estimator": "heuristic-v1", "text": "### eth_sendRawTransaction\n\nSubmits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\\_blank}.\n\n**Parameters**:\n\n- **`callData` ++\"string\"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_sendRawTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_sendRawTransaction\",\n \"params\":[\"INSERT_CALL_DATA\"],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_CALL_DATA` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 23, "depth": 3, "title": "eth_sendTransaction", "anchor": "eth_sendtransaction", "start_char": 21852, "end_char": 24207, "estimated_token_count": 714, "token_estimator": "heuristic-v1", "text": "### eth_sendTransaction\n\nCreates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\\_blank}.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction object.\n - **`from` ++\"string\"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`to` ++\"string\"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`nonce` ++\"string\"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n\n**Example**:\n\n```bash title=\"eth_sendTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_sendTransaction\",\n \"params\":[{\n \"from\": \"INSERT_SENDER_ADDRESS\",\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"gas\": \"INSERT_GAS_LIMIT\",\n \"gasPrice\": \"INSERT_GAS_PRICE\",\n \"value\": \"INSERT_VALUE\",\n \"input\": \"INSERT_INPUT_DATA\",\n \"nonce\": \"INSERT_NONCE\"\n }],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 24, "depth": 3, "title": "eth_syncing", "anchor": "eth_syncing", "start_char": 24207, "end_char": 24648, "estimated_token_count": 150, "token_estimator": "heuristic-v1", "text": "### eth_syncing\n\nReturns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_syncing\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_syncing\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 25, "depth": 3, "title": "net_listening", "anchor": "net_listening", "start_char": 24648, "end_char": 25130, "estimated_token_count": 155, "token_estimator": "heuristic-v1", "text": "### net_listening\n\nReturns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_listening\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_listening\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 26, "depth": 3, "title": "net_peerCount", "anchor": "net_peercount", "start_char": 25130, "end_char": 25483, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "### net_peerCount\n\nReturns the number of peers currently connected to the client.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_peerCount\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_peerCount\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 27, "depth": 3, "title": "net_version", "anchor": "net_version", "start_char": 25483, "end_char": 25905, "estimated_token_count": 145, "token_estimator": "heuristic-v1", "text": "### net_version\n\nReturns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"net_version\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"net_version\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 28, "depth": 3, "title": "system_health", "anchor": "system_health", "start_char": 25905, "end_char": 26247, "estimated_token_count": 113, "token_estimator": "heuristic-v1", "text": "### system_health\n\nReturns information about the health of the system.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"system_health\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"system_health\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 29, "depth": 3, "title": "web3_clientVersion", "anchor": "web3_clientversion", "start_char": 26247, "end_char": 26689, "estimated_token_count": 142, "token_estimator": "heuristic-v1", "text": "### web3_clientVersion\n\nReturns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"web3_clientVersion\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"web3_clientVersion\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 30, "depth": 3, "title": "debug_traceBlockByNumber", "anchor": "debug_traceblockbynumber", "start_char": 26689, "end_char": 27765, "estimated_token_count": 324, "token_estimator": "heuristic-v1", "text": "### debug_traceBlockByNumber \n\nTraces a block's execution by its number and returns a detailed execution trace for each transaction.\n\n**Parameters**:\n\n- **`blockValue` ++\"string\"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options.\n - **`tracer` ++\"string\"++**: The name of the tracer to use (e.g., `\"callTracer\"`, `\"opTracer\"`).\n - Other tracer-specific options may be supported.\n\n**Example**:\n\n```bash title=\"debug_traceBlockByNumber\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceBlockByNumber\",\n \"params\":[\"INSERT_BLOCK_VALUE\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 31, "depth": 3, "title": "debug_traceTransaction", "anchor": "debug_tracetransaction", "start_char": 27765, "end_char": 28609, "estimated_token_count": 249, "token_estimator": "heuristic-v1", "text": "### debug_traceTransaction\n\nTraces the execution of a single transaction by its hash and returns a detailed execution trace.\n\n**Parameters**:\n\n- **`transactionHash` ++\"string\"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options (e.g., `tracer: \"callTracer\"`).\n\n**Example**:\n\n```bash title=\"debug_traceTransaction\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceTransaction\",\n \"params\":[\"INSERT_TRANSACTION_HASH\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_TRANSACTION_HASH` with the proper value.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 32, "depth": 3, "title": "debug_traceCall", "anchor": "debug_tracecall", "start_char": 28609, "end_char": 31042, "estimated_token_count": 751, "token_estimator": "heuristic-v1", "text": "### debug_traceCall\n\nExecutes a new message call and returns a detailed execution trace without creating a transaction on the blockchain.\n\n**Parameters**:\n\n- **`transaction` ++\"object\"++**: The transaction call object, similar to `eth_call` parameters.\n - **`to` ++\"string\"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`data` ++\"string\"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`from` ++\"string\"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\\_blank} string.\n - **`gas` ++\"string\"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`gasPrice` ++\"string\"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n - **`value` ++\"string\"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string.\n- **`blockValue` ++\"string\"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\\_blank}.\n- **`options` ++\"object\"++**: (Optional) An object containing tracer options (e.g., `tracer: \"callTracer\"`).\n\n**Example**:\n\n```bash title=\"debug_traceCall\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"debug_traceCall\",\n \"params\":[{\n \"from\": \"INSERT_SENDER_ADDRESS\",\n \"to\": \"INSERT_RECIPIENT_ADDRESS\",\n \"data\": \"INSERT_ENCODED_CALL\"\n }, \"INSERT_BLOCK_VALUE\", {\"tracer\": \"callTracer\"}],\n \"id\":1\n}'\n```\n\nEnsure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value.\n\n---"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 33, "depth": 2, "title": "Response Format", "anchor": "response-format", "start_char": 31042, "end_char": 31225, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "## Response Format\n\nAll responses follow the standard JSON-RPC 2.0 format:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"result\": ... // The return value varies by method\n}\n```"} +{"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 34, "depth": 2, "title": "Error Handling", "anchor": "error-handling", "start_char": 31225, "end_char": 31444, "estimated_token_count": 64, "token_estimator": "heuristic-v1", "text": "## Error Handling\n\nIf an error occurs, the response will include an error object:\n\n```json\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"error\": {\n \"code\": -32000,\n \"message\": \"Error message here\"\n }\n}\n```"} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 37, "end_char": 303, "estimated_token_count": 40, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThis guide helps Ethereum developers migrate their smart contracts to Polkadot Hub. Most contracts work without modifications on the REVM backend, while the PolkaVM backend offers enhanced performance with minimal adaptation for standard patterns."} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 1, "depth": 2, "title": "Migration Considerations", "anchor": "migration-considerations", "start_char": 303, "end_char": 645, "estimated_token_count": 62, "token_estimator": "heuristic-v1", "text": "## Migration Considerations\n\nTake into account the following considerations before migrating your contracts:\n\n- Standard ERC-20, ERC-721, ERC-1155 tokens work without changes.\n- DeFi protocols, DEXs, and AMMs migrate seamlessly.\n- DAOs and governance contracts are fully compatible.\n- Most Solidity contracts deploy identically to Ethereum."} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 2, "depth": 2, "title": "Migration Checklist", "anchor": "migration-checklist", "start_char": 645, "end_char": 1058, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "## Migration Checklist\n\nBefore migrating your contracts, review this checklist:\n\n- Factory contracts using PVM bytecode need pre-uploaded dependencies.\n- Contracts using `EXTCODECOPY` for runtime manipulation require review (for projects that will use PVM bytecode, not EVM bytecode).\n- Replace `transfer()` and `send()` with proper reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode)."} @@ -1106,15 +1097,15 @@ {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 7, "depth": 3, "title": "How do gas costs compare?", "anchor": "how-do-gas-costs-compare", "start_char": 3177, "end_char": 3328, "estimated_token_count": 47, "token_estimator": "heuristic-v1", "text": "### How do gas costs compare?\n\nFor more information on gas costs, see the [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\\_blank} page."} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 8, "depth": 3, "title": "Which Solidity features are not supported?", "anchor": "which-solidity-features-are-not-supported", "start_char": 3328, "end_char": 3915, "estimated_token_count": 133, "token_estimator": "heuristic-v1", "text": "### Which Solidity features are not supported?\n\nFor REVM, any Solidity feature will function smoothly without requiring changes or adaptations. For PVM, there are considerations, as was mentioned above. \n\nFor PolkaVM, there are some considerations:\n\n- `EXTCODECOPY`: Only works in constructor code.\n- Runtime code modification: Use on-chain constructors instead.\n- **Gas stipends**: `address.send()` and `address.transfer()` don't provide reentrancy protection.\n- **Unsupported operations**: `pc`, `extcodecopy`, `selfdestruct`, `blobhash`, and `blobbasefee` (blob-related operations)."} {"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 9, "depth": 3, "title": "How do I handle the existential deposit?", "anchor": "how-do-i-handle-the-existential-deposit", "start_char": 3915, "end_char": 4518, "estimated_token_count": 121, "token_estimator": "heuristic-v1", "text": "### How do I handle the existential deposit?\n\nPolkadot requires accounts to maintain a minimum balance (existential deposit or ED) to remain active.\n\nThis is handled automatically for you:\n\n- Balance queries via Ethereum RPC automatically deduct the ED.\n- New account transfers include ED in transaction fees.\n- Contract-to-contract transfers draw ED from the transaction signer.\n\nYou typically don't need to do anything special, but be aware:\n\n- Accounts below ED threshold are automatically deleted.\n- ED is around 0.01 DOT (varies by network).\n- Your contracts don't need to manage this explicitly."} -{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 10, "depth": 3, "title": "Can I use my existing development tools?", "anchor": "can-i-use-my-existing-development-tools", "start_char": 4518, "end_char": 5499, "estimated_token_count": 304, "token_estimator": "heuristic-v1", "text": "### Can I use my existing development tools?\n\nYes. Both backends support:\n\n- **Wallets**: [MetaMask](https://metamask.io/){target=\\_blank}, [Talisman](https://talisman.xyz/){target=\\_blank}, [SubWallet](https://www.subwallet.app/){target=\\_blank}\n- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\\_blank}, [Foundry](/smart-contracts/cookbook/smart-contracts/deploy-basic/foundry/){target=\\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\\_blank} (just consider that for PVM bytecode, you will use the Polkadot version of the tooling)\n- **Libraries**: [ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank}, [web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank}, [viem](/smart-contracts/libraries/viem/){target=\\_blank}\n- **Testing tools**: Your existing test suites work\n\nConnect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow."} -{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 11, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 5499, "end_char": 6247, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nMost Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance.\n\nThere are a few key points to keep in mind during migration:\n\n- Replace `transfer()` and `send()` with `.call{value}(\"\")` and use reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode).\n- PolkaVM factory contracts using PVM bytecode need pre-uploaded dependencies.\n- Don't hardcode gas values.\n- Test thoroughly on [TestNet](/smart-contracts/connect/#__tabbed_1_1){target=\\_blank} before mainnet deployment.\n\nYour existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns."} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 0, "depth": 2, "title": "Quick Starts", "anchor": "quick-starts", "start_char": 173, "end_char": 1843, "estimated_token_count": 456, "token_estimator": "heuristic-v1", "text": "## Quick Starts\n\nKick off development fast with curated links for connecting, funding, exploring, and deploying your first contract.\n\n| Quick Start | Tools | Description |\n| :-------------------------------------------------------------------------------------------------: | :-------------------: | :-------------------------------------------------------------: |\n| [Connect to Polkadot](/smart-contracts/connect/){target=\\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer |\n| [Get Test Tokens](/smart-contracts/faucets/){target=\\_blank} | - | Request test funds to deploy and interact with contracts |\n| [Explore Transactions](/smart-contracts/explorers/){target=\\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state |\n| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\\_blank} | Remix | One‑click browser deployment to Polkadot Hub |\n| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\\_blank} | Foundry | Scripted deployments and testing from the CLI |\n| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank} | Hardhat | Project scaffolding, testing, and deployments |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 1, "depth": 2, "title": "Build and Test Locally", "anchor": "build-and-test-locally", "start_char": 1843, "end_char": 4050, "estimated_token_count": 596, "token_estimator": "heuristic-v1", "text": "## Build and Test Locally\n\nSet up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying.\n\n| Build and Test Locally | Tools | Description |\n| :--------------------------------------------------------------------------------------------------------: | :---------------: | :--------------------------------------------------: |\n| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\\_blank} | Polkadot SDK node | Spin up a local node for iterative development |\n| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts |\n| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\\_blank} | Remix | Publish verified source on explorers |\n| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\\_blank} | Foundry | Install toolchain and configure networks |\n| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\\_blank} | Foundry | Write and run Solidity tests locally |\n| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\\_blank} | Foundry | Verify deployed bytecode and metadata |\n| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank} | Hardhat | Initialize a project and configure networks |\n| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank} | Hardhat | Unit test contracts and run scripts |\n| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\\_blank} | Hardhat | Verify deployments on explorers |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 2, "depth": 2, "title": "Ethereum Developer Resources", "anchor": "ethereum-developer-resources", "start_char": 4050, "end_char": 5794, "estimated_token_count": 488, "token_estimator": "heuristic-v1", "text": "## Ethereum Developer Resources\n\nBridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment.\n\n| Ethereum Developer Guides | Description |\n| :-------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------: |\n| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts |\n| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\\_blank} | Transaction types, fees, and multi‑dimensional metering |\n| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\\_blank} | Gas vs. weight, proof size, and storage deposits |\n| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\\_blank} | Deployment patterns and best practices on Polkadot Hub |\n| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\\_blank} | Supported Ethereum JSON‑RPC methods and examples |\n| [Migration](/smart-contracts/for-eth-devs/migration/){target=\\_blank} | Port existing apps and tooling to Polkadot Hub |\n| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\\_blank} | Overview of EVM and native execution on the Hub |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 3, "depth": 2, "title": "Cookbook: Hands‑on Tutorials", "anchor": "cookbook-handson-tutorials", "start_char": 5794, "end_char": 7098, "estimated_token_count": 409, "token_estimator": "heuristic-v1", "text": "## Cookbook: Hands‑on Tutorials\n\nFollow step‑by‑step guides that walk through common tasks and complete dApp examples.\n\n| Tutorial | Tools | Description |\n| :------------------------------------------------------------------------------------------------: | :-----------------: | :---------------------------------------: |\n| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/){target=\\_blank} | Remix | Minimal deployment walkthrough |\n| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/){target=\\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token |\n| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/){target=\\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection |\n| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\\_blank} | Hardhat | Full dApp project: compile, test, deploy |\n| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\\_blank} | Multiple | End‑to‑end dApp patterns and practices |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 4, "depth": 2, "title": "Libraries", "anchor": "libraries", "start_char": 7098, "end_char": 8111, "estimated_token_count": 313, "token_estimator": "heuristic-v1", "text": "## Libraries\n\nChoose the client libraries that fit your stack for connecting wallets and calling contracts.\n\n| Library | Description |\n| :----------------------------------------------------------------: | :-----------------------------------------------------: |\n| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank} | Connect, sign, and interact with contracts using Ethers |\n| [viem](/smart-contracts/libraries/viem/){target=\\_blank} | Type‑safe EVM interactions and utilities |\n| [Wagmi](/smart-contracts/libraries/wagmi/){target=\\_blank} | React hooks for wallet connections and contract calls |\n| [Web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank} | Web3 provider and contract APIs |\n| [Web3.py](/smart-contracts/libraries/web3-py/){target=\\_blank} | Python toolkit for on‑chain interactions and scripts |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 5, "depth": 2, "title": "Integrations", "anchor": "integrations", "start_char": 8111, "end_char": 8799, "estimated_token_count": 220, "token_estimator": "heuristic-v1", "text": "## Integrations\n\nIntegrate essential services like wallets, indexers, and oracles to round out your dApp.\n\n| Integration | Description |\n| :-----------------------------------------------------------------: | :---------------------------------------: |\n| [Wallets](/smart-contracts/integrations/wallets/){target=\\_blank} | Supported wallets and configuration notes |\n| [Indexers](/smart-contracts/integrations/indexers/){target=\\_blank} | Index and query blockchain data |\n| [Oracles](/smart-contracts/integrations/oracles/){target=\\_blank} | Bring external data on‑chain |"} -{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 6, "depth": 2, "title": "Precompiles", "anchor": "precompiles", "start_char": 8799, "end_char": 10060, "estimated_token_count": 358, "token_estimator": "heuristic-v1", "text": "## Precompiles\n\nDiscover precompiled system contracts available on the Hub and how to use them.\n\n| Topic | Description |\n| :----------------------------------------------------------------------: | :-------------------------------------------------: |\n| [Overview of Precompiles](/smart-contracts/precompiles/){target=\\_blank} | What precompiles are available on the Hub |\n| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\\_blank} | EVM precompiles and interfaces |\n| [Staking](/smart-contracts/precompiles/staking/){target=\\_blank} | Interact with staking functionality via precompiles |\n| [XCM](/smart-contracts/precompiles/xcm/){target=\\_blank} | Cross‑chain messaging helpers for contracts |\n\nFrom here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\\_blank} or reach out in the community channels."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 10, "depth": 3, "title": "Can I use my existing development tools?", "anchor": "can-i-use-my-existing-development-tools", "start_char": 4518, "end_char": 5319, "estimated_token_count": 257, "token_estimator": "heuristic-v1", "text": "### Can I use my existing development tools?\n\nYes. Both backends support:\n\n- **Wallets**: [MetaMask](https://metamask.io/){target=\\_blank}, [Talisman](https://talisman.xyz/){target=\\_blank}, [SubWallet](https://www.subwallet.app/){target=\\_blank}\n- **Development frameworks**: [Hardhat](/smart-contracts/cookbook/smart-contracts/deploy-basic/hardhat/){target=\\_blank}, [Remix](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\\_blank}\n- **Libraries**: [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank}, [Web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank}, [viem](/smart-contracts/libraries/viem/){target=\\_blank}\n- **Testing tools**: Your existing test suites work\n\nConnect to Polkadot Hub's Ethereum JSON-RPC endpoint and use your familiar workflow."} +{"page_id": "smart-contracts-for-eth-devs-migration", "page_title": "Migration FAQs and Considerations", "index": 11, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 5319, "end_char": 6067, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nMost Ethereum contracts migrate to Polkadot Hub with minimal or no changes. Use REVM for seamless compatibility or PolkaVM for enhanced performance.\n\nThere are a few key points to keep in mind during migration:\n\n- Replace `transfer()` and `send()` with `.call{value}(\"\")` and use reentrancy guards (for projects that will use PVM bytecode, not EVM bytecode).\n- PolkaVM factory contracts using PVM bytecode need pre-uploaded dependencies.\n- Don't hardcode gas values.\n- Test thoroughly on [TestNet](/smart-contracts/connect/#__tabbed_1_1){target=\\_blank} before mainnet deployment.\n\nYour existing Solidity knowledge and tooling transfer directly to Polkadot Hub, making migration straightforward for standard smart contract patterns."} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 0, "depth": 2, "title": "Quick Starts", "anchor": "quick-starts", "start_char": 173, "end_char": 1860, "estimated_token_count": 462, "token_estimator": "heuristic-v1", "text": "## Quick Starts\n\nKick off development fast with curated links for connecting, funding, exploring, and deploying your first contract.\n\n| Quick Start | Tools | Description |\n|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:|\n| [Connect to Polkadot](/smart-contracts/connect/){target=\\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer |\n| [Get Test Tokens](/smart-contracts/faucets/){target=\\_blank} | - | Request test funds to deploy and interact with contracts |\n| [Explore Transactions](/smart-contracts/explorers/){target=\\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state |\n| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\\_blank} | Remix | One‑click browser deployment to Polkadot Hub |\n| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\\_blank} | Foundry | Scripted deployments and testing from the CLI |\n| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\\_blank} | Hardhat | Project scaffolding, testing, and deployments |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 1, "depth": 2, "title": "Build and Test Locally", "anchor": "build-and-test-locally", "start_char": 1860, "end_char": 4067, "estimated_token_count": 604, "token_estimator": "heuristic-v1", "text": "## Build and Test Locally\n\nSet up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying.\n\n| Build and Test Locally | Tools | Description |\n|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:|\n| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\\_blank} | Polkadot SDK node | Spin up a local node for iterative development |\n| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts |\n| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\\_blank} | Remix | Publish verified source on explorers |\n| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\\_blank} | Foundry | Install toolchain and configure networks |\n| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\\_blank} | Foundry | Write and run Solidity tests locally |\n| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\\_blank} | Foundry | Verify deployed bytecode and metadata |\n| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\\_blank} | Hardhat | Initialize a project and configure networks |\n| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\\_blank} | Hardhat | Unit test contracts and run scripts |\n| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\\_blank} | Hardhat | Verify deployments on explorers |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 2, "depth": 2, "title": "Ethereum Developer Resources", "anchor": "ethereum-developer-resources", "start_char": 4067, "end_char": 5795, "estimated_token_count": 492, "token_estimator": "heuristic-v1", "text": "## Ethereum Developer Resources\n\nBridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment.\n\n| Ethereum Developer Guides | Description |\n|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:|\n| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts |\n| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\\_blank} | Transaction types, fees, and multi‑dimensional metering |\n| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\\_blank} | Gas vs. weight, proof size, and storage deposits |\n| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\\_blank} | Deployment patterns and best practices on Polkadot Hub |\n| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\\_blank} | Supported Ethereum JSON‑RPC methods and examples |\n| [Migration](/smart-contracts/for-eth-devs/migration/){target=\\_blank} | Port existing apps and tooling to Polkadot Hub |\n| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\\_blank} | Overview of EVM and native execution on the Hub |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 3, "depth": 2, "title": "Cookbook: Hands‑on Tutorials", "anchor": "cookbook-handson-tutorials", "start_char": 5795, "end_char": 7141, "estimated_token_count": 427, "token_estimator": "heuristic-v1", "text": "## Cookbook: Hands‑on Tutorials\n\nFollow step‑by‑step guides that walk through common tasks and complete dApp examples.\n\n| Tutorial | Tools | Description |\n|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:|\n| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\\_blank} | Remix | Minimal deployment walkthrough |\n| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token |\n| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection |\n| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\\_blank} | Hardhat | Full dApp project: compile, test, deploy |\n| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\\_blank} | Multiple | End‑to‑end dApp patterns and practices |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 4, "depth": 2, "title": "Libraries", "anchor": "libraries", "start_char": 7141, "end_char": 8154, "estimated_token_count": 317, "token_estimator": "heuristic-v1", "text": "## Libraries\n\nChoose the client libraries that fit your stack for connecting wallets and calling contracts.\n\n| Library | Description |\n|:------------------------------------------------------------------:|:-------------------------------------------------------:|\n| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank} | Connect, sign, and interact with contracts using Ethers |\n| [viem](/smart-contracts/libraries/viem/){target=\\_blank} | Type‑safe EVM interactions and utilities |\n| [Wagmi](/smart-contracts/libraries/wagmi/){target=\\_blank} | React hooks for wallet connections and contract calls |\n| [Web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank} | Web3 provider and contract APIs |\n| [Web3.py](/smart-contracts/libraries/web3-py/){target=\\_blank} | Python toolkit for on‑chain interactions and scripts |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 5, "depth": 2, "title": "Integrations", "anchor": "integrations", "start_char": 8154, "end_char": 8842, "estimated_token_count": 224, "token_estimator": "heuristic-v1", "text": "## Integrations\n\nIntegrate essential services like wallets, indexers, and oracles to round out your dApp.\n\n| Integration | Description |\n|:-------------------------------------------------------------------:|:-----------------------------------------:|\n| [Wallets](/smart-contracts/integrations/wallets/){target=\\_blank} | Supported wallets and configuration notes |\n| [Indexers](/smart-contracts/integrations/indexers/){target=\\_blank} | Index and query blockchain data |\n| [Oracles](/smart-contracts/integrations/oracles/){target=\\_blank} | Bring external data on‑chain |"} +{"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 6, "depth": 2, "title": "Precompiles", "anchor": "precompiles", "start_char": 8842, "end_char": 10103, "estimated_token_count": 362, "token_estimator": "heuristic-v1", "text": "## Precompiles\n\nDiscover precompiled system contracts available on the Hub and how to use them.\n\n| Topic | Description |\n|:------------------------------------------------------------------------:|:---------------------------------------------------:|\n| [Overview of Precompiles](/smart-contracts/precompiles/){target=\\_blank} | What precompiles are available on the Hub |\n| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\\_blank} | EVM precompiles and interfaces |\n| [Staking](/smart-contracts/precompiles/staking/){target=\\_blank} | Interact with staking functionality via precompiles |\n| [XCM](/smart-contracts/precompiles/xcm/){target=\\_blank} | Cross‑chain messaging helpers for contracts |\n\nFrom here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\\_blank} or reach out in the community channels."} {"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 198, "end_char": 665, "estimated_token_count": 75, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nConnecting a compatible wallet is the first essential step for interacting with the Polkadot Hub ecosystem. This guide explores wallet options that support both Substrate and Ethereum compatible layers, enabling transactions and smart contract interactions. Whether you're a developer testing on Polkadot Hub or a user accessing the MainNet, understanding wallet configuration is crucial for accessing the full range of Polkadot Hub's capabilities."} {"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 1, "depth": 2, "title": "Connect Your Wallet", "anchor": "connect-your-wallet", "start_char": 665, "end_char": 689, "estimated_token_count": 5, "token_estimator": "heuristic-v1", "text": "## Connect Your Wallet"} {"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 2, "depth": 3, "title": "MetaMask", "anchor": "metamask", "start_char": 689, "end_char": 2383, "estimated_token_count": 403, "token_estimator": "heuristic-v1", "text": "### MetaMask\n\n[MetaMask](https://metamask.io/){target=\\_blank} is a popular wallet for interacting with Ethereum-compatible chains. It allows users to connect to test networks that support Ethereum-based smart contracts. However, it's important to emphasize that MetaMask primarily facilitates interactions with smart contracts, giving users access to various chain functionalities. \n\nTo get started with MetaMask, you need to install the [MetaMask extension](https://metamask.io/download/){target=\\_blank} and add it to the browser. Once you install MetaMask, you can set up a new wallet and securely store your seed phrase. This phrase is crucial for recovery in case you lose access.\n\nFor example, to connect to the Polkadot Hub TestNet via MetaMask, you need to follow these steps:\n\n1. Open the MetaMask extension and click on the network icon to switch to the Polkadot Hub TestNet.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-1.webp){: .browser-extension}\n\n2. Click on the **Add a custom network** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-2.webp){: .browser-extension}\n\n3. Complete the necessary fields, then click the **Save** button (refer to the [Networks](/smart-contracts/connect/#networks-details){target=\\_blank} section for copy and paste parameters).\n\n ![](/images/smart-contracts/integrations/wallets/wallets-3.webp){: .browser-extension}\n\n4. Click on **Polkadot Hub TestNet** to switch the network.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-4.webp){: .browser-extension}\n\nThe steps in the preceding section can be used to connect to any chain by modifying the network specification and endpoint parameters."} diff --git a/llms.txt b/llms.txt index 78de7de68..33ebbc345 100644 --- a/llms.txt +++ b/llms.txt @@ -160,8 +160,6 @@ Docs: Infrastructure - [Rewards Payout](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-rewards.md): Learn how validator rewards work on the network, including era points, payout distribution, running multiple validators, and nominator payments. Docs: Tooling -- [Quickstart Parachain Development with Pop CLI](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-quickstart-pop-cli.md): Quickly bootstrap parachain projects, scaffold templates, deploy local networks, and streamline development workflows using Pop CLI. -- [Write Tests](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/develop-toolkit-parachains-spawn-chains-zombienet-write-tests.md): Write and execute tests for blockchain networks with Zombienet's DSL. Learn to evaluate metrics, logs, events, and more for robust validation. - [Install Polkadot SDK](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md): Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. - [Indexers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md): Discover blockchain indexers. Enhance data access, enable fast and complex queries, and optimize blockchain data for seamless app performance. - [Oracles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md): Learn about blockchain oracles, the essential bridges connecting blockchains with real-world data for decentralized applications in the Polkadot ecosystem. @@ -236,14 +234,6 @@ Docs: Uncategorized - [reference-tools-chopsticks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md): No description available. - [ParaSpell XCM SDK](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md): A powerful open-source library that simplifies XCM integration, enabling developers to easily build interoperable dApps on Polkadot. - [reference-tools-zombienet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md): No description available. -- [reference](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md): No description available. -- [smart-contracts-cookbook-smart-contracts-deploy-basic](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-basic.md): No description available. -- [smart-contracts-dev-environments-foundry-compile-and-test](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-compile-and-test.md): No description available. -- [smart-contracts-dev-environments-foundry-deploy-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-deploy-a-contract.md): No description available. -- [Use Foundry with Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-get-started.md): Learn to install, configure, and use foundry-polkadot for smart contract development on Polkadot with PolkaVM bytecode compilation. -- [smart-contracts-dev-environments-foundry-install-and-config](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-install-and-config.md): No description available. -- [smart-contracts-dev-environments-foundry-troubleshooting](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-troubleshooting.md): No description available. -- [smart-contracts-dev-environments-foundry-verify-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-foundry-verify-a-contract.md): No description available. - [smart-contracts-dev-environments-hardhat-compile-and-test](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-compile-and-test.md): No description available. - [smart-contracts-dev-environments-hardhat-deploy-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-deploy-a-contract.md): No description available. - [smart-contracts-dev-environments-hardhat-install-and-config](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-install-and-config.md): No description available. diff --git a/smart-contracts/dev-environments/local-dev-node.md b/smart-contracts/dev-environments/local-dev-node.md index d5e4d4dda..fb8959831 100644 --- a/smart-contracts/dev-environments/local-dev-node.md +++ b/smart-contracts/dev-environments/local-dev-node.md @@ -6,8 +6,6 @@ categories: Smart Contracts # Local Development Node ---8<-- 'text/smart-contracts/polkaVM-warning.md' - ## Introduction A local development node provides an isolated blockchain environment where you can deploy, test, and debug smart contracts without incurring network fees or waiting for block confirmations. This guide demonstrates how to set up a local Polkadot SDK-based node with smart contract capabilities. @@ -30,7 +28,6 @@ The Polkadot SDK repository contains both the [Revive Dev node](https://github.c ```bash git clone https://github.com/paritytech/polkadot-sdk.git cd polkadot-sdk -git checkout {{dependencies.repositories.polkadot_sdk_contracts_node.commit_dev_node}} ``` Next, you need to compile the two essential components for your development environment. The Substrate node provides the core blockchain runtime with smart contract support, while the ETH-RPC adapter enables Ethereum JSON-RPC compatibility for existing tooling: From 24bf1c67d31f09c60fdf3437af0291df26b4c623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hussein?= <80422357+nhussein11@users.noreply.github.com> Date: Tue, 18 Nov 2025 17:43:13 -0300 Subject: [PATCH 10/12] Add Remix IDE (new IA) (#1174) * fix: get started ready * fix: remix deploy * Update troubleshooting guide for Remix IDE and comment out 'Verify a Contract' section in navigation * fix: images and names * fix: remove verify contract file * fix: llms * Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: prerequisite * fix: llms * Grammarly things and reformat to FAQ style dropdowns for troubleshooting page * applies review feedback * Clean up formatting of titles and bullets * fix: feedback * fix: llms * fix: gifs lists wording * fix: llms * Remove outdated troubleshooting and verification guides for Remix IDE on Polkadot Hub. * fix errant merge conflict syntax, description length * applies review feedback * grammarly pass * minor fix and llms --------- Co-authored-by: Dawn Kelly <83190195+dawnkelly09@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: DAWN KELLY Co-authored-by: Erin Shaben --- .ai/categories/smart-contracts.md | 381 +++++++++++++----- .ai/categories/tooling.md | 381 +++++++++++++----- ...ev-environments-remix-deploy-a-contract.md | 80 +++- ...acts-dev-environments-remix-get-started.md | 136 ++----- ...-environments-remix-troubleshooting-faq.md | 156 +++++++ ...-dev-environments-remix-troubleshooting.md | 5 - ...ev-environments-remix-verify-a-contract.md | 5 - .ai/site-index.json | 196 ++++++--- .../remix/deploy-a-contract/remix-1.gif | Bin 0 -> 1642689 bytes .../remix/deploy-a-contract/remix-2.gif | Bin 0 -> 1195757 bytes .../remix/get-started/remix-1.webp | Bin 201270 -> 432120 bytes .../remix/get-started/remix-10.webp | Bin 145094 -> 0 bytes .../remix/get-started/remix-11.webp | Bin 126058 -> 0 bytes .../remix/get-started/remix-12.webp | Bin 91678 -> 0 bytes .../remix/get-started/remix-13.webp | Bin 87460 -> 0 bytes .../remix/get-started/remix-2.gif | Bin 0 -> 1533379 bytes .../remix/get-started/remix-2.webp | Bin 232340 -> 0 bytes .../remix/get-started/remix-3.gif | Bin 0 -> 994567 bytes .../remix/get-started/remix-3.webp | Bin 227332 -> 0 bytes .../remix/get-started/remix-4.webp | Bin 226618 -> 0 bytes .../remix/get-started/remix-5.webp | Bin 272678 -> 0 bytes .../remix/get-started/remix-6.webp | Bin 231768 -> 0 bytes .../remix/get-started/remix-7.webp | Bin 96304 -> 0 bytes .../remix/get-started/remix-8.webp | Bin 160414 -> 0 bytes .../remix/get-started/remix-9.webp | Bin 115868 -> 0 bytes llms-full.jsonl | 32 +- llms.txt | 13 +- .../dev-environments/remix/.nav.yml | 4 +- .../remix/deploy-a-contract.md | 89 +++- .../dev-environments/remix/get-started.md | 136 ++----- .../remix/troubleshooting-faq.md | 155 +++++++ .../dev-environments/remix/troubleshooting.md | 1 - .../remix/verify-a-contract.md | 1 - 33 files changed, 1243 insertions(+), 528 deletions(-) create mode 100644 .ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md delete mode 100644 .ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md delete mode 100644 .ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md create mode 100644 images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-1.gif create mode 100644 images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-2.gif delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-10.webp delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-11.webp delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-12.webp delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-13.webp create mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-2.gif delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-2.webp create mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-3.gif delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-3.webp delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-4.webp delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-5.webp delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-6.webp delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-7.webp delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-8.webp delete mode 100644 images/smart-contracts/dev-environments/remix/get-started/remix-9.webp create mode 100644 smart-contracts/dev-environments/remix/troubleshooting-faq.md delete mode 100644 smart-contracts/dev-environments/remix/troubleshooting.md delete mode 100644 smart-contracts/dev-environments/remix/verify-a-contract.md diff --git a/.ai/categories/smart-contracts.md b/.ai/categories/smart-contracts.md index 5412f63f8..51b361f54 100644 --- a/.ai/categories/smart-contracts.md +++ b/.ai/categories/smart-contracts.md @@ -3678,6 +3678,92 @@ Now that you have the foundational knowledge to use Ethers.js with Polkadot Hub, - **Build scalable applications**: Combine Ethers.js with frameworks like [`Next.js`](https://nextjs.org/docs){target=\_blank} or [`Node.js`](https://nodejs.org/en){target=\_blank} to create full-stack decentralized applications (dApps). +--- + +Page Title: Deploy Contracts Using Remix IDE + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/ +- Summary: Learn how to deploy smart contracts to the Polkadot Hub network and interact with them using the Remix IDE and wallet providers, covering deployment and state. + +# Deploy Smart Contracts Using Remix IDE + +## Overview + +After compiling your smart contract in Remix IDE, the next step is to deploy it to the Polkadot Hub network. This guide will walk you through the deployment process using a wallet provider and show you how to interact with your deployed contracts directly from the Remix interface. + +## Prerequisites + +Before deploying your contract, ensure you have: + +- Completed the [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} and have a compiled contract ready. +- A compatible wallet extension installed (e.g., [MetaMask](https://metamask.io/){target=\_blank} or [Talisman](https://www.talisman.xyz/){target=\_blank}). +- Your wallet connected to the Polkadot Hub network. Check the [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} guide for more information. +- Test tokens in your wallet to cover deployment and transaction fees (available from the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank}). + +## Deploy Contracts + +The steps to use Remix IDE to deploy a contract to Polkadot Hub are as follows: + +1. Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. +2. Locate the **Deploy & Run Transactions** tab. +3. Select the **Environment** dropdown. +4. Select **Browser Extension**. +5. Select the **Injected Provider - MetaMask** option. +6. Click the **Deploy** button and then click **Confirm** in the wallet popup. + +Once your contract is deployed successfully, you will see the deployment confirmation in the Remix terminal. + +![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-1.gif) + +## Interact with Contracts + +Deployed contracts appear in the **Deployed/Unpinned Contracts** section. Follow these steps to interact with the deployed contract: + +1. Expand the contract to view available methods. + + !!! tip + Pin your frequently used contracts to the **Pinned Contracts** section for easy access. + +2. Select any of the exposed methods to interact with the contract. + + You can use these methods to interact with your deployed contract by reading or writing to its state. Remix IDE uses a color-coding scheme for method buttons to help differentiate between types of available methods as follows: + + - **Blue buttons**: indicate `view` or `pure` functions which read state only. Interactions do not create a new transaction and do not incur gas fees. + - **Orange buttons**: label `non-payable` functions which change contract state but don't accept any value (ETH or other tokens) being sent with the transaction. + - **Red buttons**: designate `payable` functions which create a transaction and can accept a value (ETH or other tokens) to send with the transaction. + +If you deployed the `Counter.sol` contract from [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank}, you can try interacting with the exposed methods as follows: + +1. Select the **GetCount** button to read the current count value. + +2. Select the **Increment** button to increment the count value. + +3. Submit the transaction and click the **Confirm** button in the wallet pop-up. + +Once the transaction is confirmed, you will see the updated count value in the Remix terminal. + +![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-2.gif) + +## Where to Go Next + +You've successfully deployed and interacted with your smart contract on Polkadot Hub using Remix IDE. Continue enhancing your development workflow with these resources: + +
+ + + +- Guide __Troubleshooting__ + + --- + + Find solutions to common issues when working with Remix IDE. + + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/troubleshooting-faq/) + +
+ + --- Page Title: Dual Virtual Machine Stack @@ -8967,6 +9053,165 @@ You now know the weight system, how it affects transaction fee computation, and - [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} +--- + +Page Title: Troubleshooting Remix IDE + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting-faq/ +- Summary: Common issues related to developing, compiling, and deploying smart contracts using Remix IDE on Polkadot Hub paired with troubleshooting suggestions. + +# Remix IDE Troubleshooting + +This guide provides solutions to common issues you may encounter when using Remix IDE with Polkadot Hub. If you're experiencing problems with compilation, deployment, or contract interaction, you'll likely find the solution here. + +## Contract fails to compile or shows errors in the terminal + +- **Check Solidity version compatibility**: + - Ensure your contract's pragma statement matches the compiler version selected in the **Solidity Compiler** tab. + - Example: If your contract uses `pragma solidity ^0.8.0;`, select compiler version 0.8.x or higher. + +- **Review syntax errors**: + - Carefully read error messages in the terminal panel at the bottom of the screen. + - Common issues include missing semicolons, incorrect function visibility, or mismatched brackets. + +- **Clear cache and recompile**: + - Delete the `artifacts` folder in the **File Explorer**. + - Try compiling again with `Ctrl+S` or click the **Compile** button. + +## The `artifacts` folder doesn't appear after compilation + +- Ensure compilation completed successfully without errors. +- Refresh the **File Explorer** by clicking away and back to the **File Explorer** tab. +- Check that your `.sol` file is saved before compiling. + +## Remix doesn't detect your wallet extension (MetaMask, Talisman, etc.) + +- **Verify wallet installation**: + - Ensure your wallet extension is properly installed and enabled in your browser. + - Check that the extension icon appears in your browser toolbar. + +- **Refresh the page**: + - Reload the Remix IDE page and try reconnecting. + +- **Check browser permissions**: + - Ensure Remix has permission to interact with the wallet extension. + - Check your browser's extension settings. + +- **Use correct environment**: + - In the **Deploy & Run Transactions** tab, select **Browser Extension** from the **Environment** dropdown. + - Choose **Injected Provider - MetaMask** (works with most wallet providers). + +## Wallet is connected but to the wrong network + +1. Open your wallet extension. +2. Switch to the Polkadot Hub network. +3. Refresh the Remix IDE if the network change isn't detected automatically. +4. Verify the network name and chain ID match Polkadot Hub's configuration. + +## Deployment fails with "insufficient funds" or similar error + +- **Check your balance**: + - Verify you have enough test tokens in your connected wallet. + - Visit the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank} to obtain test tokens. + +- **Wait for faucet tokens**: + - Allow a few minutes for faucet transactions to complete. + - Refresh your wallet to see the updated balance. + +## Deployment transaction is rejected or fails + +- **Increase gas limit**: + - In the **Deploy & Run Transactions** tab, adjust the **Gas Limit** field. + - Try increasing it by 20-30% from the estimated amount. + +- **Check contract constructor parameters**: + - Ensure any required constructor parameters are provided correctly. + - Verify parameter types match the contract's constructor signature. + +- **Verify contract selection**: + - Ensure you've selected the correct contract from the **Contract** dropdown. + - If you have multiple contracts, make sure you're deploying the intended one. + +## The "Injected Provider - MetaMask" option doesn't appear in the Environment dropdown + +- Select **Browser Extension** from the **Environment** dropdown to populate the **Injected Provider - Metamask** option. +- Ensure your wallet extension is unlocked and active. +- Try disabling and re-enabling the wallet extension. +- Refresh the Remix IDE page. + +## Wallet rejects transactions when trying to interact with deployed contracts + +- **Check wallet unlock status**: + - Ensure your wallet is unlocked. + - Verify you're approving the transaction in the wallet pop-up. + +- **Verify sufficient gas**: + - Ensure you have enough tokens to cover the transaction fee. + - The wallet pop-up should show the estimated gas cost. + +- **Network mismatch**: + - Confirm your wallet is still connected to Polkadot Hub. + - Check that Remix is using the same network. + +## Deployed contract doesn't show in the **Deployed/Unpinned Contracts** section + +- Wait for the transaction to be confirmed on-chain. +- Check the Remix terminal for deployment confirmation. +- Scroll down in the **Deploy & Run Transactions** panel to find the deployed contracts section. +- If the deployment transaction failed, check the terminal for error messages. + +## Blue buttons (read functions) don't display return values + +- **Check the terminal**: + - Return values appear in the terminal panel at the bottom. + - Look for the decoded output section. + +- **Verify contract state**: + - Ensure the contract has been properly initialized. + - Check if the function requires a specific contract state to return values. + +- **Network connection**: + - Verify you're still connected to the correct network. + - Try refreshing the connection to your wallet. + + +## Orange/red buttons (write functions) execute, but the state doesn't change + +- **Wait for transaction confirmation**: + - Transactions need to be mined before state changes are reflected. + - Check the terminal for transaction status. + - Wait a few seconds and try rereading the state. + +- **Transaction failed**: + - Check if the transaction was actually successful in the terminal. + - Look for revert reasons or error messages. + - Verify you approved the transaction in your wallet. + +- **Check transaction parameters**: + - Ensure you're passing the correct parameters to the function. + - For payable functions (red buttons), verify you're sending the correct amount. + +## Remix takes a long time to load or becomes unresponsive + +- **Clear browser cache**: + - Clear your browser's cache and cookies. + - Restart your browser. + +- **Disable unnecessary plugins**: + - In Remix, deactivate plugins you're not using via the Plugin Manager. + +- **Use a supported browser**: + - Use Chrome, Firefox, or Brave for the best compatibility. + - Ensure your browser is up to date. + +## Changes to files or folders don't appear in the File Explorer + +- Click the refresh icon in the **File Explorer**. +- Switch to a different tab and back to **File Explorer**. +- Save your work and reload the Remix IDE page. + + --- Page Title: Use Hardhat with Polkadot Hub @@ -9098,76 +9343,45 @@ Ready to explore the specifics? Dive into these guides to continue your Hardhat --- -Page Title: Use the Polkadot Remix IDE +Page Title: Use the Remix IDE on Polkadot Hub - Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md - Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/get-started/ -- Summary: Explore the smart contract development and deployment process on Asset Hub using Remix IDE, a visual IDE for blockchain developers. +- Summary: Explore the smart contract development and deployment process on Polkadot Hub using Remix IDE, a visual IDE for blockchain developers. # Remix IDE -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -
-- :octicons-code-16:{ .lg .middle } __Deploy NFTs Using Remix IDE__ - - --- - - Mint your NFT on Polkadot's Asset Hub. Use PolkaVM and OpenZeppelin to bring your digital asset to life with Polkadot Remix IDE. - -
- [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} - -- :octicons-code-16:{ .lg .middle } __Deploy ERC20s Using Remix IDE__ - - --- - - Mint your custom ERC-20 token on Polkadot's Asset Hub. Leverage PolkaVM and Polkadot Remix IDE to bring your blockchain project to life. - -
- [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} -
- -!!! warning - The Polkadot Remix IDE's contract compilation functionality is currently limited to Google Chrome. Alternative browsers are not recommended for this task. - -## Overview +## Introduction -Remix IDE is a robust browser-based development environment for smart contracts. This guide will walk you through the essentials of the [Polkadot Remix IDE](https://remix.polkadot.io/){target=\_blank} to understand the processes of compiling, developing, and deploying smart contracts on Asset Hub. +Remix IDE is a robust browser-based development environment for smart contracts. This guide will walk you through the essentials of the [Remix IDE](https://remix.ethereum.org/){target=\_blank} to understand the processes of compiling, developing, and deploying smart contracts on Polkadot Hub. ## Prerequisites Before getting started, ensure you have: -- A web browser with [Talisman](https://talisman.xyz/){target=\_blank} extension installed. +- A web browser with the [MetaMask](https://metamask.io/){target=\_blank} extension installed. - Basic understanding of Solidity programming. -- Some WND test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/westend?parachain=1000){target=\_blank}). +- Some test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank}). -## Accessing Remix IDE +## Access Remix IDE -Navigate to [https://remix.polkadot.io/](https://remix.polkadot.io/){target=\_blank}. The interface will load with a default workspace containing sample contracts. +Navigate to [https://remix.ethereum.org/](https://remix.ethereum.org/){target=\_blank}. The interface will load with a default workspace containing sample contracts. ![](/images/smart-contracts/dev-environments/remix/get-started/remix-1.webp) -In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. +In this interface, you can access a file explorer, edit your code, interact with various development plugins, and use a terminal. -## Creating a New Contract +## Create a New Contract -To create a new contract using the Polkadot Remix IDE, you can follow these steps: +To create a new contract using the Remix IDE, you can follow these steps: 1. Select the **Create a new file** button in the `contracts` folder. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-2.webp) - 2. Name your file with a `.sol` extension, in this case, `Counter.sol`. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-3.webp) - -3. Write your Solidity code in the editor. +3. Write your Solidity code in the editor. You can use the following code as an example: - You can use the following code as an example: - - ???- "Counter.sol" + ??? code "Counter.sol" ```solidity // SPDX-License-Identifier: MIT @@ -9190,95 +9404,46 @@ To create a new contract using the Polkadot Remix IDE, you can follow these step } ``` - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-4.webp) + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-2.gif) -## Compiling Your Contract +## Compile Your Contract -1. To compile your contract, you need to: +To compile your contract, you need to: - 1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). - 2. Select **Compile** or use `Ctrl+S`. +1. Navigate to the **Solidity Compiler** tab. +2. Select **Compile** or use `Ctrl+S`. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-5.webp) - - !!! note - Compilation errors and warnings appear in the terminal panel at the bottom of the screen. + !!! note + Compilation errors and warnings appear in the terminal panel at the bottom of the screen. -1. After compiling your contract, you can navigate to the **File Explorer** tab (first icon in the left sidebar) and check that: - 1. The `artifact` folder is present. +3. After compiling your contract, you can navigate to the **File Explorer** tab and check that: + 1. The **artifacts** folder is present. 2. The `Counter_metadata.json` and the `Counter.json` files have been generated. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-6.webp) - -## Deploying Contracts - -1. To deploy your contract, you need to: - - 1. Navigate to the **Deploy & Run Transactions** tab (fourth icon in the left sidebar). - 2. Click the **Environment** dropdown. - 3. Select **Customize this list**. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-7.webp) - -2. Enable the **Injected Provider - Talisman** option. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-8.webp) - -4. Click again the **Environment** dropdown and select **Injected Provider - Talisman**. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-9.webp) - -4. Click the **Deploy** button and then click **Approve** in the Talisman wallet popup. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-10.webp) - -5. Once your contract is deployed successfully, you will see the following output in the Remix terminal: - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-11.webp) - -## Interacting with Contracts - -Once deployed, your contract appears in the **Deployed/Unpinned Contracts** section: - -1. Expand the contract to view available methods. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-12.webp) - - !!! tip - Pin your frequently used contracts to the **Pinned Contracts** section for easy access. - -2. To interact with the contract, you can select any of the exposed methods. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-13.webp) - - In this way, you can interact with your deployed contract by reading its state or writing to it. The button color indicates the type of interaction available: - - - **Red**: Modifies state and is payable. - - **Orange**: Modifies state only. - - **Blue**: Reads state. + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-3.gif) ## Where to Go Next -The Polkadot Remix IDE offers an environment for developing, compiling, and deploying smart contracts on Asset Hub. Its intuitive interface allows developers to easily write Solidity code, compile contracts, and interact with them directly in the browser. +Remix offers an environment for developing, compiling, and deploying smart contracts on Polkadot Hub. Its intuitive interface allows developers to easily write Solidity code, compile contracts, and interact with them directly in the browser. Explore more about smart contracts through these resources:
-- Guide __Smart Contracts on Polkadot__ +- Guide __Deploy a Contract__ --- - Dive into advanced smart contract concepts. + Learn how to deploy smart contracts using Remix IDE. - [:octicons-arrow-right-24: Get Started](/smart-contracts/) + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/deploy-a-contract/) - External __OpenZeppelin Contracts__ --- - Test your skills by deploying a simple contracts with prebuilt templates. + Test your skills by deploying simple contracts using prebuilt templates. [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank} diff --git a/.ai/categories/tooling.md b/.ai/categories/tooling.md index 7b85f85c4..f4dd788b0 100644 --- a/.ai/categories/tooling.md +++ b/.ai/categories/tooling.md @@ -2976,6 +2976,92 @@ Now that you have the foundational knowledge to use Ethers.js with Polkadot Hub, - **Build scalable applications**: Combine Ethers.js with frameworks like [`Next.js`](https://nextjs.org/docs){target=\_blank} or [`Node.js`](https://nodejs.org/en){target=\_blank} to create full-stack decentralized applications (dApps). +--- + +Page Title: Deploy Contracts Using Remix IDE + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/ +- Summary: Learn how to deploy smart contracts to the Polkadot Hub network and interact with them using the Remix IDE and wallet providers, covering deployment and state. + +# Deploy Smart Contracts Using Remix IDE + +## Overview + +After compiling your smart contract in Remix IDE, the next step is to deploy it to the Polkadot Hub network. This guide will walk you through the deployment process using a wallet provider and show you how to interact with your deployed contracts directly from the Remix interface. + +## Prerequisites + +Before deploying your contract, ensure you have: + +- Completed the [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} and have a compiled contract ready. +- A compatible wallet extension installed (e.g., [MetaMask](https://metamask.io/){target=\_blank} or [Talisman](https://www.talisman.xyz/){target=\_blank}). +- Your wallet connected to the Polkadot Hub network. Check the [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} guide for more information. +- Test tokens in your wallet to cover deployment and transaction fees (available from the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank}). + +## Deploy Contracts + +The steps to use Remix IDE to deploy a contract to Polkadot Hub are as follows: + +1. Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. +2. Locate the **Deploy & Run Transactions** tab. +3. Select the **Environment** dropdown. +4. Select **Browser Extension**. +5. Select the **Injected Provider - MetaMask** option. +6. Click the **Deploy** button and then click **Confirm** in the wallet popup. + +Once your contract is deployed successfully, you will see the deployment confirmation in the Remix terminal. + +![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-1.gif) + +## Interact with Contracts + +Deployed contracts appear in the **Deployed/Unpinned Contracts** section. Follow these steps to interact with the deployed contract: + +1. Expand the contract to view available methods. + + !!! tip + Pin your frequently used contracts to the **Pinned Contracts** section for easy access. + +2. Select any of the exposed methods to interact with the contract. + + You can use these methods to interact with your deployed contract by reading or writing to its state. Remix IDE uses a color-coding scheme for method buttons to help differentiate between types of available methods as follows: + + - **Blue buttons**: indicate `view` or `pure` functions which read state only. Interactions do not create a new transaction and do not incur gas fees. + - **Orange buttons**: label `non-payable` functions which change contract state but don't accept any value (ETH or other tokens) being sent with the transaction. + - **Red buttons**: designate `payable` functions which create a transaction and can accept a value (ETH or other tokens) to send with the transaction. + +If you deployed the `Counter.sol` contract from [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank}, you can try interacting with the exposed methods as follows: + +1. Select the **GetCount** button to read the current count value. + +2. Select the **Increment** button to increment the count value. + +3. Submit the transaction and click the **Confirm** button in the wallet pop-up. + +Once the transaction is confirmed, you will see the updated count value in the Remix terminal. + +![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-2.gif) + +## Where to Go Next + +You've successfully deployed and interacted with your smart contract on Polkadot Hub using Remix IDE. Continue enhancing your development workflow with these resources: + +
+ + + +- Guide __Troubleshooting__ + + --- + + Find solutions to common issues when working with Remix IDE. + + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/troubleshooting-faq/) + +
+ + --- Page Title: Deploying Uniswap V2 on Polkadot @@ -10977,6 +11063,165 @@ You now know the weight system, how it affects transaction fee computation, and - [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} +--- + +Page Title: Troubleshooting Remix IDE + +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting-faq/ +- Summary: Common issues related to developing, compiling, and deploying smart contracts using Remix IDE on Polkadot Hub paired with troubleshooting suggestions. + +# Remix IDE Troubleshooting + +This guide provides solutions to common issues you may encounter when using Remix IDE with Polkadot Hub. If you're experiencing problems with compilation, deployment, or contract interaction, you'll likely find the solution here. + +## Contract fails to compile or shows errors in the terminal + +- **Check Solidity version compatibility**: + - Ensure your contract's pragma statement matches the compiler version selected in the **Solidity Compiler** tab. + - Example: If your contract uses `pragma solidity ^0.8.0;`, select compiler version 0.8.x or higher. + +- **Review syntax errors**: + - Carefully read error messages in the terminal panel at the bottom of the screen. + - Common issues include missing semicolons, incorrect function visibility, or mismatched brackets. + +- **Clear cache and recompile**: + - Delete the `artifacts` folder in the **File Explorer**. + - Try compiling again with `Ctrl+S` or click the **Compile** button. + +## The `artifacts` folder doesn't appear after compilation + +- Ensure compilation completed successfully without errors. +- Refresh the **File Explorer** by clicking away and back to the **File Explorer** tab. +- Check that your `.sol` file is saved before compiling. + +## Remix doesn't detect your wallet extension (MetaMask, Talisman, etc.) + +- **Verify wallet installation**: + - Ensure your wallet extension is properly installed and enabled in your browser. + - Check that the extension icon appears in your browser toolbar. + +- **Refresh the page**: + - Reload the Remix IDE page and try reconnecting. + +- **Check browser permissions**: + - Ensure Remix has permission to interact with the wallet extension. + - Check your browser's extension settings. + +- **Use correct environment**: + - In the **Deploy & Run Transactions** tab, select **Browser Extension** from the **Environment** dropdown. + - Choose **Injected Provider - MetaMask** (works with most wallet providers). + +## Wallet is connected but to the wrong network + +1. Open your wallet extension. +2. Switch to the Polkadot Hub network. +3. Refresh the Remix IDE if the network change isn't detected automatically. +4. Verify the network name and chain ID match Polkadot Hub's configuration. + +## Deployment fails with "insufficient funds" or similar error + +- **Check your balance**: + - Verify you have enough test tokens in your connected wallet. + - Visit the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank} to obtain test tokens. + +- **Wait for faucet tokens**: + - Allow a few minutes for faucet transactions to complete. + - Refresh your wallet to see the updated balance. + +## Deployment transaction is rejected or fails + +- **Increase gas limit**: + - In the **Deploy & Run Transactions** tab, adjust the **Gas Limit** field. + - Try increasing it by 20-30% from the estimated amount. + +- **Check contract constructor parameters**: + - Ensure any required constructor parameters are provided correctly. + - Verify parameter types match the contract's constructor signature. + +- **Verify contract selection**: + - Ensure you've selected the correct contract from the **Contract** dropdown. + - If you have multiple contracts, make sure you're deploying the intended one. + +## The "Injected Provider - MetaMask" option doesn't appear in the Environment dropdown + +- Select **Browser Extension** from the **Environment** dropdown to populate the **Injected Provider - Metamask** option. +- Ensure your wallet extension is unlocked and active. +- Try disabling and re-enabling the wallet extension. +- Refresh the Remix IDE page. + +## Wallet rejects transactions when trying to interact with deployed contracts + +- **Check wallet unlock status**: + - Ensure your wallet is unlocked. + - Verify you're approving the transaction in the wallet pop-up. + +- **Verify sufficient gas**: + - Ensure you have enough tokens to cover the transaction fee. + - The wallet pop-up should show the estimated gas cost. + +- **Network mismatch**: + - Confirm your wallet is still connected to Polkadot Hub. + - Check that Remix is using the same network. + +## Deployed contract doesn't show in the **Deployed/Unpinned Contracts** section + +- Wait for the transaction to be confirmed on-chain. +- Check the Remix terminal for deployment confirmation. +- Scroll down in the **Deploy & Run Transactions** panel to find the deployed contracts section. +- If the deployment transaction failed, check the terminal for error messages. + +## Blue buttons (read functions) don't display return values + +- **Check the terminal**: + - Return values appear in the terminal panel at the bottom. + - Look for the decoded output section. + +- **Verify contract state**: + - Ensure the contract has been properly initialized. + - Check if the function requires a specific contract state to return values. + +- **Network connection**: + - Verify you're still connected to the correct network. + - Try refreshing the connection to your wallet. + + +## Orange/red buttons (write functions) execute, but the state doesn't change + +- **Wait for transaction confirmation**: + - Transactions need to be mined before state changes are reflected. + - Check the terminal for transaction status. + - Wait a few seconds and try rereading the state. + +- **Transaction failed**: + - Check if the transaction was actually successful in the terminal. + - Look for revert reasons or error messages. + - Verify you approved the transaction in your wallet. + +- **Check transaction parameters**: + - Ensure you're passing the correct parameters to the function. + - For payable functions (red buttons), verify you're sending the correct amount. + +## Remix takes a long time to load or becomes unresponsive + +- **Clear browser cache**: + - Clear your browser's cache and cookies. + - Restart your browser. + +- **Disable unnecessary plugins**: + - In Remix, deactivate plugins you're not using via the Plugin Manager. + +- **Use a supported browser**: + - Use Chrome, Firefox, or Brave for the best compatibility. + - Ensure your browser is up to date. + +## Changes to files or folders don't appear in the File Explorer + +- Click the refresh icon in the **File Explorer**. +- Switch to a different tab and back to **File Explorer**. +- Save your work and reload the Remix IDE page. + + --- Page Title: Use Hardhat with Polkadot Hub @@ -11108,76 +11353,45 @@ Ready to explore the specifics? Dive into these guides to continue your Hardhat --- -Page Title: Use the Polkadot Remix IDE +Page Title: Use the Remix IDE on Polkadot Hub - Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md - Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/get-started/ -- Summary: Explore the smart contract development and deployment process on Asset Hub using Remix IDE, a visual IDE for blockchain developers. +- Summary: Explore the smart contract development and deployment process on Polkadot Hub using Remix IDE, a visual IDE for blockchain developers. # Remix IDE -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -
-- :octicons-code-16:{ .lg .middle } __Deploy NFTs Using Remix IDE__ - - --- - - Mint your NFT on Polkadot's Asset Hub. Use PolkaVM and OpenZeppelin to bring your digital asset to life with Polkadot Remix IDE. - -
- [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} - -- :octicons-code-16:{ .lg .middle } __Deploy ERC20s Using Remix IDE__ - - --- - - Mint your custom ERC-20 token on Polkadot's Asset Hub. Leverage PolkaVM and Polkadot Remix IDE to bring your blockchain project to life. - -
- [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} -
- -!!! warning - The Polkadot Remix IDE's contract compilation functionality is currently limited to Google Chrome. Alternative browsers are not recommended for this task. - -## Overview +## Introduction -Remix IDE is a robust browser-based development environment for smart contracts. This guide will walk you through the essentials of the [Polkadot Remix IDE](https://remix.polkadot.io/){target=\_blank} to understand the processes of compiling, developing, and deploying smart contracts on Asset Hub. +Remix IDE is a robust browser-based development environment for smart contracts. This guide will walk you through the essentials of the [Remix IDE](https://remix.ethereum.org/){target=\_blank} to understand the processes of compiling, developing, and deploying smart contracts on Polkadot Hub. ## Prerequisites Before getting started, ensure you have: -- A web browser with [Talisman](https://talisman.xyz/){target=\_blank} extension installed. +- A web browser with the [MetaMask](https://metamask.io/){target=\_blank} extension installed. - Basic understanding of Solidity programming. -- Some WND test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/westend?parachain=1000){target=\_blank}). +- Some test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank}). -## Accessing Remix IDE +## Access Remix IDE -Navigate to [https://remix.polkadot.io/](https://remix.polkadot.io/){target=\_blank}. The interface will load with a default workspace containing sample contracts. +Navigate to [https://remix.ethereum.org/](https://remix.ethereum.org/){target=\_blank}. The interface will load with a default workspace containing sample contracts. ![](/images/smart-contracts/dev-environments/remix/get-started/remix-1.webp) -In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. +In this interface, you can access a file explorer, edit your code, interact with various development plugins, and use a terminal. -## Creating a New Contract +## Create a New Contract -To create a new contract using the Polkadot Remix IDE, you can follow these steps: +To create a new contract using the Remix IDE, you can follow these steps: 1. Select the **Create a new file** button in the `contracts` folder. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-2.webp) - 2. Name your file with a `.sol` extension, in this case, `Counter.sol`. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-3.webp) - -3. Write your Solidity code in the editor. +3. Write your Solidity code in the editor. You can use the following code as an example: - You can use the following code as an example: - - ???- "Counter.sol" + ??? code "Counter.sol" ```solidity // SPDX-License-Identifier: MIT @@ -11200,95 +11414,46 @@ To create a new contract using the Polkadot Remix IDE, you can follow these step } ``` - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-4.webp) + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-2.gif) -## Compiling Your Contract +## Compile Your Contract -1. To compile your contract, you need to: +To compile your contract, you need to: - 1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). - 2. Select **Compile** or use `Ctrl+S`. +1. Navigate to the **Solidity Compiler** tab. +2. Select **Compile** or use `Ctrl+S`. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-5.webp) - - !!! note - Compilation errors and warnings appear in the terminal panel at the bottom of the screen. + !!! note + Compilation errors and warnings appear in the terminal panel at the bottom of the screen. -1. After compiling your contract, you can navigate to the **File Explorer** tab (first icon in the left sidebar) and check that: - 1. The `artifact` folder is present. +3. After compiling your contract, you can navigate to the **File Explorer** tab and check that: + 1. The **artifacts** folder is present. 2. The `Counter_metadata.json` and the `Counter.json` files have been generated. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-6.webp) - -## Deploying Contracts - -1. To deploy your contract, you need to: - - 1. Navigate to the **Deploy & Run Transactions** tab (fourth icon in the left sidebar). - 2. Click the **Environment** dropdown. - 3. Select **Customize this list**. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-7.webp) - -2. Enable the **Injected Provider - Talisman** option. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-8.webp) - -4. Click again the **Environment** dropdown and select **Injected Provider - Talisman**. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-9.webp) - -4. Click the **Deploy** button and then click **Approve** in the Talisman wallet popup. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-10.webp) - -5. Once your contract is deployed successfully, you will see the following output in the Remix terminal: - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-11.webp) - -## Interacting with Contracts - -Once deployed, your contract appears in the **Deployed/Unpinned Contracts** section: - -1. Expand the contract to view available methods. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-12.webp) - - !!! tip - Pin your frequently used contracts to the **Pinned Contracts** section for easy access. - -2. To interact with the contract, you can select any of the exposed methods. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-13.webp) - - In this way, you can interact with your deployed contract by reading its state or writing to it. The button color indicates the type of interaction available: - - - **Red**: Modifies state and is payable. - - **Orange**: Modifies state only. - - **Blue**: Reads state. + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-3.gif) ## Where to Go Next -The Polkadot Remix IDE offers an environment for developing, compiling, and deploying smart contracts on Asset Hub. Its intuitive interface allows developers to easily write Solidity code, compile contracts, and interact with them directly in the browser. +Remix offers an environment for developing, compiling, and deploying smart contracts on Polkadot Hub. Its intuitive interface allows developers to easily write Solidity code, compile contracts, and interact with them directly in the browser. Explore more about smart contracts through these resources:
-- Guide __Smart Contracts on Polkadot__ +- Guide __Deploy a Contract__ --- - Dive into advanced smart contract concepts. + Learn how to deploy smart contracts using Remix IDE. - [:octicons-arrow-right-24: Get Started](/smart-contracts/) + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/deploy-a-contract/) - External __OpenZeppelin Contracts__ --- - Test your skills by deploying a simple contracts with prebuilt templates. + Test your skills by deploying simple contracts using prebuilt templates. [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank} diff --git a/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md b/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md index 52b2658ff..e91a53f47 100644 --- a/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md +++ b/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md @@ -1,5 +1,83 @@ --- +title: Deploy Contracts Using Remix IDE +description: Learn how to deploy smart contracts to the Polkadot Hub network and interact with them using the Remix IDE and wallet providers, covering deployment and state. +categories: Smart Contracts, Tooling url: https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/ --- -TODO +# Deploy Smart Contracts Using Remix IDE + +## Overview + +After compiling your smart contract in Remix IDE, the next step is to deploy it to the Polkadot Hub network. This guide will walk you through the deployment process using a wallet provider and show you how to interact with your deployed contracts directly from the Remix interface. + +## Prerequisites + +Before deploying your contract, ensure you have: + +- Completed the [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} and have a compiled contract ready. +- A compatible wallet extension installed (e.g., [MetaMask](https://metamask.io/){target=\_blank} or [Talisman](https://www.talisman.xyz/){target=\_blank}). +- Your wallet connected to the Polkadot Hub network. Check the [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} guide for more information. +- Test tokens in your wallet to cover deployment and transaction fees (available from the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank}). + +## Deploy Contracts + +The steps to use Remix IDE to deploy a contract to Polkadot Hub are as follows: + +1. Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. +2. Locate the **Deploy & Run Transactions** tab. +3. Select the **Environment** dropdown. +4. Select **Browser Extension**. +5. Select the **Injected Provider - MetaMask** option. +6. Click the **Deploy** button and then click **Confirm** in the wallet popup. + +Once your contract is deployed successfully, you will see the deployment confirmation in the Remix terminal. + +![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-1.gif) + +## Interact with Contracts + +Deployed contracts appear in the **Deployed/Unpinned Contracts** section. Follow these steps to interact with the deployed contract: + +1. Expand the contract to view available methods. + + !!! tip + Pin your frequently used contracts to the **Pinned Contracts** section for easy access. + +2. Select any of the exposed methods to interact with the contract. + + You can use these methods to interact with your deployed contract by reading or writing to its state. Remix IDE uses a color-coding scheme for method buttons to help differentiate between types of available methods as follows: + + - **Blue buttons**: indicate `view` or `pure` functions which read state only. Interactions do not create a new transaction and do not incur gas fees. + - **Orange buttons**: label `non-payable` functions which change contract state but don't accept any value (ETH or other tokens) being sent with the transaction. + - **Red buttons**: designate `payable` functions which create a transaction and can accept a value (ETH or other tokens) to send with the transaction. + +If you deployed the `Counter.sol` contract from [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank}, you can try interacting with the exposed methods as follows: + +1. Select the **GetCount** button to read the current count value. + +2. Select the **Increment** button to increment the count value. + +3. Submit the transaction and click the **Confirm** button in the wallet pop-up. + +Once the transaction is confirmed, you will see the updated count value in the Remix terminal. + +![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-2.gif) + +## Where to Go Next + +You've successfully deployed and interacted with your smart contract on Polkadot Hub using Remix IDE. Continue enhancing your development workflow with these resources: + +
+ + + +- Guide __Troubleshooting__ + + --- + + Find solutions to common issues when working with Remix IDE. + + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/troubleshooting-faq/) + +
diff --git a/.ai/pages/smart-contracts-dev-environments-remix-get-started.md b/.ai/pages/smart-contracts-dev-environments-remix-get-started.md index d5fc50a30..effb8d270 100644 --- a/.ai/pages/smart-contracts-dev-environments-remix-get-started.md +++ b/.ai/pages/smart-contracts-dev-environments-remix-get-started.md @@ -1,74 +1,43 @@ --- -title: Use the Polkadot Remix IDE -description: Explore the smart contract development and deployment process on Asset Hub using Remix IDE, a visual IDE for blockchain developers. +title: Use the Remix IDE on Polkadot Hub +description: Explore the smart contract development and deployment process on Polkadot Hub using Remix IDE, a visual IDE for blockchain developers. categories: Smart Contracts, Tooling url: https://docs.polkadot.com/smart-contracts/dev-environments/remix/get-started/ --- # Remix IDE -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -
-- :octicons-code-16:{ .lg .middle } __Deploy NFTs Using Remix IDE__ - - --- - - Mint your NFT on Polkadot's Asset Hub. Use PolkaVM and OpenZeppelin to bring your digital asset to life with Polkadot Remix IDE. - -
- [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} +## Introduction -- :octicons-code-16:{ .lg .middle } __Deploy ERC20s Using Remix IDE__ - - --- - - Mint your custom ERC-20 token on Polkadot's Asset Hub. Leverage PolkaVM and Polkadot Remix IDE to bring your blockchain project to life. - -
- [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} -
- -!!! warning - The Polkadot Remix IDE's contract compilation functionality is currently limited to Google Chrome. Alternative browsers are not recommended for this task. - -## Overview - -Remix IDE is a robust browser-based development environment for smart contracts. This guide will walk you through the essentials of the [Polkadot Remix IDE](https://remix.polkadot.io/){target=\_blank} to understand the processes of compiling, developing, and deploying smart contracts on Asset Hub. +Remix IDE is a robust browser-based development environment for smart contracts. This guide will walk you through the essentials of the [Remix IDE](https://remix.ethereum.org/){target=\_blank} to understand the processes of compiling, developing, and deploying smart contracts on Polkadot Hub. ## Prerequisites Before getting started, ensure you have: -- A web browser with [Talisman](https://talisman.xyz/){target=\_blank} extension installed. +- A web browser with the [MetaMask](https://metamask.io/){target=\_blank} extension installed. - Basic understanding of Solidity programming. -- Some WND test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](https://faucet.polkadot.io/westend?parachain=1000){target=\_blank}). +- Some test tokens to cover transaction fees (easily obtainable from the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank}). -## Accessing Remix IDE +## Access Remix IDE -Navigate to [https://remix.polkadot.io/](https://remix.polkadot.io/){target=\_blank}. The interface will load with a default workspace containing sample contracts. +Navigate to [https://remix.ethereum.org/](https://remix.ethereum.org/){target=\_blank}. The interface will load with a default workspace containing sample contracts. ![](/images/smart-contracts/dev-environments/remix/get-started/remix-1.webp) -In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. +In this interface, you can access a file explorer, edit your code, interact with various development plugins, and use a terminal. -## Creating a New Contract +## Create a New Contract -To create a new contract using the Polkadot Remix IDE, you can follow these steps: +To create a new contract using the Remix IDE, you can follow these steps: 1. Select the **Create a new file** button in the `contracts` folder. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-2.webp) - 2. Name your file with a `.sol` extension, in this case, `Counter.sol`. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-3.webp) - -3. Write your Solidity code in the editor. +3. Write your Solidity code in the editor. You can use the following code as an example: - You can use the following code as an example: - - ???- "Counter.sol" + ??? code "Counter.sol" ```solidity // SPDX-License-Identifier: MIT @@ -91,95 +60,46 @@ To create a new contract using the Polkadot Remix IDE, you can follow these step } ``` - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-4.webp) + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-2.gif) -## Compiling Your Contract +## Compile Your Contract -1. To compile your contract, you need to: +To compile your contract, you need to: - 1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). - 2. Select **Compile** or use `Ctrl+S`. +1. Navigate to the **Solidity Compiler** tab. +2. Select **Compile** or use `Ctrl+S`. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-5.webp) - - !!! note - Compilation errors and warnings appear in the terminal panel at the bottom of the screen. + !!! note + Compilation errors and warnings appear in the terminal panel at the bottom of the screen. -1. After compiling your contract, you can navigate to the **File Explorer** tab (first icon in the left sidebar) and check that: - 1. The `artifact` folder is present. +3. After compiling your contract, you can navigate to the **File Explorer** tab and check that: + 1. The **artifacts** folder is present. 2. The `Counter_metadata.json` and the `Counter.json` files have been generated. - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-6.webp) - -## Deploying Contracts - -1. To deploy your contract, you need to: - - 1. Navigate to the **Deploy & Run Transactions** tab (fourth icon in the left sidebar). - 2. Click the **Environment** dropdown. - 3. Select **Customize this list**. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-7.webp) - -2. Enable the **Injected Provider - Talisman** option. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-8.webp) - -4. Click again the **Environment** dropdown and select **Injected Provider - Talisman**. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-9.webp) - -4. Click the **Deploy** button and then click **Approve** in the Talisman wallet popup. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-10.webp) - -5. Once your contract is deployed successfully, you will see the following output in the Remix terminal: - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-11.webp) - -## Interacting with Contracts - -Once deployed, your contract appears in the **Deployed/Unpinned Contracts** section: - -1. Expand the contract to view available methods. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-12.webp) - - !!! tip - Pin your frequently used contracts to the **Pinned Contracts** section for easy access. - -2. To interact with the contract, you can select any of the exposed methods. - - ![](/images/smart-contracts/dev-environments/remix/get-started/remix-13.webp) - - In this way, you can interact with your deployed contract by reading its state or writing to it. The button color indicates the type of interaction available: - - - **Red**: Modifies state and is payable. - - **Orange**: Modifies state only. - - **Blue**: Reads state. + ![](/images/smart-contracts/dev-environments/remix/get-started/remix-3.gif) ## Where to Go Next -The Polkadot Remix IDE offers an environment for developing, compiling, and deploying smart contracts on Asset Hub. Its intuitive interface allows developers to easily write Solidity code, compile contracts, and interact with them directly in the browser. +Remix offers an environment for developing, compiling, and deploying smart contracts on Polkadot Hub. Its intuitive interface allows developers to easily write Solidity code, compile contracts, and interact with them directly in the browser. Explore more about smart contracts through these resources:
-- Guide __Smart Contracts on Polkadot__ +- Guide __Deploy a Contract__ --- - Dive into advanced smart contract concepts. + Learn how to deploy smart contracts using Remix IDE. - [:octicons-arrow-right-24: Get Started](/smart-contracts/) + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/deploy-a-contract/) - External __OpenZeppelin Contracts__ --- - Test your skills by deploying a simple contracts with prebuilt templates. + Test your skills by deploying simple contracts using prebuilt templates. [:octicons-arrow-right-24: Get Started](https://www.openzeppelin.com/solidity-contracts){target=\_blank} diff --git a/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md b/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md new file mode 100644 index 000000000..64e771cf9 --- /dev/null +++ b/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md @@ -0,0 +1,156 @@ +--- +title: Troubleshooting Remix IDE +description: Common issues related to developing, compiling, and deploying smart contracts using Remix IDE on Polkadot Hub paired with troubleshooting suggestions. +categories: Smart Contracts, Tooling +url: https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting-faq/ +--- + +# Remix IDE Troubleshooting + +This guide provides solutions to common issues you may encounter when using Remix IDE with Polkadot Hub. If you're experiencing problems with compilation, deployment, or contract interaction, you'll likely find the solution here. + +## Contract fails to compile or shows errors in the terminal + +- **Check Solidity version compatibility**: + - Ensure your contract's pragma statement matches the compiler version selected in the **Solidity Compiler** tab. + - Example: If your contract uses `pragma solidity ^0.8.0;`, select compiler version 0.8.x or higher. + +- **Review syntax errors**: + - Carefully read error messages in the terminal panel at the bottom of the screen. + - Common issues include missing semicolons, incorrect function visibility, or mismatched brackets. + +- **Clear cache and recompile**: + - Delete the `artifacts` folder in the **File Explorer**. + - Try compiling again with `Ctrl+S` or click the **Compile** button. + +## The `artifacts` folder doesn't appear after compilation + +- Ensure compilation completed successfully without errors. +- Refresh the **File Explorer** by clicking away and back to the **File Explorer** tab. +- Check that your `.sol` file is saved before compiling. + +## Remix doesn't detect your wallet extension (MetaMask, Talisman, etc.) + +- **Verify wallet installation**: + - Ensure your wallet extension is properly installed and enabled in your browser. + - Check that the extension icon appears in your browser toolbar. + +- **Refresh the page**: + - Reload the Remix IDE page and try reconnecting. + +- **Check browser permissions**: + - Ensure Remix has permission to interact with the wallet extension. + - Check your browser's extension settings. + +- **Use correct environment**: + - In the **Deploy & Run Transactions** tab, select **Browser Extension** from the **Environment** dropdown. + - Choose **Injected Provider - MetaMask** (works with most wallet providers). + +## Wallet is connected but to the wrong network + +1. Open your wallet extension. +2. Switch to the Polkadot Hub network. +3. Refresh the Remix IDE if the network change isn't detected automatically. +4. Verify the network name and chain ID match Polkadot Hub's configuration. + +## Deployment fails with "insufficient funds" or similar error + +- **Check your balance**: + - Verify you have enough test tokens in your connected wallet. + - Visit the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank} to obtain test tokens. + +- **Wait for faucet tokens**: + - Allow a few minutes for faucet transactions to complete. + - Refresh your wallet to see the updated balance. + +## Deployment transaction is rejected or fails + +- **Increase gas limit**: + - In the **Deploy & Run Transactions** tab, adjust the **Gas Limit** field. + - Try increasing it by 20-30% from the estimated amount. + +- **Check contract constructor parameters**: + - Ensure any required constructor parameters are provided correctly. + - Verify parameter types match the contract's constructor signature. + +- **Verify contract selection**: + - Ensure you've selected the correct contract from the **Contract** dropdown. + - If you have multiple contracts, make sure you're deploying the intended one. + +## The "Injected Provider - MetaMask" option doesn't appear in the Environment dropdown + +- Select **Browser Extension** from the **Environment** dropdown to populate the **Injected Provider - Metamask** option. +- Ensure your wallet extension is unlocked and active. +- Try disabling and re-enabling the wallet extension. +- Refresh the Remix IDE page. + +## Wallet rejects transactions when trying to interact with deployed contracts + +- **Check wallet unlock status**: + - Ensure your wallet is unlocked. + - Verify you're approving the transaction in the wallet pop-up. + +- **Verify sufficient gas**: + - Ensure you have enough tokens to cover the transaction fee. + - The wallet pop-up should show the estimated gas cost. + +- **Network mismatch**: + - Confirm your wallet is still connected to Polkadot Hub. + - Check that Remix is using the same network. + +## Deployed contract doesn't show in the **Deployed/Unpinned Contracts** section + +- Wait for the transaction to be confirmed on-chain. +- Check the Remix terminal for deployment confirmation. +- Scroll down in the **Deploy & Run Transactions** panel to find the deployed contracts section. +- If the deployment transaction failed, check the terminal for error messages. + +## Blue buttons (read functions) don't display return values + +- **Check the terminal**: + - Return values appear in the terminal panel at the bottom. + - Look for the decoded output section. + +- **Verify contract state**: + - Ensure the contract has been properly initialized. + - Check if the function requires a specific contract state to return values. + +- **Network connection**: + - Verify you're still connected to the correct network. + - Try refreshing the connection to your wallet. + + +## Orange/red buttons (write functions) execute, but the state doesn't change + +- **Wait for transaction confirmation**: + - Transactions need to be mined before state changes are reflected. + - Check the terminal for transaction status. + - Wait a few seconds and try rereading the state. + +- **Transaction failed**: + - Check if the transaction was actually successful in the terminal. + - Look for revert reasons or error messages. + - Verify you approved the transaction in your wallet. + +- **Check transaction parameters**: + - Ensure you're passing the correct parameters to the function. + - For payable functions (red buttons), verify you're sending the correct amount. + +## Remix takes a long time to load or becomes unresponsive + +- **Clear browser cache**: + - Clear your browser's cache and cookies. + - Restart your browser. + +- **Disable unnecessary plugins**: + - In Remix, deactivate plugins you're not using via the Plugin Manager. + +- **Use a supported browser**: + - Use Chrome, Firefox, or Brave for the best compatibility. + - Ensure your browser is up to date. + +## Changes to files or folders don't appear in the File Explorer + +- Click the refresh icon in the **File Explorer**. +- Switch to a different tab and back to **File Explorer**. +- Save your work and reload the Remix IDE page. diff --git a/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md b/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md deleted file mode 100644 index afc5441ff..000000000 --- a/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting/ ---- - -TODO diff --git a/.ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md b/.ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md deleted file mode 100644 index 9171898a2..000000000 --- a/.ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/smart-contracts/dev-environments/remix/verify-a-contract/ ---- - -TODO diff --git a/.ai/site-index.json b/.ai/site-index.json index 39d5f0a1d..ed6c41e58 100644 --- a/.ai/site-index.json +++ b/.ai/site-index.json @@ -7534,27 +7534,54 @@ }, { "id": "smart-contracts-dev-environments-remix-deploy-a-contract", - "title": "smart-contracts-dev-environments-remix-deploy-a-contract", + "title": "Deploy Contracts Using Remix IDE", "slug": "smart-contracts-dev-environments-remix-deploy-a-contract", "categories": [ - "Uncategorized" + "Smart Contracts", + "Tooling" ], "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md", "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/", - "preview": "TODO", - "outline": [], + "preview": "After compiling your smart contract in Remix IDE, the next step is to deploy it to the Polkadot Hub network. This guide will walk you through the deployment process using a wallet provider and show you how to interact with your deployed contracts directly from the Remix interface.", + "outline": [ + { + "depth": 2, + "title": "Overview", + "anchor": "overview" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" + }, + { + "depth": 2, + "title": "Deploy Contracts", + "anchor": "deploy-contracts" + }, + { + "depth": 2, + "title": "Interact with Contracts", + "anchor": "interact-with-contracts" + }, + { + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" + } + ], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 3828, + "words": 565, + "headings": 5, + "estimated_token_count_total": 887 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:00209001a769a1bce5d78b123dcb0d4243e8fd80a77d3b7fd55cf35635bd980b", "token_estimator": "heuristic-v1" }, { "id": "smart-contracts-dev-environments-remix-get-started", - "title": "Use the Polkadot Remix IDE", + "title": "Use the Remix IDE on Polkadot Hub", "slug": "smart-contracts-dev-environments-remix-get-started", "categories": [ "Smart Contracts", @@ -7562,12 +7589,12 @@ ], "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md", "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/get-started/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**.
- :octicons-code-16:{ .lg .middle } __Deploy NFTs Using Remix IDE__", + "preview": "Remix IDE is a robust browser-based development environment for smart contracts. This guide will walk you through the essentials of the [Remix IDE](https://remix.ethereum.org/){target=\\_blank} to understand the processes of compiling, developing, and deploying smart contracts on Polkadot Hub.", "outline": [ { "depth": 2, - "title": "Overview", - "anchor": "overview" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, @@ -7576,28 +7603,18 @@ }, { "depth": 2, - "title": "Accessing Remix IDE", - "anchor": "accessing-remix-ide" - }, - { - "depth": 2, - "title": "Creating a New Contract", - "anchor": "creating-a-new-contract" - }, - { - "depth": 2, - "title": "Compiling Your Contract", - "anchor": "compiling-your-contract" + "title": "Access Remix IDE", + "anchor": "access-remix-ide" }, { "depth": 2, - "title": "Deploying Contracts", - "anchor": "deploying-contracts" + "title": "Create a New Contract", + "anchor": "create-a-new-contract" }, { "depth": 2, - "title": "Interacting with Contracts", - "anchor": "interacting-with-contracts" + "title": "Compile Your Contract", + "anchor": "compile-your-contract" }, { "depth": 2, @@ -7606,52 +7623,99 @@ } ], "stats": { - "chars": 6664, - "words": 905, - "headings": 8, - "estimated_token_count_total": 1347 + "chars": 3422, + "words": 456, + "headings": 6, + "estimated_token_count_total": 784 }, - "hash": "sha256:ceef35da1647c5f10217ad5058a5a932f0931e1c83e624539f0b67fd075eacb4", + "hash": "sha256:51d23086e729a9bd299c33409a3a647c385e1444961e0d41019455002561e009", "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-dev-environments-remix-troubleshooting", - "title": "smart-contracts-dev-environments-remix-troubleshooting", - "slug": "smart-contracts-dev-environments-remix-troubleshooting", + "id": "smart-contracts-dev-environments-remix-troubleshooting-faq", + "title": "Troubleshooting Remix IDE", + "slug": "smart-contracts-dev-environments-remix-troubleshooting-faq", "categories": [ - "Uncategorized" + "Smart Contracts", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "smart-contracts-dev-environments-remix-verify-a-contract", - "title": "smart-contracts-dev-environments-remix-verify-a-contract", - "slug": "smart-contracts-dev-environments-remix-verify-a-contract", - "categories": [ - "Uncategorized" + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md", + "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/troubleshooting-faq/", + "preview": "This guide provides solutions to common issues you may encounter when using Remix IDE with Polkadot Hub. If you're experiencing problems with compilation, deployment, or contract interaction, you'll likely find the solution here.", + "outline": [ + { + "depth": 2, + "title": "Contract fails to compile or shows errors in the terminal", + "anchor": "contract-fails-to-compile-or-shows-errors-in-the-terminal" + }, + { + "depth": 2, + "title": "The `artifacts` folder doesn't appear after compilation", + "anchor": "the-artifacts-folder-doesnt-appear-after-compilation" + }, + { + "depth": 2, + "title": "Remix doesn't detect your wallet extension (MetaMask, Talisman, etc.)", + "anchor": "remix-doesnt-detect-your-wallet-extension-metamask-talisman-etc" + }, + { + "depth": 2, + "title": "Wallet is connected but to the wrong network", + "anchor": "wallet-is-connected-but-to-the-wrong-network" + }, + { + "depth": 2, + "title": "Deployment fails with \"insufficient funds\" or similar error", + "anchor": "deployment-fails-with-insufficient-funds-or-similar-error" + }, + { + "depth": 2, + "title": "Deployment transaction is rejected or fails", + "anchor": "deployment-transaction-is-rejected-or-fails" + }, + { + "depth": 2, + "title": "The \"Injected Provider - MetaMask\" option doesn't appear in the Environment dropdown", + "anchor": "the-injected-provider-metamask-option-doesnt-appear-in-the-environment-dropdown" + }, + { + "depth": 2, + "title": "Wallet rejects transactions when trying to interact with deployed contracts", + "anchor": "wallet-rejects-transactions-when-trying-to-interact-with-deployed-contracts" + }, + { + "depth": 2, + "title": "Deployed contract doesn't show in the **Deployed/Unpinned Contracts** section", + "anchor": "deployed-contract-doesnt-show-in-the-deployedunpinned-contracts-section" + }, + { + "depth": 2, + "title": "Blue buttons (read functions) don't display return values", + "anchor": "blue-buttons-read-functions-dont-display-return-values" + }, + { + "depth": 2, + "title": "Orange/red buttons (write functions) execute, but the state doesn't change", + "anchor": "orangered-buttons-write-functions-execute-but-the-state-doesnt-change" + }, + { + "depth": 2, + "title": "Remix takes a long time to load or becomes unresponsive", + "anchor": "remix-takes-a-long-time-to-load-or-becomes-unresponsive" + }, + { + "depth": 2, + "title": "Changes to files or folders don't appear in the File Explorer", + "anchor": "changes-to-files-or-folders-dont-appear-in-the-file-explorer" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-verify-a-contract.md", - "html_url": "https://docs.polkadot.com/smart-contracts/dev-environments/remix/verify-a-contract/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 6316, + "words": 872, + "headings": 13, + "estimated_token_count_total": 1306 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:fccd676c0aee4f3dcbaccbcfb31fb6e3802445188eaea04ff79b759f018b562d", "token_estimator": "heuristic-v1" }, { diff --git a/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-1.gif b/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-1.gif new file mode 100644 index 0000000000000000000000000000000000000000..704090f00afd40dc17883415dce777076196edec GIT binary patch literal 1642689 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
J|0Ck3gw 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⋘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

{7gZ`5~gJ&IJ-DBi@P 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 z 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

Kw&$jpVhkBSxI<#QxU6pNv424=s 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�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

8!@T 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 z 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∋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®9Gx{Pr?i>SVLO!*|89BJ0lH zMu+P^bhw&p*)n2Y8|``5@h5j>pRO-0zoNVOJ=@QJWp3qfI^5VVXo<%ccTX;VHTy0G z5h;={27N1f&gPWAwDC6`?vLb>dH*bn&1>$!1BazZ3P$6X!Cg*3WreicN0c<6tt5n; z3es;BN*xh8%Ke79jzUE;?MP9{?oIB@6>_n|M0(@C($y5$)?s2SUbz6GAj52D1O%a8 z+hw4Cb<ujZ1Q2* z@jHFV;`osEBt8&$6iZ>(CEop@=+ued#vp%xgobfHZM;M_LIA0y0zQ6?EG*X8zF*d` zT~=OFjF;LjuXq_FP^L08H&)pkCNN&!G&c80{eoHfQ&IQ}_I{=Ci`oc9G`%v0g3iPS z$#?|FCMu_QsafvF>0=r;uLmAfmcz=gzuirc($(#lI(zMKaimWEx&s9pNV&F)+HJqe5Q%lv~flL6Z3?wI$%_bosP!{(6KCYEsh5lHd zJZuMT_a=OR)k-iqpTwj}Q0d9VVT7V6rERI|^o5doqcELoUEmrb&|9DR_P3*cP`m>6 z6Pc6fXb#@}kh4$o=47o()SH7twFLh{?`g-9&$NQ13O5ks>}^C!us?OU|Gwu6?nEdm zo+IO{H~}8!RK4cq@e|V#uI08(DGqL5UV_)K=#B8d-(KMELPV5dZcJV94l<8jWFp>A zCJCmXTzN-5P04n1<~>1&n}UvzKiMeZeS2{*cTn4V{Ng)#8?Ifr+{rWL%QJ!wR}Rnn$NWz+f(|!j_o??E zU*xuZ<$_ng2Pd4pJS7X`#BtkRc^*R0;bvxnK-iF>`F0oy@4x798{8j*o3F_p5x)=4 z#-MfCyRLdW7TgGLj{>s;x$zys%29W1;rP?`S$BdCH>C^BX8sD4NcZtW^WL92TwRb7 zT6yVOw||t(-hLwOoqc|}(@=zC*PU6a@JGt0YO}DK8*Iix(f1a9lwibv;7@rJ5MUiw!T~ZvrjPC{Il;TdCgZT3`1;bl z5tFG0Nh3@EIsH*Qz>?VpBrItQRVHK_OyRCc`&mL!Nl2<~Pu3AMG3T|X$*24BnS6Z3 z0#favgrO^cv_I_MqegajJJqOH;8VIf z{FM?tKz5xf!b;f&)I$`-x4f6&QMzng=dMf_NfqJXUO*#;>lQv2PULp+PNuC;SA69= z%C4N7*>l<}9@8K4+v$5B*P}9C4K#CCx`L-Chhvk`s-+whgKesunK4lNJ+b-(ww+r& zdo7-LnM8V~ctyCQh`!53E#U}B!V{T{mPOe#SormbpXbJSPmnOI;8fsMBEXg5sjG*% z-E5?u$opX1oGfN_jy|az8y_!f$y}DF)1TVg9dEt*&PI0Aubq%{Yy&x@@4RKH`!N`Y zX2_W#6OSag@HWS(l`^9QhTHWNO>JL9weZ1tkb`cLBuuP1L^iPmhuq9Eb55HoT~9T} z6GC7uB?*rXN27((3gBz>+rpW7F+zo$6f4FZ4;~38+AssU2C)^<`&1DGC3Ny#N1%v5 zGC{&Tldg;&a5FL_o{tTEb%TCeZkQk&bg_Zp9EG(Dj^Tk#w^(*^hN)p3Q@7tU;G;O+ zw9_vp<7|{y7!KV_IA7+)Foq~ynNcSfziN*4lq9((ZA=0+s1CQV1a^$H@I?Uj)<|f_ ziSN!3!}Em`&xMxgOK`+D9Ici;3ps1zXUHV>Mq_P`hZ7=DB`hM2360YcTw>A0(?_|ziW+By z6wvfIb}?z08=I<6*TmEJ$PFZu$u3M%=?eG0$*ZtcvnNQ9YqHXf-0YrO-s%(S_xgpA-zxDwG4#`)RFuiHUHB;3IdKy!DqOT?S$bfbF; z3Mf{AI(nE}u!_PmPt~pg-$Y8FY?yLF+J&7*qg9Vkkdbx3SIYab@+p5L-zP8NDR}wg z_lUv7&(413wbUg0Z68kNJo#++2bF`ABwwR9oW8<9T4od*8BrNtRJ(ML-TZcT8D}u~ z54ep*i@deA_lCijFo ziG$+DLLHPh3}~fF=|_L1iGan5LNmkQ7!~5@ijYo(SsL%$u2*T43}|$CzM@c2K4 zkwHu`ecZDq3-La)Yk zMlXTlNXQfTY@=6?g0(jsdDIiy)$LJymV=UsM>BH6O$h~jh)?0_lbOcry;{>vS~nsP z%|N#WPy#?Vo^(I>qcZv&y@aTh;;?k~Qz3 zO!(Fw58eiL3;X%r0;;&{zG?=IuqCB7>o?Lq*L$H&LLU-$+b{FAR>>LSp?ZK?f98Zq z4)xgcQ#+GWENNX5Oh$q%`L(GOzS~ww7_vnK(+vTC3kQ!NT}SjNFOjf937ES(Y_=Of zki>DP!{&a-)L}_8_rUofAnC~zI^Cy>!em@xkn|{MusF;s3i{UFbcRUX0ta0Qp~wt@ z<3hk2!meT=;J#wA{5?ny7TniEoKkub&aCPu&)X#(3n$?%I|7(VlSpp%7q6e!7SV%Ekv+-EO|YGbSp$%vkku1 z4Amrp)m1${Pcv`NC5!0RY9Rv3giyF6fpL*kXk`a+3E=!5ner3JEmAnaYe&$*1xLK# zH3e?4k!~S@@p#lD19A9d1oQ(6a>pH}yGIs0MJX)-G^B8pDVFL)QEIk9g~iEo5K!qh zNH0k$MP7`mNnsUZ`7D*3bAA3PmYjJ2+Oh}XiGu1flAh;MoaQ>$Rr!B+H&v4e>=uPU zvS7|tUKoOkju1W&1%KBCXs;5^L;@_>ib_urXj`*RB#dN=91>|JgMy2)m3|<4jeh=W ze$Nil;NU(<+W8Jj5W%^Zz{kZQWx21{a7B15cqGJI6X%kU1SoTc(MZ_UBPnU@G9@z6 zHKx^9&6xNl9a?Nrr|uM6J(O#?6a)d`U=_5k?eQrVyg={>CcRw|2C``0yFda4vjC$6 z`QKYq#ql1z(_Qd%Pey8wyoe3(+Tn4r1J#m-3l2+;L)nPQS4gu}Y$3>3+{X+z|4es5(X; zO-7Yt zKzB$W;$04cw5c~Y0S9v4DABC~)M0B|=K+tg;4!n8p(l{xPmUH?%0N8sEm>%c9Ajbl zv)0W=^vQm~oXQdeIR~}mz1-$Rea!t=N~ye0Q(Gsr#E?MNzOpOq?!C3oLkpcYdIL8x z#yhd8)6*f1T=yu<6>DE84)s#bqac5rAu7+|<1boSFWNP#TLZ!BldDmyS7SOHed)LX zGP&xkrBpeR$@LhO_opA%o_~aTWYSW0$Sid7KPII=DzpUvmE)UM3@t_ zFS;}#iDO%x`sUrN#NEZGnraJCpHCf;Z(<+H#8T?EMmu%e2lUW-B$_HGcb+EfH7Z&% z_jp1=6O`kCdGdCKY0Pmw0Smq49)_v<5;>XO=bsW>{37_nsl4#nD(id+H_`N7erAunrNE7&_W46iIf$ySkC>FZS{D{*YO+-DI(2DK5rE7`n@0}ZaTp9 zH@I{Qco-(wf8@&!bh_6yz%a-~pTNLA*b^|==Q2o@IY`}?K&lJi!h^e~;ll|4Vr zT(pa{6Z2t*7B7Zy%)`qv!>i`Q>jA@?*~8l{!#i(=*|E0)r||O3p`)GlGtZIJ?2+@9 zk&A_qi;LStELf7yw<|h`$6TJ%JnH|^f(`#V0{ewUu#8gQ9X$;|)LoQ8az?Lejxv89 zW&JgJ%@r{rSjcEGHVGc%%NY~+FjfbR$4NkwORmljHNXwbcx)F}mn%KvTCbG;ql*)3q%o^xR z-SnQ_vzdFtg5j-0>bqhLKaA&F%v1P@7HX?heCQLLkj+Sws9;%e#wgafAa1(O_f>=- z_2*vEM-ScYmEv#r2Xt$=DEf0QbU;7Fy2eRoFD&A7d_GmoQ;0>+-0ggt=`?*BZa5KZ zLYuS=T}ZR&dLl8)9~bfRZZ{q$`Q^hGr-p^^lTjIB&#V2qcz5PJKL?5B+4tanEON&WBn(gN!ACO1{$q3s8@rMdG+JgoIsr_{C=TfvF zAaU3~rcW1A)n_^b6-Qk`c|^eZqNY9^**LzJkFMb#lSUS)7MMZ~t`BO{%)n=Ai3d6@BE6 z$C7&N$!JyqRfu%&x>p6ghR5%@n{GW1K#)=!0_%v#OR(Tzc}hV+tB}o&01L&f59Hgz z6p2{x>^bsycbG7OoS?nN3&WieDCs0vAP%I~2=!`44-d%a4HOI zqA1Fk1Yfj4GWTF3dj!ojEENBQBJMVM34+v1p3?gqxMi_u*ryfBM%V~b%CP}rCqb2l zfW;)TxI)hrcjRds`Al1&fg!*HMY%214?~dj?h(!8Qa=a7g6_b@gkd&FnCBn476?-7 zo{Z{>WUgO(p5O1S8ScJ6hxA9nF$icG5#TV1>^rum#T^z;1lX&DYa;3insDj}k5>m96s6x73cw%t?2n;ug;36mZ=(?wpSXV9sFUZk=C@Z*D zWJoe%K@QW|!ZP0zJAI8lC&5F|SeRY?rS9dvbZ;v4{d|>pR+TLMtp~;0IkFLq2HW~& z1{IdwSq5JXD=j_*kun+X7}r?&#yy?3iEDL;U$=U8^4R#DPW(l@mH6Ap(x95dnx5ODz zfk%MJ^1|<6ZRnNSE6ZR0$KO7GByV1MILs`D5{&lJ&Gp*AX9UD8$Dc>`S&`FU&MLGr zQfLUvlRWn;h-LK4d>f^ruWJVz_QWOejw$~HDJRM9C`8FCHZPO00y*5sWykn#w6jKT z7EoqHVmRX`{V@fJWAcRTr$j|ibw~Eq1*d3L$&RhQ0+&^_m%%Me6tdUfc8O}|(1#pcbRro2werCv|Hw09&6;|M}14c)2pm2HjMi*D3bFUrh$J7S9 z`6=MLnWYNGv7##%SS_mSb@0eE^$Q2>d%SiUubRfrKrO;*-1Yi;_f^CU42K-KglJq%bs zpJC%#gW2Pcq!Q*H$tj6i#`m&)rsT$dA(3O@+($+OVXiTzV}%t}Ga{d~u4=31+@03d zNnak;d#TJKVHH7V-$alfW>AbdG03ERx%Eiw){3JVB=eT99GY$#wN~V7taYbndh%K9 zsw6I2?vF%%zM?{E>pvb75_NNYdmdODI~Dy{48Er~Ym>MEePQ`D&}X}IRMtk^B$oFZ zJswr^hba9-Fk-#=(c6z?(k|7}4u3&C!1PLPh1mpzH`mO z3;Fz^TLZrf`oPVllMpB1(am6Z$SJ=MobV``fMqGN_+i-(KcyCHc@1q;(Akf~WF78@ z&rHA`kKScYE(J}6b+tmGUjNSEHlY##> ze8x65Y8&YY>6X|i=`Ja0X=y2ul2A}!FhUq3rKL+m+5#QjFj6o_haxE=Dtq?%e(&cv zK0n>Z{V(i??b`b~&)2DI6GCTtqD^LV5u=t7t4c$&uCT|F2DwZ6E<140!wx zepmq)T58uuwkGGIafjlr>$GsEQ<=IHofO1xL*7p*v`k}evT6mUOumN$Vst-56aPR3 zU;ZzCxI3ebyzMqr=_V7_vzEpQ5XnQ=SHgK)!7{$R5Ce+G*JuP3wLPS@J)lavVw#@& z7MLwSRgssR=q>53Y*KqLm1P{VF4Z%S5lHc1AY1D)r4hkA)$TC;vtgE)Rb9%Z#zsbH zjPb%9=x8@r^qxGh*%(nSI%WzDAIQpO4XmQu0J@HyK?zHn+;_Sg>q8mxzMBFhhx(>_`nW!s+S}vht>oh`6u*)z6J`8 zW;1~B``1#fv}xNdv-9Vx6TNZ`myKF7No$w)eOIn|t5_G+O5N_dVg?sGY0pyxV<)Tp zERx2q!$L-C4fBM?hfW16{U$tgll*PG9p|Z+a~oB~@NcVM+crn!MLc4LUOkD2n<8!b z{2i$o=s?f-ml}|bMxP}^4w(3(7MdfI+ytj)FdA{5wB6f-a<5S!TeYetPt*{q5|432 z0l9)Ru8>`YRUO7cAKf(Bek6gc%yeV`a#s>3Raf~6-Q6hXLj+iZ&&gr2Yq7IxY?S$R zTC%xLXVrEUbfitYaat!0-h7 z?f>A1&TLxV5MKO;-ro})PdXOD2ykq0ob93#qI5LshCXEwj@um;iR{t8KVLWjdWLpU zaN#isNxMnEI(_!k^mfw7fsL9c=hsdJTYXdq3OirDxHPN@lfXr*dGTFZ9ubuy;*!ZR zbAnfwNB>p(C!OA1RoXFe7?u0-l9-Y^qOm-F^FdwK>amENxPrsr?b1U;zsl}si)UZx8mxJdiy-f-Rk4ss zU=1v(fIqj2V)T!oC6|+g19eq(3owEoKG6P95r9?t4s`DQ%e?)bz*OKnfO<_Vy7Qv@ zW4SiHMkQa#ZFvDCxxny}iX|?3pn{M7Cbg901DpYAjj?fQ$S|LeE}vLQj|&DBR3B$O zd?+Ng6$SM1JI=ZRTKf?DDofBmYm z#4u)KmLj_}5_`%Ad2N`$bc{e6-KamBvs5>j6F&ZUaWyod`5#W6LNsa&Rr0Y6{B znN8;f)^&sRL<3i#mVe{f5BBvq=ZUF*XIHZuEr9ave4hlhIE!<{w!yF5K=57az^Ep3 z6qY{<=vWVb71iTP1##StHwY%6;{d;r7)Ju$5lWE4zzgnUkJes%`vzPRD;FbRkNzZI zC1AtXQpwv1JZJFY1DTvPaP1mqB5MXG^A@%_zk-Hc%Taz+ z;8VzZ_FX+`glGZ8xLHV}#b^L` z=QZ(-8huTnS)sFi)ZJxJ}yZR&3j#ZJy(B?PJh&)%_*=&cY;}ALfo7c zc`IJ*W;z>7$)LygM#m0)XPcoe4uUij(mqh%{jaXtdMXq(6rg6nno@X0P*$y5TtN_R zJfB_0oRxd8-rae~;TjLJ#UL=;u>Kwuj8ZRq#LZJREG)++)1epEkzZ^)yuK0#^&O5B z8p&CWTZaNz;{ZusBT3;S*u;_Kj@;Dhk+hBx@}q%~^!bsD^%303NG9l7x?Vg2I+7qi zn$1a@V=;9CkGGqSwc426 z9W#EWH~u1V{AJ*1XZ3ghb9QD5RZbM$tM&1>>7$v@@z<=Tj?ByfHn>E+_yL=VL9dCS z@QLBXiILoi(dvn@j*0OB(@}X`7x%=Jq)^XaNUqUv2Vi)%x^Yf#a^7Zg!E16ceDZzb zWb+p2xNivCbYDH*j)pT+hG#ow($ex(o91!5w21FlD z3d^c2TUbtp7_BtLyP0hszb^)vBFQ%S#9tNEeY^zZ8F z^9~6Lhxpf-_m`yp*WBwIt*p zUr_*>n|fnPge8?_xe@QBwRUQAxHPb>9kS6YOtE>-%q0%tdbwR%iTw7|oO|h6fW$PO-LmYaT1!xpgPHppu>kG*D=Ep{euCY}$PBx%n| zpF!<|&^VKmA|ho#qw$ybX5C z&y+JT(Mrjogr<-Jh$9{s76oYss+oUdai!o_N=X_huts^hz*(NW3cAWocJ{ZeyX`R1 ze!k=^PXLkN%$Mlni@6lVbs&p%OG!`~fjb8G+}F0gzOh&u5|>G3TW~+woQeX0Vm*U< zzV;_e7hpnBH+U?-21JPEc2Zb<=EPFp=r+ch$m05p3(_O&!D!#cVV59f7p!VmI+iDJ z25{g@bXJPzU21q}Pfs?r04Hu!dj%_L?xf$|Tg>b%yz>uYVFvBkjt@m9-%7#$xsOeJ z(-nrI@g&9TZv$hu!A^+h9I0K>B#f&LC_3R;qKiEr9!zhMd<8*$nLw*^j9s65KHkro z30`i9EeQVH!x;=z+DnYKe~vClb~lD75t7{tAR1!HtZLZBrFe6tBs2-Av<)UzSR8ey z-9#rkivi`L05zrTk+C#B7D?e0{BR~u0Ikna4xUYt#QsFrtb<964NMDLpSd7Z_w+wfHQ=8+{k z+4kmnlba7e7m|;e!OmSego;1Q(08RwTX)u;Lr&u9*Tlh<#2z~P!}Ma#T+WtBHg*rG zkd^+waT9v0LUyadKC2=Is|W(sU+z_L*G%?^aft6q>HMnH=Bo6UYmd28X%TB^c260_ zH93Pdvb^1zg3p?w`5K{mRmm03e>kqvwbqckre+RTdAp`@x>hm2rlpaoDYC9pc1_!0 z{SdXT@8gwcx^5`)$RK}R2fJ!d^*RMycR~D>W+KrmAGiP6Z+ePpCmy=+HGA|;PQqyF6|@h zWR=e2wY*KgA^p;pNoSwUK#{bMdhv}qhW<2L!KahJh0Ra{x?d-o)KWL=nYJSGeL@wt zqBd#6MRJ_deIkdpX!iht`CEatTjk5ScX6Z`k?rG8TMvG0z4`7VAzvn^z4TaoB_ZFJ z93yERtL&SIyOosxhPHHp~_#?%=!OSl#2>Sdo(3Ij0*8?1t7)(hJro&LJN!T39gQO%FqZQ1+1r4`{LF5igq3fY@UujDVlqE5 znF4Curu^W~S@;-#pVQbgT>-d{2=b7U@MYg0)ZznL>i1^T?ox`slUSgO;0=NC&59tr9_t8Gr5UNpfRJfP-K z`mwd>bA$GY{|;9%yS!WJ_OIrCEoSglV~j?;>#>i|-D;gTBA3pv`@153e>eT1xPhvJ zePA+|>x?Tv=GM74+O(k#_;8=j=b&8rviqhxpvj$9#uwatkb61=*}Aja+5jKkW`2_I z5zPlwJoGj=gnvPu@slvOLtLaUcfZ5~Xx5&rheYI6*fy|>cs-=WPE zZHEP|;WjnuE=C^{?|R_JX>}z0!mFS^`CTc*kYbZAIX>P52lIU)bB={dU0*ljc>7xe zVn~GK4kni$CyP?r#W#-CG)tVXVP0+ng4`0r+(7MX@zDp(@fJCfbI1CS;-S>gl+Zby?%5&Eua~ z4*e6xdcAl14)5>U`RRqU-F<*&&*dP*2JRDEdXO3sAtzi-GO=>`8C;>F=f&KIGm1kHb7=0XV^w+#T-m@iB&m`Fsh2{QE zheDqB4@wvkXjV%h%2EkuPJcDF{Q|W>e`INFDflZVisr*E5Q#|Yioz;cV9*4t!FIg4 z8_nAfGCU+24P=6~8;v32ZN4Vha68_Ul=Sv_d^jn7g)`ZjB9j|Eps?INBdl$GShwx? zXe5xfH}Mt;BaOP~_?CFf0_@`p?LmNps8T$2qn7Vkd5z#jNoDC=EE_j7!$=ouk7hS` zGsD(edaRTDxMYGk-bgmg0J#+dbt<1MSKRTR{1R@Q#%Eyy`F=BMAUy8}ZzD!7$AZB1EX zelR_>y!x}bsVY2_9Ku!WZoz&}u0%HMw-U13rY2f( z{WH>FEp7Y0-4C0LXnpg`6hPkowUX`o|AQYMZOuKuL)N(XtC3vKiA8;8S>XTz<+>U8 z)6i?VAjs8;5-X5Ye~Fy)B??Z*z>uNWZpLbo9?z`UF~Q=*sy@)lsG}RB05WztvC!4o zqFh0wKB~>78i&NmrQ5AY%^0Dfy-IMI&h-OZWfulCjbcATPCw#UQuey?Mm;lFr|X~f z6mtxtB_^0W?AG`G5lIs5!n-tY!FfZyx?oCkQOf`peezGW|9w98%Y9j31#NEB3jgJLf}9FU{0f(#dp_`i*Lm zQ~Ufb4V}!=D|&`Afg@bHa|{|u!5G@BmS>hY&c3^{=8Uo7bZ)#GF&&BMN_G~oVk0Y8 zk{Idl0$A#iT9`5Gn$j#-NkKAe8+pv&ZYugd13jeL-LN_&=hhhV9mzud2d?o6HfMr1 z$-UuQf#Hln_0eAGM)fnQPPoEUQGJtgeg}3y-b#5obAlR!Crm1aqd$a6^`OrYu1utc zp~<>`kI^zRZ&^d(qK_8)QESMhQS<}~Gg|l2Ep!2fJBeo-469c%*H;t!perhtQE`M* zEl`6=L6!T$Su;cW$2Bccz$tO{bifxxN??12Ala?bl{Y}u3NzzEnI;#!`J`Ivr_m@HD{;$ozU-!I&HytW=|(6!_`^cnc>38uo-6M z^@Hm$^^w2VD`fU;6DRWC{CK^tUSj@xJ!q=4A5n4Vhl&B}2R?M?<=xajFlEHw>(>zO z=6~#pi{)Q0I1NtqJ2Pzszg|H7=w#a@+yARvZ@HPr%Hh#Le*5RJU-RAHpK}l2{UiTg zd-v`i{tsD`3MfVZ@OX#Xt(E=2y}0yVVfx-p3Da%5LCmvx&vctE02T0fW=Xc|3BkAsv35g&;Dh(hPyq53{_ z+f0&st^n6yK~G;U`hHkz#W~jAP+}^}Eo6d+6(~NU&D@5^=4Nsy`wph;FvZKS0}R;3 zuW5Q%X5Q_nhM^mV(ae^2^Vh3IH4A$`Zdl|z?x_B4w4Ezhrr zDXZx7)it_`qUWeyZplg(lel*n{k(`)AfFmd_tJCB z_#i(iQMO)sF`kp1^e*^s%CipTGlXWy+DnAUMM%1No+okyIdt=$C9b;6v(<$!L&Bd$ z+SRR}9d-7>1ggm3L%DJ4`${SW0de?x4@jt))SaTl3?BJ>uFiUI-jggWf4Lo-T2wL` zw~`_(-_>rdE*+Zl^wV0ibP>*t#&l}M(Ns(x_Gud=;|c(-p7P6^5Dacd1%GaFOyE#Q zQKG9eP-H!TEB4Gz&?X!wr4G2#P?_|5tT)-?Ai?qJ=WIiAmUN&VMRTN~#hy{76d44| zQ5J)0E%BMlxE0PELn96J=tM27Vd??h|aC3!r)d(WLoaTd?E z)PuQ+6RZDxkwvp1`GSHUqVZr_%)|Nwb}>r8_O({EyBiQZunj`v@-boM<`hy%2)*BvV-{L4uXMbs2h$G)kqVjG=!4)n;HFG;Y#CKa(v3bBB$G$fSA&t zTHH{D8wkU`(K4vCiU$VGQ*o;+wFR7OeJoPwYuVWyL|ZM;7NF?3N<%<0@{8M|lD}_8 zzV(Ma7@}7=(5VV;(DtTFq<(FtD9WTocoz0AoA3Db`?nXJWfoNa1!7R{r%%x`oHK3< zd22=veohvdfSl)S9V|U5VM|>Vbb^B`NYQ07^Y@lc{>d(XAvDs*uV}yY7|g{ zTA*L5pknDfgD75DN-zGy=qn?KHPe|s`KDL6I;pU=a%nRh$79%kxy~_1#lRB3yNXz52HbzVlrV$~luF_9=SHK3-c(*X@~7eFE?ooi?x9hptJY07$ib5NLz; zvQ4C-k$R+?w?>*lATvhnwE=Tg(fh7iE;EtEzYyJ@exmCW_POKYrQY&TBi5F`b=vp! zyy{F;vgm<_Kn^jw7MPDm9wTHZV2mvH{P$#-t2iu*3UYx46sVP-)RL2Ttf%84e+5tE zLt@R`?&Lrx5`h&j)XjWla^@dD`1um9{>_O@$+lhm?7X9XRz*1eGK_BxN!O)b16 zsdRZz)dp#EYO8vNQePtKO<6O4t;njX=c1Olz*&d9y52*?k~rZfhar zH*9DC78hDpUkHpA!uCEM774QrP))W35H_ z<`l^3gPzleM7wig50P3AX%SDwT2BoTFN0bya}jU5T5neoAD>#EAdy=UwYMIGiTGk` zeQ_dw`L%v!BL20t{>>r*U9|ykMFNLv1E)l8FV^1vA`-M&8}viu&S~wP3z1+N%J{Ho z2zy-!k7%e!U8uAue={&lLp0o=F8owj)wJ%et7wFesKO8?BBCzRu0}29mVcM7sZCu} zwn%hYogdAAQ5Ry=hExrJ`2Twk?I8=DhVPkMRWFW@<(}8lVa0Hkpv-?MdK~D4$znw= z1B;h)d{Ymv`t5!fZxNkIFoe^vjs2IRxA4@y-T(7g=hOGkDT-dFQTVOd*8lOA7I)3? z+^b`y|G%R5dHlumukYgaut>FneoXsqmMallD*y;9O2DM7q^fOWEJyriSBb-s&s3>< z%nQAzAy1u-rN$ftfqi$_1$ErHKY$vsi%f4rqr z(T`ZkpzRfJ@K3%q`#oBrwRD=F2iFr-4V3g4kG1Xl5#k>pURk1>#MNw2)a{lVzvok{&lbhFSeZTU;O!pKs2@tq%3{RllAtvh^| ze}^w8E@7)e%ed>R9&2~HrLG`OQhOuUgXfiQz70%!9GATqHIv~4JG>46Byvhn>lyzB z$@F*6CS|BJQez|(jL72Oauw=VMygfbihD9P8toYI9{fb=hm$tiJF{%(VJP(dd;r%Gg7V;QfHI_-Xd7}q65xcjBI3~T)D=V@~ z41hcRAZXVw9aI|E^A0Evuxy0um?-N;v<|>F4uZ`~`lOkX>XIXL(p#RMQo#mQ(*@U1 zrOs*t%qHAn&+F8~XU7$V4VjX1Wgq>XfK6<(Pzae6@neK%OcM{T^}+DojPGUksus`g zV{`6qwYg!njodki#{R+4l;+L}^RQa!MA(#~Iw@>wUbkEDb|L%T#|B`EtX=5K0=K zs^<*z3K-^qGHWG*X@Xnn*7Q=xxvC6GYPH&={6=K2R+P=HJ5T&6CHLvg>Zp*U*L0lG)L%{>7eD?Lq z7*i)&sgh>89w6u2%V6pz2su*%OHIvy?h%_AKLfB(fm6m_Vysqs{vhg8>H4(4&Y z2dTDq-5EU33>m*5lFVPaGni~siwvRKHSGJ0#V)6GzeXepE9o$%arX1BmJ4#|Yg_u< z29-rSV%qMk-JfTJblp$ow{&esUjKzi>3% z;L}jN`S?%`0jwJx|0@i=TNALQv9>#S!>2ie-NaR5l5X-mw!PXRw9v}Eunr`C^5iG$ z@{`?VM`fzUTA$pT7(ARk8LZNSZc(M|0ZpPp=OrVM91fW}m)?YP1RWCN_M zaK*(tN1Tl=c|A<{lkQu(zs`8CpLx7NSc%-?8Ax08UdZ7amz7z2Wo_6eT{Q2sd3Z0M z4>@U-cjw!;2$KO>O9G8z*@^P)V(aM zdGYzY6Z=W=RJCCG$~Aj6duo~2PK6O{?k1LI7>O_a`=gr#2V1g7VCT7-b9&)&FYH>f zR@7e5wf0b+0=^^-$;DKq4pA76Byoe>+AbEjpp6UGgPkA9bKH&R&4}|i+9IWh9q=*6 zZtGrZ)OeDYmH=;$)2%!hU@q6c%TSP_!#G4tRto$_tGl$@&nb=QAXm}v#9;)hH@yr8 zRxB)@X)nS%8?klTjIl@^L67dAV&AD6Etgar0?dD>>KP}y5QdSnA?abLP@V~bp=e91 zbZq#_<-vkv!Af^nuskboZ;O@anR~iBsUO)vX${Wy0%K90JfD_^l$r)GZrgEiUj&$Q zaUr|yaupL!b(q;B66V8z;W9BY6r_wy1V@cAZ4{J}c@Oy0Mf`6=Nt6{>8%z3W%{309 zwZ6=SB~C22KOexdsdl zV9X$=I$R#RPXzXA(Nn4@s(hw{#H(d(j2}r1r!CQHBxn-I=!~el;YQC@2cJQhHoDQD zJdW+}V?YJNqO5e3QR=0=xNGQUJx z93NfPW3wHED0MIVL83Ngl#e5q=8Q}L_6Lib56E=$fo0=p)d|q_dS;a<6$-TP_ZX(G z#Xw2po|OapK(Gx01VxamJTTJ7!}MDsb%Pl!QScBHB!fuLl?+dLPg_c$cV+?i&C`Yo zVHJWIp0@y}iL@jzaT+UNKmdz!jkA1Pn2T396C!WQSCn< zjpUfKPQa)Eqcm@HSQnchrMJqmJyhX#AW6z?J26 z1&Aw5buuo=wqB8;o|P_{w$5?C1a++>RI-6yojiLwc6|bJu0wggv%u|DzQY8~Te?h; zs2o{?n>?F5{s<#GfdIP>MXo8e#s6%Pq z6{91e4B^l_TKFiABGpB^eSlCNK8kH+`_^Mh<(k+#R}J3JYKPOKpr z%VI^TNdoE1d`|{EpV7KF^~ppoD!#Z@JRV(~uPB1rD$aXfqDaA<6#_$RU9y)8;M%2M zewY4XW{M<>mk!zT>(Z3XM>C0smTfB+n}{HgI%QU;ROUwk`SE32qh(r)%zKpkrJV;A zr^p-Su%kj_+)Nt80HI`rpH*=AnD=DOKwm~%gZ#T35gD{bK;1QB^A}D zy{`8pH~KudSO002$+fRO*Rdf@r4E13xx3=h9SS3K2tRB{j>0- z=|f|)vCp^-5EVxqqTQJ4-I$*xwV>?t{KM0?yHBqw^711Zq4Bj{j*X8)e0tBHPJC$U zaRmO1ZfZ#6p92IEYaUM(J^S#X3@Xu>De;Wc>RFzpTkf^yf68tb?wns&LYH+@pF*J^EEo-*XPe^ zoQhu$1~SWXk{yLOhlHJ&dD%`{#)_WP1QefX*D%nF$$0os$6LOgu}9S1JU`U2VfNMV zc9|g4*qH1*@AenC9C3A&F7R%s!)<$?g|pC;6}JT2oH+deWw$nJbff4MF{nf!VNe=B znD>+>x!{%QB-kxi!G+rnC`$y#v_P+ZY@bo^8JBSTHw(PV2c*3xGq-4e)z*$WL}p6% zw#4hIka%jtP^k{v&g8zzz++L%0JSe3B2t6!(gS$68$(@|XekkLNlr*t);eZYQ4MjuQF40t2DK+6xr0$a*q5=nyp5;a@fOvnceYj{{C>E%|O zrY@0w!wuFO7sP)+MX(2E0(jr|YwOj?nUw3%hofOWFX>ualK*fg&pdmfKx1DO0w535 zQ#zADc-Tldrm_5Pe+y^;5yv@9e+LCuCmO{h(Ein;)DPu|35-JrAg5VySFl7E5!_w= z8cg&2N5w4_D*C{3m@$>H3qnbq&(trDag9$&R5*464^-eY{bmJ3DIriKb18>6 z5|a0|dRAs3cjXnne1rBMFgSUdbHyHog8D*6gMy;C_bbC$NY9r%$- zQX#l^rv>DPkDnn*PqfHg2&N1CrJ^UqE?Mvlg_<>1Sc6x>)CTV!EX!|{#5ij;EZBa)tSi{*qU;+)T7?@aUW!JA)ai3JDn2M1P^ z0!#2WziSZz^qX90D*8k`J$o=%G*Xa7NKjMK7FBrv;{mLrfHISn9}=8Fjqc+{y)_#L zlsEy)FEQ}Q!b=XVUMXq6JMPjcb+zD>gOie%Xb6hYquL zheYbcda9?y$Q*RGg`gSu+#6L^89%Yb`TkmEy0*?M-1>V2Hjw~QPwM>9iV`DdR;!cH7eL0H;ov#>%C_*1HVI8 zb8Z)QS!*HacHID)gu-<}$#FRtjtI^cNymRG>Eq+g|VqDUg`ASyli;h`u-Yu*BO4D)7|;y!cVOD&od z5Y3ko8CNJ&=*vR{IK0#e{%Qx3C5}Mz{i75YC&{O#%A0&c*}~oDH+8c^n?@yKWlIY0 z7KT)Qnu-22tn0$U<#Ap_xKVwp=;vq64ZnMfUt#V6xJA=-pIeG{iv^oSuY5ATN_-ue z^xb##Sc>-X9T#`r{JIGwF#udX_ylH(lU9X?6n98QRgWjD0}D7rJ0nPguiW=Xzeb;a z{re2@$~owM>W58{#r3;h+|o=#W~*r--gx$vYgl*H8uzc8o|hi9bG}9Jy=@o8c|%>- z6@L)59?0LQU7G~ST4%eK)p+=J+2{00a7T1GM|6E)BiUV)RTaK^mEdHJ3qT+FD)TTc z-QSqb^7bnAzp?r$cBleuDN;G)sa6h5`tkuw)>uo%ZDVo5?w6SY*S1KdUram&CDXPF zja{8Qwo5eD%%*PPG#1&IzCx!ygJ!&uH8!)03Q2oP%X$YY-Idz&k1*#gb5NmC<08&P?FTJ)-NOp&nf0sP-@ zWUZ8&e+&G95O@#WouO}}g7{ew^!XCih=XrWK&4cWPg7E;ww2e;-=;y^V9RYXVY}>N zpWHm;FUdNfEF74P$f%CEE6UKpN7LUTJUc~yvzksnj&|8~KQ4QNp>_8%-45-{HjL?j ze&tZ^(5NyPtrkpIih@Xhh7{~Uf@BBK3q&Nx^TTAv?TaY{_z8Q!i?A$^1La4d`dH2v`_adT!tld|MV^|58FASIokPCj~nsYZuCAk#x7tmKUZMeS2p6= z`-VM?CVO978+o)OMz$j();UgQ7yawZ1>Hz zk}_-oo2GIoAJ411+ZiRR9)G_cy?E}1R)Faq+ULZlS7~)8z|UH2kK+_t1fC`Tgddas zIPnYipx`@1S_J~!u}$?12%D5!Xc_MPX)7WaF@0j?#XW3NM46f!Sq*y`F)dT6;7gV`M9 z&ujJ9cmB7BcCTf4k>^g-;cgq~W}T}pR*7@*)=0K%$3(C>rH3Z?&RUvRvwQ#b-rm>YC+|r2F`IvWNsn|SBc5J= zH~U={r45GMe~zA4VhL6wZ$H8-Qj;6p)v4u7p{?Hpilq3LCD&0x583rv-;6Zh$2Bj+ zg`st;xEr5hsXN0a71E5W8T$uNfnrq%rlMywRsJUEYpgfYJqpmF_1bynX;1kf?OuXG zw1(*%{Uei6O#m8G>`D^f9@f1U4y)tF6x=!&OL=^Y6P^9ISkl@z#h^s532w`+Ji=r< z-?Wk;hP9C;TmI|f?0@1eFn5b<^^4nR(`ER5!(6e~#!XmsW%+H0EvH{~j)s3o@T>T9 zBT+%06Ao%_+Y6&x&_LhRwNmM*3jK_5V|jntcF;fnbY;Rh3+3X@QN^x+Qm!@OVXNs< zH#m&G1+_is9bydH;;1Y!Pe)^G%uiNoGoxQBi>BQgi>|9r@c&(xrEQxEocW9`s55u; zw_oLcAOpO`5FEfaCuuqcK*1cjm78*`{W&}tEUPz!bzR-gwiwNB?zA~(?N#}vM^5bk zxqVu8Dw!N3c0I}>5B@@UIdB}q`B6Vt1`EQ{zgOlwd|kfrL=&}Q|4MAO!X(d?PG#%K ztuhW{G9$K%VQ4P$u~0%X!H}fJ3_;!?DY2qzQ7HN^wzl9G+@SXHIj9g@FJ(q>Hyu93HppmW*oMZgBL&3^Kc z=`yybb(EQPM$S!d~D_hV9iP+cvG<`^;d z3B{LH*Ic>wYMjtC`}m!+U_`d3kpr{b;~cg1D9K?HAAt>k7=kG=?zaiuKZAmPa<_1L zhu^5bdArJ6Wuw_5<*Dr8@@TL}%|p;U?@gMK;_Eh0xE05Ar1@OwnEZ%K;LcQZS6C@B zK|~oW!3;~}(;6|Yl0I%g1T~A|E&;rBqeQuo!EWW3dPaas7DPn&d=)R)&q!az>OVa+ zQGGvSTTW`$j`sMk|;aRn^tl5n%Xh>$21NI!&;@MUsk5CHq3Xp}xOWmP&la zE^FO&mlX4WMw>>vg~l6${&uZ&w#__xjgH^|`#}}Ewu_FZF8}-;7GB$RbuHB0+Gupz zP`U9sfvx#!=Z@y?>l<%R+3F()>#gaT<1vT`AufGM5Blt-4C(wPuG6&xpGM!oBgul^?(i0AlWJm=fu&9Yy>pUn_Za=t z8FWDF{G;a_<=pE(`>Q`~$NsZ7;CYnIkJm$Ehlok^k&r?|b{O1?Yyslkq{_aL0PuG7 zEWy|e4PEu|@~p_IKyL#ry7{nqSiVh;-b0iciP&t;Pv?37$aadpUb3NfOXdCYRODN^ z?5y7-Tpbl0@hyM{;N;Zk^g+90BSYSB2Tw_QrN=28K#kcMp!|jw+jN{gpz5&CTuql% z7l}b*(IDQV@*5qbBxDpoo5vzrGYWgR$(u1iohy4f-U7nq76P2_cDtJ4M*_KU6xZwvB?fY`$}vG8vM3E>ti$0fWHIWTs`^q# z_)(S;G*Qy#fS!MwPgX6Z(6H79BbKhqmaG@iR{ZiiIlHIdtG~d}G8dhmna+QC25Ing zt{fg1w|3cSN5?Wj1gL$;_c`IzJ>tW&VKH_9^uCy`WGH_k*LK_^*w!yqe`0E6_-a1j zQWWs<b4(P5bR#v&L6;Gl?KKhA|k4s4cWMvSS!C;(wk+!+sck^FM{WgvDWtQ>erX?fuHy1;VM zccDVy_yhT#p#7?~At6-iLs~m`VW(jAGhwejk?=mz#6GcHo#o1Q{szE0bqk*jYjJjC zQDc(~s2}xLhk>tOc7O`4*Dr6=ui({BRt(owG?kL7W|!t}gcig>TXdfl#i_6N(;ht4 zWPLiYDz4nbUPnEkt2fXoFrYL4R4;tM@Kd9{q@GdrfU&&9wGus(`2jO-J=0Hp2I~VB z)q2-WnfE@_;~b$`5-GGs(5zK4{Jp`<-DZ4|KE6@k!Di68THmEZ-*sTn1vKPpqmLmd zTiM{Ji+Wf63CitR-ns4Xjrx3Zhy1FC{F~aBJ^=XShge(dH&K*PbTh9NPqwfgv= zPeUO0#)n#fvzKop6Nhg)W~7bvg$HKd4IJK18ID~a-aSCwpU?c6khwrrtGzpnk$=up zZy4tVkN0A{BWskHJ91!Ugq?ts$H#^hJOmR0wbYA7GS%K0W+M*mjUIi+b&riWor_#k zf#JhPRT|;ZueFE8uH}4!<*wtup|bUZOZmsNGXlk$soVZNm0cuWDGto^NR*G=esf!i zVQCD2bSrT3uWTyT6gy(Ew*YI9NXjWO6tk*4sni>HIr^ z0*nI%gN~wh<*R<~jF>=i3?Q+dQOLU-)Ul*^@6-<6EU}mW+d~84IPvlBz~mFv0Us9OtN5K`4ndQ5q}dj4=3u5POfk0 z(Y~(++ZJG!t0&K#wGUB>nK3Dk*9{9j2XSljL>!x8fowr)u;g@02I z53rK{ycAT+s>UElh?;i~u6Z zF)BeL4#M|`v{`SHbcHVsq$yXv$$0Es0x$&ALLP3`4zmi zg*>GU;A&6JqvcrhEM9;r*BXg+4^HGEISi#R2cC6so?)I`sg^f#>SUzxK+;$ub9y#j zyxjiy@QsP~N(qB<5_dVcz{1v)gy({s|HyjJsHUQCZx={N0t5)4fYi`ChTePcMLN=Z5$PQv2_%swO#u}Qy@~WD zMY@O}O{6P`GzFz8om|fUoICEh@4G+jPy5pvYmBw$T=V%olB-F8@5>WPNudY~lWM*k zV`GRc{hr!NkSr-S2GFUNCWaulR0XZFIq7%*Tw z#fjWuaf5>dhcI<}NND<69V-S!#4w?VmARpjWHH9xEpojWHeIZs~|!E5%`CZ-Lv}6(7;4vMzDLN9SOahMM+8!V`DH8mdP0deT1=-1xp&N zXz_#n8L?|3B!jqD!HfX+%A{b}Gf{r9;Xa6sAIm9wulpB}uj8ru9k5H2xql>v@6^@a zl(a?D-7>@Q%SFBx9K)&VAh$`X1R4u{!m)iIVC%hQVyt7m2-0yF9YJP~-YKxqZ(&+)xL{{)dh;>`!E zNZ0nlpasnIZu0|Jm+|@yK|;cMoy_B%SY<|0r-Y5l1IN{q29D$!+k1wlWA4**#mh3! z&SDAbAIA|#9+pIHeMOdTkmsmKu>EPSu`}j|$t|2Ug7#t0NDE|6pL47}cEOn|zqWI%9xNB-TY1tL+S`3IArQj8Xg7 z?s&sk;`{{IP@(*oU{g{yn?$pwpNQ~w7x=HWr|dG@#5KJBPRf2dtIV(Npd|yh;)$?T zcd)Dokl{SBxhDuCkS!Ala?o}QTt$Y;f^4huyM6=P|K%$aeR*KyyHua0b+i8m;Vo86 zNWNZR{TlIFI!T|)uk~y2x-`TPMo$@>C|aNDQ2T9dxUNAi=SEh*Z$py2jn-zQQO&Z4 znnQJT(WC23O>ux-T)<~WX8w>wnJ}oP4GOx03ZYXrFQHi37-3xnv?M4G@uOt7QDovv zwzU*em2X+wAAauLTjr&lNkC?6Nf=bkwJcdT<(bUcWQx(v-}+G;&jaJ1LZrpQ-m338D9)JgZXH5Sb2}>}WSGFq&{yafDfmm0S_?EEnCxg;8DR63pdwhS-*%CUc z3#D(P+2@4yWu}dsrl%=#UG3(0=7?{G9DwP#epME8GIBBdK)+-J6KGfu`6g(D_4w%D z*Lk{!kSt6vHDpR{rEj8Jebqwe^>zR4_SSkXMy82|21v zS8qE~&_8l!wUlFjB6aszwN6QP=xFMc_7reDS{eLoKU1dUo!YCWyZN_4&4MjBW{HT`z}VUc){p#xoNBobY3;Ys$|cfRAf7@e&*OF@jt~raD+N;1O07K z_x3Rl*fs`DZKPH)H_`e$FjBBK-uU!%NiQ1z#37&;X10&Vws$5wd+OGZuTf1~;(6Xb=^9%Z< z2a{MP$YOl`YSPrR85(j^<^U(-R33zfAtOn^HflZ$73>*3i( zg$E@*;J;XM_E^yE44ublK6`Fl@|`6QY_P=6tc;yI0X<|y-+?nJa2&M4N2pvHLaW%sn-x>C^K`_P@R>`+Ln15${6uGu; z>5eP$YCgBvwFt235Z!4HN*PG`@-F@lCZQ?G=xHCT(x#FeIDP4*W9zku9yVyXL8i+> z&%w&%g}@MTIr`b!h5K!tg&?_a?$ukG4`_kR8rny+_#pC#faEqp_!JxgUqKOD=8 zBBX~!Z&vC)d0HKP`%~9Zw(@QN;cB4)oxOsHdqhuu8WmR9rwu& zQM@Q&i7RIOHC=K4Ng2UcR{WpvsDkHuYM6No`c5s&=JnGU^AepEM~$z4BmY6~^vE0) zzoZH$AKn++h-B69ei6YC>+t<0b9wdqcOeeyY#|b_XVRIDFt_Zdx9+EjE!WE_`TZA% zc7Ag7=b_b46*<@!fWO&G2~Fx#VHzX8?&HHJp>m=96k^p-4t@4jD2v-c z@8<#8wX1B5pqysIR|P4=x-Lt>q^`R>p;&X~vs|^NR5t(oas6QM#-+rdV%UScbitjM zXlmJNMAMpreE&@vk5cIjS*TLN7JKny!MFT3{yR%RsgxqXIA3aC{8OkBVn&ZWG0xt)oWW^SQU-mhDXQ*IVeSo>88F(I z#~3jvBs7itb3UM(j+sec^QYdpl%|s2nE$>`75`G=RrxA^%5HT5BW_%_>&O1CoE($J zPQHF_>>maZH+|@CbQ3`Vo=1b z%;6UYK9`;utAFvsvRNoLJYYIN8>mVS zpuV6oLmQF~WT2T;B(6+o6iyTmVB#KKOv5P$ikOErMlTCT5R>-4~;_RoB|Sn!?T&v);gUN49x3kC{SuM=(-ZOJ>hD6#JH^xQ1CL_$H@w)R zzAnYTd-V6p^qBB%FZua1lBu!LY)Ci64fjsbAk-e4Vz-5OV=n3 zY}Ba^_memWizxhLH8?gAIC1V`nvlFKTF?5&#?5drFM^oLv?19nl!%@ct|by+mSS`H z9>9jUE#{h(YAfcZ-w)B2EDsX2jV%ETR%(l5%+mc|lQVBXw5ul@(!+kNv(3!wsDch3 zV-&f6)mIL`?wumGvi;HDgL|*2PMi6xi<|cZ@Il|RF}v`Rn_oj<)GVtpr(BUo@LtuZ zW#j*FXaXMzw$qKzTDy2eL#jSH95&|mT=F2$0%I<;O?ktLyyDqaV;;G_QSxqlD75U_6sy>A^HWmDiiUvT6(Bf?q;1B7l=#)@swb1gn~SL8_%*o%ryiR(7t?q1YfDs5r3E*auwC)% zY6wneW;K`cDhcS{tDb(^*jy$WCt&C%IFmo!TrS-$U>s6CQ*hW^p?oD^iWdA_MB7rS ztt4okUH!RCyrt^DIked-^OkC>Zb7T2>e<@hmKw(^L7M@=FAZ5OuRWE7>}IOJv^3VY z)CR-}-Cq}+>zHnN6W%T4cvL;teb`d>=t{^LAT-}c+gguN5_YAlnI95wZAgz3cIOgW z_+Z}J_^eylQ=(>JJh-)~@JiTQLuhd-tF^gYNyPVF&EjlhYs;HB5q~$KrG@F%*4A#3 zfRLJ{mBZGyo-2_+w9xVzEkou5+228PH^1NFZ5`urWg#U(E9+yYP2%VrL1Tfr>A+U)4 zkE(}4eeC~`M&J8i5QAQmXCDcH1X!OxRis&{iY8~(Z?61bG94N^>C3b1ioq(ICf79i zz+W1*HxNUuofHrBmg)Z|jUEk4A@Qd|QPL#x8_cZb#Rn`8o-ud@-pF*w=(NY$8`j@v za2XUDcGQ1=6C&aF-@Z<~Ms_02#WCYQdF_kvUwdt<7<-EfQYmp$mbql| zTY)-Ii(%C&%(;mq+1cn`MObw)rdgD2Mz4`@YGUp%2%TaezC^WmIRRvS;x-4NL^}ibUsgRY18#T++QST@yy>2|sjMidV0+xvF75ic{hhf)~G0Qf;>f z%r>;!+tL!V{oBa%dJ`3DBVW0c?mbYt#k}2CaOnrE@{w|^IZ*E@O?{w@Fc()sYi zf27guvzG}5vUe>Wa2G!F%vyQxRC2j8^VNQPW2=sEed#5c82D!3iIE_8<0-<^_sRfI z!Z4ybYvU&tWC}=ntA6`$ZDPVsu!-Bh#CM<@UnhK*i99@`Cth zz&x9{-QwZ1|MGQ4eE8^i{$IY%as*b-(9({= zj}AR9_B7uxIW0KU?qB&lySNNSFr^bW%h{1?J3e7ZN@Ha?^(mFqNLuQ)Ec%&TtCqgYL}_Jd&y_SgY~- zqi-`$cjFQ#o~x zulYS^VP+%m;$6GkxL4|QoJLP?A;?J0Zg|C-uYc{Fy8%9RvFip-r=E%3JGFme_by)H zrDvb>L}l2#*OqTRZ*6$5wQp7}WVK**QZLyc>Y_5e2wb17OCf!YK~LLL3E9+t+zSk% zUS3Q7@o!+lLEom#V1-^nw(a9sQ6pY{ed+e*Q+^FW^~tBA7UtPJoEm>(z^=r9d#p)y z*bY^aUw`A_%7+_%eW;##>3%J5`(c0RuG%NLOv`hd{M;dkpvb^?Q_^xto^nXQRQ232 zCj+5BE)J2TWp1-z9@*jR>7O(ny|x|>9O7jQG9Ze}q+yO8LjN5}y!Tp>R!FA4`N1zS zx&gO+V=LRoMdJ^8{YSwqO$JYUR?-F4*Nelga#{hOV)I#?gzw3H_?_00d1UXz?`(gZqym~Nlzu<eTVI}

8m?j!g36n}}w<*oWF&Wi@3{jL)5xmUwQx>GP8Eb^aNM4VhhIPeS-SAwxZh&tZWj z5mYn8zXf6yVq;kexc43PHNs0Ukm2ZJmiqJowcFFTaBRnzT*kA?J2mp%mYyv!nPZM+ z)@N`-Yqc1k2e7mL^A9HRhcPDbpR5&n!$UoWvYnUY0b{-#Ndg>iQ>Fe<-Yxy~vv99) ztII}bdubxP2Xgm2(K1hH5xvJ%3KIM(MXvMMc(9LFOr)omcPz z@Ah^hXefHbe!$}zn;JNpH0VdXZWbM`j^fhHo z7>q!RNynQpy^63I#y|W`&k^qq88(O`gWA~OD~DN|Ub=FWibhc@~obaeNSu!n5KTniF}jDw#9frG#oron6A zkW(Val!Q5{8DuR2mPDiwJFJYQ#;o^)Gc?nqBKKcBlaCd@a!U=So_NFCFIV_HtZKRxs1+Df% zSDl4*C7>Pi!qEdl*(X8-RcKm$PK1{zFq5i_Q%cDzK!=Nb00C^li=p`P4A0;L(~z!u z;AR3DU?y9Kj&%HeERSS#oioK>ox7qa${|&Xd$zD8L{!jO(#oW;S;CX?;#^`k*tiZw zkE`&%IY<}@)pOxmF;tR&iVz(~r}4xkSre@6m3Tu&Ks6f=&Z zoM!jy7K4l0eYqDK*5W7`rbj+C;uKDgL^i+^e2^F|ZhD29orJ)dUt3 z>%nT^WY~Rbk3h)l`V!IuQ5rdz_hdME5Y(w1wi%2lK;+d*Qu*$~o1O96VTK>d$qP*5 z++|_0XVeVVsh#4m=nyJ{UJC8@oX99xoGBHmEla~Wp2q@f0251AqX-;{0Zvi&MDX!^ z=5kOi3`2>9>{v2|#KcAA#1Pbr^xTB)B6H$QDRi@ohSXs#frVxgFtbSr(ntNPsk+Ex zJzp59#y&&bJ~;*)GZ$9)wn|9jJEuWCrJ3qoO$k`weEc#o))!w%hC~AzQq2;O{x+fj zVyfIW@i5WI!M0qpbDVTi|@47)+Wwdq=PuRq*4>{?C9lLU^zUbf9=ZRFE$x{9u5WO~j*miFOe z^`4W*%0B|Zf|KGRZp7Z^u$_6TAM-)QIq8IqSHR5RWe=vkQ&FmFDt{RHgA5*>GEi52 z_6~~MnI1ghEGbS17qP&=vi2zfYZQy7u#cu79XJ^v2;>E$qE~G;kcNHBXzrAT)i@JR zn}VkCBnr`x{e9|^RbTy+lKnFGtyBJ3J^#uE)LTa1QttXR1pkJY#gr`L&}5c$XO?T& z3j$2G4lcD5g77t^s*aR#t4yx2zR4yQ-CPCr>%S!IlhXt<{fh`cGN<@BA~Y+WFL_UB zd>W!E0n0cOVm^ye+BV-*rD!IK%vOh0%L4}=OJ>VO_b`$A`@+~L3JLI>W?IsY#i*bK zO&wB^tM^s&Fv>B`NZYdxja4BcuJUPAwp&Dva69&|WF@03`Br5$mDej>P`HchdCc(~wMe0l3D#c(< zBQet?O50jtq7pFTGs?YS2pZ8$Mw2l;IVhNrp?^WG`;pwfw<&-B2}~EJctH)VhSBnC zDbjL4>`iB<$dud+`%?NoqYdND%UsX70ByiFKDTBBaD0v;Zy!fIJ-DnW7(M(X6vPI>^1h={3( zh|w((Tfu+WL955w@ihm6jn0H_0FX@KXxJg1 zHhvPdvtHAtLosCvEwb-3X#f`NLpdB?M)En#6bXLOfE{E|3YmgRU{pK=0}?tZSawDl zXpLISkg=?lHzRm}E@eO+0Skktv4+{MhnWT;xO$4oW61^1NBk7@n@dcG?P@5q0zrxj zke)!G^Wl?4Jjpassp!B>jZaas-()Zh(mbd3xT5|B%gEpVLcmkzt0D>TVJcmio-cCY z*yHKO%M%Q#%{kqlM!LUwWBl zvuu_F=AF*ZwBmE`ncuY+xXr=}hE4`j@EFYO@dJfAd4f%Y399&O*dzVPpbzv3Ns~7d zHF2~dqK!w?o-m3(!6ep!q@Jd)bgv{=>tjJfTErF0h zrilq_X>E?ada^g<-U|vxJ2*;7H@ykHz z)<}!+x%A=6&vw{tSPSVHKdZrPP7>ah`_Ymi?aJM$s$f#-Kdr)H0*?l+Th@uRe>LVj z`J7wU0xb-<3D8%5xbSRghQYe85C+xR)P3~O`;q$C*WFK#-hB}D_8ndr|5UZ`<^KCm zoAc#f+~u1InB9xb@mbH6ujzZoUZR_>bt@a6=Y!lRpj;bx5Gv9eVUT?wR+u;lRMny}81OTS4#q zu6Na`_s015KC$lVK0KN!JeG=I>GF6m_~z*4mFt|*k^Z|4rMnT}6W7e)W5*}Q``1=f z(*N$o@2QHg%HMAkRNc0C>IUiiHKd(2TLC8@-G{P+zj4sA&w8YgD3LXSgnPa-{5gQD z9NNwKqVJx9PZNp@6Mlw~IIXTi1}q9K4gT7k&9`I?P;KeGqMf61)%ktIgACIC=DFHq zQ~J)cf_>AS@Jr(1Zq38<;=4!9PtL6;&YKA5m;e5DvHyGJV&mn31ZIM`;bFR)37$kn z0}UvlNU+=L<>a>+0J}n3&^~||O!?&MtpqKOKxy!ySw^q-JGorOahXROs947?flkhe z-1hqSw`+Q5kR$3apw6L%?c|xsfdJ(8)#e4!fyt^W>i-Whn0?nwzAfT7m}j=Goqju4 z^Q>aii6x6?y-O`$oad#q=l#OKg>ovErw^Aa%|h;#GV#dzm4~ixZkaxnBy`K^|3{{S z?YAv4CGD#sRND;+?pJ?7**8Vk%7^{3q7e1rWR03MdXH3F=}BTfsqJkET7E7mfVjJa zjJ)~}#NgbYM9HrG(&oT*IE|G-8zOu7?ZYFX_3o}Y{15b#8;D^q?~nI%nNDXJ^A>)T zmBgj@6k9w5p<^RB;=E~?hXTHKM`8C_@1F*KA4;S45+X?i(~TFzIDch1PuXelTk0{s z8cJDQYBM=eW{r*fJ^3KMt>Bt8qx7NvsKZBw>)4J5gd*uQnt(^wS62iujPsO)yIvJQ zt$716%og9}&-u=X0#IE?;ngV!9Yh02mikF`ure@nfJ%qEL6gozQ%vi&wPX-6gAQ~G z34$l|BAMJS1BaO&COQ){F=yaO$S}Z05{@)rBQcN9ZYBwN0<@8YS}-qD1IgCxCo22K zzy7~uIufE;%Zui4*-x4hMpAQ%O|^(`i4w+gTcu6L3V#MAOq5Q3G?}OnfRd(aV4mj5 z5@41o0S_k6LZHYP&jZx}3_NCG2dpHgd!Np`q-gzPcYSIUZtL}e@}Dg-(DI+5FScyf z#-l;1b;<2rTKJN06;H&Xf4-KrU09J(?#)G4(uqUVN}0^p=&cqRr`VJ3HmA6&4H-w- zX-1ocPy(@xT@szAvYq+3hh zDH5q&X|+Lnlt+2K@Ebn!EC|_*@_H2mI`=9<-ym);rr-l#v;?~L;qdHe@FWxsr2WO@O$49s?1(Pf5eV|lBnbsS{#3`mbFbX>cURE}GeIo)W$=Mkd(aRo_T|CbBl?(!ABo?+3>=r(VhNd$A#{aI>M(R4Pnz(t zhRxjbiVK^w#CHFk*J4->Nc`Zv{;DowuKQ#;{zNHq70b{Q`TdEEa@3DpYe(}fO3rn5 z@$wVb-Nm~1$}xLwTRky<-howO51PFCDeUG(9_(z*d3`G`Q&>J`7uk&1A-|}r?@zw? zL)gN_8=rz{^?RRkWvt!|T%i_rPg<|?$C2dAPJo*WIEYm}%5y~h_Ng{0Rrn+U%?>OA z4{3uC7JVqbRObtec6EB?K`7xSa_eW2#`E>8naLW5O- zx>7%>9N;7mdMvT*MAwAS61191w*DWPPWV*H{pD}B2IfIR+<_=BO*f|5c5Ug_skDcQ zZY&#&Iuuli(0ViW*;_-!^#5o$cow4T7Rf8Xu zBM0Wb19~EoU>td)cG^>1m#FXtMVwE)^6%hO`>o4SzH{&j zEJevdCSI&+#Sg)~ynjq3t0uDjB!NOroen>lXj&*jVN}nq>lSH{{`288p8==E${l?H zNhCRpRA5o|xwJoLYT=jrWi0t;#)&r&!-N9YozV`XK;@Z-D~i5S+2rG8On>1&ZsG35 zkLF$$9Oc(^mEGR<=jpEsxp|-gXtO7IPj}f<%AKxZkeqGvEm+E=yIY0j5K-P z_8A!Il0JUklx>v9!$VB{8MkypTRI(nhs(6jWPertCc~+7<)&Wv+%$>y?~|73 zmbjlOeh%x;TRJxnET2991MtVs3GLs;Yz}@?gIqkh4J+*xs#jeUUzie%Tmw=+vR^dL z03x}OWZb%_+m-k!#zLYTKHV3@9=aL%$yQItOE@84%)6d@|iKulcxH0`{9hMmm zN>{MC&pN@FCN;F_TSA^Bz$lY;wiEPFh>+Wl04V(dg<3w&-Ru&*MF$hZw{uP4X?tY9yv z9G<831L;S|G6J8H_;E~<`1IfM)+ZsU5Sc(;kr+i?sNKK4m>>EP#n6TClVleyKqhe9 zbuqL9TP@7i-9QX2AKh#z+6t#%!ta&{jzgt$(N#t~d|_8VJcC=x=?r=3Q(2en46NZf z{7HO;1*E@}v&hW@!dqLEmV};I_RzpGZ>iIym_pr`H?FbZE*2;8lVf7`3=-NryeD^a z$B1U{AN4RS(E7`rUL4zNHAoGLphOKUJ%+-|0Fjs~@2rw1p6Yb3@qtOX31nCH64GbZ zFuRqz$bS+yIblH>`ZfT1#IgWjFPBtu_s^G+#Hg`vIM@8SQ`vLhS6OEzV-6DCYt_{{xqUwAy{>Z0lY_JE~ z=S%Q7Q9SbMzB7T$z1QI#2~j4T^v&iOI{@f0%n_HQpA`w$kwup?j0ELa6GO{vn|uAeugu@ekcLjUzQ4Yor{v z`LW#S3~6Nko>Ya z;b8b!BRG$UI2K}KD$|`^*BMg?A$lAS#~>#=!GTE0Y}DI65|LA|7an!fP+AUrF2&Em z7_7L-2}!z;m^hL^j!678$0PGfxnL+&Itr~AN%EOyf*P})5ahX?5^7u4GP#K1u%ma8 z{YDtEcmZ~TcWVD^X9Mg`@$1D;=yZY%+ivT_>|z+F0s10HA;t)e$ot%_GUM3Zi7C|`bf zC*(eOtsvcY)T$VrgWV_k*Qh{hm_fx+sU1l)Z%V0^ugZ-ejqSz8M}l2oI6g+49t$@s zf>~s{uE$sGBOOix{+fijUVK~P4I@I+R}HoQiZ(;-wk&|?Z8B#sH;Ny5t^S%wU4T#X z<;uF?Hah7}vUJf=hlOlMfgtJbx;*c4cdp;yT1d{mIwX`U7l0P7$2<~mMXn|~ zjNTk;vcA6DAs66n4U$kUh_Q3|eK=tLqpS>fr^8ze5{6>zmr{F;Qr%B9pCr9|t3w(u zPq+|M5U_Zk_PWFEUTIr)9e6$=n+p<#Bh8l7L+vL}sP-Cg^Q(_Ci8a-gPYsFicZ@_ zfU3W)-Urk&Qpv9#gv@BQKP*d)#lOfISHI9bu+u{0NI4|YHvAA)=Y)TPl>~6)jUiN= zEEFR$B3)=gPN~!5o(+5gazAnFC zn!1$i8QO=;OXi(K^?n=`Y9BbJ_=s4o&F@c^sO(Aw;A!W}MuZUeLi$@38;r%J1+zYG z=X1_$sLYonUiG1RZjD_Djgb#cf*VI72TlFOM+EUeo=dEfZqnQlDWX&twNLs%yh!dP zk9Zyr&0c}IYD>KHm{LO02NsBvt{HMwkcP*|DVoh_hBPaOgDHAkEA`10nea)R$nr|l|buq#GgB;as zGIIeY=lV!^EK6`HCn-Z2uk&!X4+zMs=;swH{19}@mM$uJOO{j%{o76P)Dr4338ypU zxO!*rI&zWEb4-WpC0E#eQ3P<1uc6RrM0dY7RAKU!XYAL8+l!KZFf>5`?}^J>j*iF{ zjMGsFEtO`FwG(}ngv4`0SVuZ(x5lm%1SpyIuIGjIG` z?K4_IiG@F`DjwHFC47MBA|<)hka$4U1(qISQENL&u(_=Bk%tQ;yyZ0|p0Gzgx$3%D z<0mzLTZJb<%}dyouyii+Lz_dL$ke~ zE#Wm4XlE{rDwhzX_4V`ONOyclmLq9qKS5u_VUL@~!M^osgs%)n#b~|EO&o@Rgm#-# z_y8k4KoD*mnb|GR$|Q-|HoNV_KkiKa-oPuRZ%X1g$8Ff?-%%nI>Shh&w|fWUh*)jP zC%fmjo|dNxA`z2ABp=%?zQc9T@to^;e^(of7JM?9_w^xs^5+WD+u&==qAiPfs?_3! zk;2C8n!qJ*`K)vL7=+^m&NAyotv-)9m&ojGo)#r%Qf>f8>=GFfvA}GTyOMRc&?l`Z zQdBTH2!V~Vp@_VViz33tds`Ek0#SUb~KB#&HyzxBRD^+uCykdQ9O?_OdHMYegN z6xO%fl#RTMcoKUAqqaL^`Z#)W0vuh=VC?Sye9cGX`!x#9_SMA@^VNsEMm7NF@}0Z( zC%4h33gJ~glYlmUdYr%~7%Gw@ub%ys6>_%nJ+JhG7RL;kEs4JEC#r+SFoRyc9+*Cj zgaR*Q;pr+pW3N~Yk;?D8s{e$3I=Im4HVNV_WYr;8W1PC$?*6pQk|S1Z+I&uLNf0oA z71u@{-Bu{?dlV7+-nD>!IPPaRgvtDEhl@SsUy`?K8->LmZG*=wTNQ}Ah=fET!M7o2 zX*V)}OeH%Rdn+0XD}F-$U_z9T;(~__G$G+rm?xC#M`2vHDr+`BNyw zxAf7^vh<(jn4d+hKWm16zW(yFcJt?(f4+615Q*Ncg6oQSHoLpt=w&tJTaq@baLBF6 z?{c1=_FrW5ZTa7F`eE~kXq>5eGf?E0zutjRP)6GHYq#UlG6{LUAVHrfM}Il}orWoR zP09GEwAIJ2Jd|!tC84`rAfEx@c{BB*Dc-$l>Ae~4z0X#Avz~ij!uRIBaQHI&O(<7h zPB9DF_~~~Lf!h-Z?2$MM2=Oy+n?=!^0wVLT)?L&UY~YdS;Pvjl5^h+z5nkAVu4I{i z1ONJV?GtZ6tgB-{*!cQ|*w82UL+OX%<|V)X{WjsM_!s`?1oP+g*`KrWKj*DCZ%4sO z{#u$|urtwHH^|p9n27QHzn`8QsP89vZw{mv{?zswa`Xy%9f013!@FKP%P(w7?ITTF zYgQ!bV|VRP`!o|$s}w=^(Sdu<1dfLw;o%1_vNtKMMWY)#>ObtCtla`Oo9DbRM>^|i z`sm$xSma5s_LW=+p?b)z0x@$tmwX-MSIbqo(@isN&P9?D|ZPgBf_z} z^*;sn{s>XrncP1YLb1<8vCvlWN|Nw9xll8}mw!d!qSFQU34Hh87r4fSwF6H=u#oq_ zW8v>O0b2AjRq4O!PWHL)T}^{YRuS~cVMTrsjC)d5C>(?Yz>J7wX2hYbPm{b(Z_W(# zT^xZq5~k;vy9wRbT4u86J$C8o1=0T-%gBx zN1^f}k@(XW@6TS&ofT|FC9~s_v1f&U&f@nU%pR78QI!vdm+aC>bLX9AVb3db&#NlV ztJ}_N-k-moJFne3e{*tP2fnByAlVV<>Ti(TIi$ouP=STe6oxCV8nrzYb%!CkC^zmUb(F+vRC-1vfpz4; z_E=|!mtOm;3px^ za=p($IN&4nGvHntH*dL+;uw>1o;=!VBYtmjnoWp(QFoT86Zxwm>IDJJN(5mQyQXP& z*@yQhk~4@K@^6w43R>b-tJL>7hf|sE>hI16t*az+YDEkCh?nXLT1+n2H#Bhkk4%Sd zO(h9V!8;ap#5ajozk}*($lki?%7o$~SC7>aAxv_nHxR?lyNVl#A?$g}e;@|bQ2Sq@ zg=XKm>a?F<_Ee~VRm!U_C1q13(Q@it!3|^YXyu`s%YO5SPlN%SpR3`|(}wjF8&M{Q zu*_K%t2~)EKX(@n9Veot+>~={k9?-9CFl+prs0fbGM+O%$dYi!(o}&ZqGG`N-p)FX zkFktFu3FinJc3{4f=j<=S(KNa<#vjhrBOP0PP9A3MC?*@{NnyL6KnWNV)mo^t3t8M z1LlVba{9}w=C{a8^?6R=zyuCF0*)kQiiD%c1l!?gO8HZGB8@(T1AOHX`bmyZdNiR3 z+)1zwRj{10)<)5Un}!HD=Hw;A7r4L1iH+KPRmrBwVGzPQlr#Cl59ZgkRW>WRJkiIx zOlmbQw+0*-X0fmU*~^fn2hAdnHDI8%$*(GaOjGq-f*90&B~U`pefc)6*=NodB6fqB zIx}T1IkDR`o1AH@1zr^fk-w|>QWA={z3^W*e70ZV=*iddvA-=UT;^(J*K?$s>uJCU zJl-eqdGuR>%2&bi993n{qXny>zHg^se_)9dS}BqOKH5f?>t=K?GnXMv!jDB7T3{_~ zK3sJneDWFpcX-)@kBfK>HC@WBLIbdx{a(YY`BFuIXSBgfccusBnduBq{pLG=zMb8-#nVYjr6l`?EM+dxHCo?6UiH*@$F z-kQbw7TghHn!vxa);ct9z@geUeRtA2`UyS17X*>cOYt$WkBSoG;|*h##*4*_%a2bN zhz3+3Fz#a&j^04YX+5EC$r&SsE6LAh21-)1miBRfr?6`SBMwH%4Vky?3|)lOjC2!+ z-22YSh1C+Cn)10!l87;9C*3JSL)l#)e|rWP=YSP7?;!HRq;-)PsI>nAZ8LB@4nXai zEVtpDtYUu_YxSioYHVdewv2W6`Gv{b(g=*%PI-xOhDY&Z<8#N#2YO#05^PG+q}%M@ zv#Gf)8ZWd)%%*4def$!q0c-R5c&6g&9Q5+Gt!bm4F8ftU&~2;AoJ=R6$7@=xk*Kk_ z_dq>OPBmM1wanW#uj_hFK93J8Uj1E)SGgt}H>FNeC)s~(QRB95L)?C2;84v%e%;4j ze23DHDi#jp;_oAK99L(s?bkY{saX;6;B)`g%aAddcwdTxOekZ3ULVvG4>gdP3jS~x z(GP)}qSzVkfP_WGsa3WU*hBM-9@YoZxQ!68EaHf%U%YB)^U6M(5V;7%|v8z1^En9 z**-50;4ex``4M0qLEA3{+IgIE(`J3#K}=@ep2^5K#BZByWsrQ>e@pJJ5&NCev+tT2 zexJQH*(scKn&&{gkH)es^TvWcS>MdRNutTeKJ=?RDtf$~x#nb>m-=#)|347Jxx|DD ziUaC)96&$p>@i1R~gxVKKubsv7CoB8$rNC zPD@N?b(d9gGWF7SKjvwRK-DJmxY-Ue;a)^DaPgVpnO-U`kNSb1!!7x9X>Zai&-w}= zv@Zs2&=~{>X^c%crQa!`IG&>86FE^f4Yzzc!nPkpUs|fgJJ?I1*3M1uIrq}IT7cp$ zzn_GsOJn@~zB_;TwKRnqvGIv%P{aNHxvmVbxar!R`F(YIUVAQaJhI7RAH`--OsbaQ zLQbU7FG9#nj=$1iBzS8aztJgJVQsmA81~FgB4FB=8n}P5U>Kwr>ct3f()1={8mu1o z_oYj|O6iqpx*)psW0g~?k{B9JWKw7=3;`WEc z(odWJJz@auYSm4j$9z4mo_k01`|dPs_uHvwZTE%I-53dTG>fy0H~l9Zh_Hrx6Bfv| z;MS)NI)9?i-DgbzwdB&<`d#5u5seFRIe@wReg17@Lvc5Z%b;`kX$d}{Fl?kc|fID zkfOr#JG&qpNVYmM8~>7HJj*bReIS_?l`{*yQ$*(y(EB)b*Cj*6IZwxApBnwt#m2+5 znVfe^iPt-bORVcS?^!19#a?1PU6s0ksx7V1>HszDLlXV4T890+Y~`m@Y)uzY4gSqJ zXAU04A^M#(l_-_0&BBR_47GIA!I`mCmTt@*=RGG9qyfF;zcsy zU*{|~6=teFdIG-$y#II(=6r?%+`CDISIxt!X!bQRZx`>F>l_O27C}9F_4U1bIkUmE zX0bMgl^@HTaP8FVEYKowM*o)x21PJ!gXOUkw6Z^ z4@@fingXdLNq#Sn*|BWGZuicfn7eZ@v|G}tHBaU~=0rXQs-f=YOhG+Vk<2;Hyvbpa zNsseg*@}Ay-7DaW@xA|ytl$e;8F1Q_H--!UCDY+*dBAwPG)PVNz3g(o$gVN=K3Mch z`@m<0GBnp(kw}d@BVtdLGL=}lRD*J#L?Y+2#Bm>UDO#=)C3uMzJno}~YEbX@OAM+} zentrn_9=c=<-@5{16lqf({b*tWl;N^09a;_t?ZXrwvKOJmhM%p>0On$iOWwVXi(;8 zP^S`$?5f^H3^0Bs;?)G)g=tVvl1Nk{DVPQriSEn&P^H>e=L_wJ9VZA1_erp5h>R>j z<@*uM_r>Hmx4o0)Ak+uY|q_qosge%a<4m3xG~bEgoIkg~buo{(H? zbIGNWYb4d?mRl|*Nw*;pib6@)&+q@wU!TwWJRa}QIj{44_5+mrOcA?)P)9th~cWmEbVFb2-4;l*ku}_lWRQ@q|kg%1TfehjPDAj<6d!6|Vk=67tS-Qf*3EZNB~ER`wd3eQ&2{ zwC`sidq}UHoRQ?TB-;|sJf^V;NR5V7DsE+jEa^=xWTaUY&cldT~M7m;LZr0@Ua&?rj5VMzkp7KW-+Go56QLlDEa7rzfOh~ZE( z0cpg1)vjmiZ8J5C0#Te*hPy{Q-+f|ZFl z=o$=!4*j^_XAov5%k`e6gUsbQabhz?Qh@M@R)=5#&_y791gBbz&yhw%vxtOnowHhD z0DduK_EWHkezmStg%y&hX6c-gn8){Na{y52Z%J$kFNd1dnULt=--*X0mm1Dkf5{ANp-$Gt1Hecx|^= zuV+N7sL!B6K>Ket-h!$fmW=N@W<+r^st~AO>a}9^?H!~@C-w>C1PeBQv6AD!cvw1# zdO4p^uH}C1+-uv!10-I_RwfDl`TV1JgzYyphklOPd;E~5PL4dSP`V1rc zjAM=}u@_kcQV1g%Wz+_Z+?72#2&*Y(J-ujvLhAzSQl@Z(HRDQYpAy3Y0HFABeBfh& z^f*(Z8i~kBqUTqJVG&953j>oQV>WwKs%v=81vHr?9yZ;x!!WLA_o{3M>1;2B1+g$D zDZO7TWY-lQ`K1IDlem8~w7&qfCy9yzecA}B85yKk)Q6#fkja+9vmeYiNw0O2H*Ni_ zJuC%v2y)*2LXk|~NCKvaA((@n0#3A#p{kAYtjChgzPw~%z?g#++zQjYtEh2!+JZ$Y zH6gy%EHn=xE#ce|0=&30mX?Mj^!h?2uCGMY<@~<5bqwEXfDBDI&!PA?nTzqV_4$MI8QrOEs{-zL3{5 z95%#5%!DKH!U4(J?2GxPtl|fN#5$8_^ZT!*{x?c&>(Xw%;rnj7?F2h40ji!N6athm zNYUz=F#qsLp(q(grYfydF_uLl27UM9nW~IC0|p=k3!vmaN!x-c`X%26ohsr@-H#%Q z1psSCuGhFL@3?C$dpExQI_F#i(x0W=V+1earp#@rc<(;fS5)&Od1*~DPni6v5wJBw z+T)nCnMt4a4g+t=e1K%)St-htK4VKJ${Ki@`y9{oSCj3)R`p2a44~}?rHu=qvFinJ zy~hX#q4K4JzcRFAh&h#{fI*<%HsP^uGFk+rDL0QMD;TH}dW!qdn+$wRuVxoBRGpBX z!J*lH3bmrprA`o~ki|EF2JI@nuh_juwP&zxVPwg~)DwkOTl_46=Ch8k-+j36t!UHy zdCB*aIj+|#gj$xTsQ4_b!-o^KVj&hHMIdviBgYAtlpjWYiYtsJACflS^UMmzCsVkr zZHo37hh+z|ZCgr22PDL6Ic`*cTmG1);05a;0+}%_;071*PLZ~?t461)vj&ck6AGNf z*@zHlUr)WpsR|}?VQ1);+8b$Xo8qP|`%f8V<6_;KW6*yv36sB5PP=5y?1jx*O{57?P)ZaM|1@NUpw#*$e zYWs?|fCKY)Sk+%|!i6w4;y|Q!XQs{cE#mj;plrVkp@#H2Fi_Pmg$D}K^Cp};AdT~J zs&+j*)eoNZ=42eC96#ve-XaR*^qJuM&@n`#9u5y78U1aBSVf=lY;sufDfqqK2rWEF zy8d`j59jG8YqJhs0_Xf#_Y<#|Xfu-hF-ZQQ|;q7Zeq7-7e_uA6jPF!AKC-b~9xR7~gnGH-1WDe#c> zs_CW9OMMPzZ8iwGQ;P`eaQrZlX#Wvoc_mhYfNziKJ#THXjF_=NiK|$mfDSL;n}5)c zkX%C|n5hjxlouNID)>Z8>!l`g3l|Sdd zm}quYLcLA+zFL6>T>R9DI{;qii}0&43p7@x%bD>u)l>`2AN)HC0td9-wtxYMm#zMK zgNeG$oa$RGkvgCqZ;&Y{I+tAf^=Wox-2?G&;2Q#V(G-r2rD~q_J6Tg)&j5ROrnv$i z>Z{k;9O61{XgPbTHW!00RXBDY6EGyFgvDkLJ&62sDaoi_#X8P-DO>Ys^+2x(K+teM z<-^?AC*c#e{o$((}0_sv7@r|<0geCB@VZK)6gu#P0~S?=Av6&%Z1mUX}e z%p1gShGnxIh8sGK@A?1D+#avOxF9|lSbe7fsn_DrHzO%(6%T(`KyDWczIJVxl3tHj zKF_?qmr9GC4BL&3!|nxWB%Itf-ZDtAslVP`-e2=1y4K6+uHyO83wzNIEi0~dk4^Mk z^zN~4uY1Pgax#sj`jy@bPEEXKn5MYf{&|l_Ij05U-Sj7+qwg((xXU4Y&}I_{QZY_@ zQQkJ{l|=eC&0b3IF`hlOZmm;gJ=t+Fx&I$5p3DNkCIQx6s43VZwugO*LmtvZeIc)P zGcLYx!g^_abVl9ka)eBSlP&lOor|dH#X(vM$xyGgclswf`m9 zRG7pbUfr-iV%T28wQ#;ve11vzP42A879#zgeoUjN!Ru4ccTPRw5k1(E>iTWdWgmU; zTdM2PvcX{4Q=bh>p;RhLj*2d__{RqEQ&&AE1y^E>^Ed42l*C72?RMUhx%I1frp z|L|Mu&%Qx}V-wbd!=FKJ8lP~)eDwm*9QHWEOenfvgA$ri9$5du816MSr+Mw4whZePEqven3`1)j1 z{p;P!JeprwmdPPr;=|c#?|#KLeYg{|^tICXkJNv(^T5U2Cuz>_8R_$)hqu1G;Azu~ zu{^X93OQYNM4UjD8LmAaw?4|5nwIIj)O2gwulaTT*txe4sLz_To^U(Pxt$rkTlxNC zXjx~+KFNRPQq8+D&F2}!!5$tRIJLj-d`3?IwXu>%1*F>FiW??$ALmR z<9}_^Y2&~J>oYQ!tqpQ4{{~6sHu@tQGMsl|X$>{XYrS{cf2HBXaqrg^)r{;{Wq}uW zr8592afpT#bk-K6M?FUKbUkgY7J*hr0rCSwvczdWi;TO{KH`vasTi6ZZ}B#pdG`b@X0u9R;_yZ< z*9iJA1R>^!U6dlEGMDez#5g(^UFj$Z96w_x>#B?isQ-1RKBIfm>BVXezfx=O{hYhl z`sz%WLI#Q;8sZg^lqg(_Yjg<8%kV|swq6o43LFVF{ zy&{U@xN`B|FSQDk9)9>WN{7otbX*u0ytj5Zm8bBdJ37{L^GD&#?DR|7>pP*B;(RW? z{#fW^G7~;={qEu3KM2DBCa}t!izt5p!}T0I;;v(RQb#AS>}n;MaI=v`DK+=D?uw-J zQUv|vp=Rwsl9}1Eh-to7ny*&9|AMSUobA~mQ8vt3IC1c{jj;cqFIT;cx*vYew<$12 zY{WH3`|;zBmqd?-qe(Y0O@Wr~`dsM~IGEJP-NKcEL7WZ%SmROx(jeO@Ib**%&;qsJ zxFj^o-z~_2B)+Vj@G{PDpG@yd$;mkpO@vmp>h)Q_!TqOcA%N03x{fWaamg2*sm2#7 z8l>G#^S@k(h$sFl=IQN&4M>(x% z9-)%5u+_}R8vz|k&|yO4V;q%yCN1I6pTj>m+qn)8NPV&Fk*@hxep&ZXgL%zcdc70>MT51j-&GJnR z=!jz4groyZ`#|->d$YG4nMhkM^i`QIYfTu6=J6<=)p1<_k?C_@t$*m@ieU@xPuNuFequS_{R(1U{tIs@dHseux z)i4cx@*crg@^}xxYJqHBl+R4Dxxai3^I=7FoN`Tb?AMJ;2uE8s?iyyFntP6tqOgYp z^Rc69K9WH}f0B~Yt;=Dz-x;{Sf%Rv*M>6(UP&RF6i_ygA}FZ|bAFh|3Nn{TFvs1IFE$+7H7eK!G&rNfO9?-7bPHcj>vP+t?8oT7x zC5Q;xse6yVi4V+eiv#kNvC=xJ1%7N6SHLmDn}2@-Al)T4Z&o5fY9S7gWdn%9Ar-|G z4N#b6yimeBA>&+mO3t||?AE;SDEsnDu>;R}yrP8cb@6xE9iDJ~jaq~YLgU`Ry&K1i zu^){YabZsRB;`VVdeq`?tT zUEWBKI(bLYt7|v=`0yr~>g-LxbMv2sh7R;9FBJIPC!bIsY_MvFpO?B6@<8-(>e{8- zYH{{MO!G%7DUu%&pg;d<1XsZ#6!>>*67>E&o_b0yG3q)uo4L7?+&ZthvM9037>qa> zTr{&pbS!V>g$um8xH)g7xJ%=9+r&~q*#8!2}Nz-HPx$O(9UcD~4?syiP!YJR>O7KedtRjD79a+Z6UZ}wjB1z=MrM=iMS-pLtya!_a|;LBH& z(Tnl3$g%?vp6TOyb?{QZ_kWX9KP&wCIjk1Dq`_toT=a(}*CWabkoEp?*V1;T(oRqo zMc(vs>4oq@+_rt812lPqh-qk8ST(AL@j|odBP(i#ctF2AJO?QP=xSI-eQWdQ5ZCDoVt+ys;LRA-teq*`qF_M@{yQ53qb}|SXBB_dhhm^ zd5N#9Qh4eAuCBX33c{Ts2abQ0N~TE9_S1gLLGN;;GvqAX2WdvKVFkUFgFN(Cqg-KC zPEB0Wjn-dF9=d1rt&bzy^C9po-|y0knqLb zn(GSyT%V)m`dw-UzP0%>Q`|o&VB*KjxvO8u(DC$%g-y&2O_B1xzq8Q2IW>>F8y;uL zpV)a+kyp~(o4$xRsz@IF-zJ^EnIM>MA+^Vnr~-(crHX~n!B4OfM)x7b6sZIf4zI}XF*e}Y$ZO_Yp@|E1D@;04aYLw-k0y8-7Ye8!@i75t+&RLSOYVFOMIhr)S zKw6O#GAS9khOcM>z&YV5yZDqt0#xV$S530OAU0N+TPU;_k^le)oaAGlMB&b2rQbI| zYzdV!*^q5(KBb8F#Vnx>2Bes={S}m1fs;PIC^bmY3{C$1$R6TMgC_#O9vh006#R1E z)*+qqEOxq4PNoQ}8d`;1=EWUkcy?d&-ljwH=6M<{aOz&Cs4rl)WY}M&qzU(3B z`$J%0;>({Q3rGd#j-Q2q`G%q@lmFtH;t%pvQ?AB~X+gW_-0tnUUG>tdOonOJjN;Or);D&Vr~JceCN#;E_2$|8vCDoAwG#6y@ug8=^7=+mY; z+((O_PgoM&3|>pRkYlsF7(ozE6^V5t8BUWzGlA7K@lRy&STf=jRp=F6=n&c%Li|#( zC12dC6jkf&r9kcH<9^QP5*nB_#%HHJOt?$-{ymwj1%)>Tb_M`=25G7N+*+L1cO36l zw)4E2&fKZbv5zA|$&}q$m|1#2XCyh$S9Npsn9_8nYp^@l5QkIy1Fkr-?XDJNw*C3; z_s7M4%3o!J&soR@0Jt2gbrYlhHMMui$&Jw90KIBh1(*H zKj;$d%rB8a2Cq0BLPm=bABut9$>%z`4#P3AWXzG$`mBXuF&Pm;6^j z83yLO7a$$y&kA}Ln~@Eq{T1=Y4f;L8JP(0l<3Mo-)R%M) zYc|2UlrK&wHhLPGGSIJISH;uH2pvyLTx(XlOuGFEm(>_aofuSTP3~^|dbQzP#SeXL z2L*eD>JuU9*I#f!8V66D<$z)uyMCo<_57;j6Tz*hpndGSYgCeWyRt1ki>7SzkN+)l zGQ8;)f7A2vO`pFveGQ8P0toRS+{WZHAzYv7TSXz{L-d9>}Si0n25k8wbu&a1Rp!LL$ zoTPQT_ek%Nw>V63?zd6}4tl6)4RIw-?>-jJ7~q~Q@DBxX<5G$4fiA5UF7*KJ!}-Jp zGBJ)l3B#@$>;ujGP36SzJ4bQ!gD`?6}aGTKAN9o;foWjakv zwA!v)muz%bWUk#Hq0R?XMdhfLD630LsL$-aoqKvcb`E|T{TB&f?$N zrq)~R>)klqEJHLN#Ub4c0wTtKJ-DF*M;q(<$;NDHJdcbfQqpbk|zaX2O z9(;#t+?95@EAvTL?!T@Z#*cHw5ITE$d~+fni|x7)eN>IUfq%;CInKUw#g(ok8;!#|=r>z8W}_oO(y{J1aQd1wRY zvPQL2S~||UhW+Cf7lq5n(f#FHwdF7O%9oS?xMgZ!HCUpFRg+i^lg&h`4t$5wd)aBp z=&&cS-+M@XXE%kx# zcx4FwJ-MWu7_#`daxSH|y!+{skt=7P?9_KZ@NRsVh^yFAY=8UUjt<gWPVA4@DO7-SG?ow{`a$9eQII|1}(W~z-4H^ z1leZTS42t%yS7(UQ>sX6Sn zTMC`c{QMM*__3~Nz1GKM!AG#cLa7P{PYCsk+(>52D3~T&P7LkkyUhq~viQ;s6ix}% zO$G@oFfHG*^b<%cbo0H!YVP{#d$bR^H5IdUUh64-YooWRw+X4^iGgvoc7iI$p=y>x z=&@c^#HhE(W%=n+mB^{sgWx(1B8`i!=^vy|$2%n#*XC#TKT;ED$znV@BJ<%+x+H01s)w{vj0b5crH40V3Rc2)5rDZYxqx^@q+y_mJYVE z1I|SXNyeEI(&Tz5A(^e+-*m$;>S>&{r+^kREQ4G}N%%4B+- z%DQn7notkxmHe^v$QhCJh-a|iiVNd*!Ic7! ze}D3B8weGPc&houiQXdJa&NJiwMw7H^aWs0X)?Rt(Q^RiI$)K}Q zM~xQ5)=9-@4m0VOo8tvO+X_bA8a00$;*=$<{E-ZmV1EGE-zT#gM~~|jwdPBw?~`E1 zjfT4?QSALqkYdb1^{A@e_r2@b%lW+QAxW3G80oXW-YFHP!=t)fPFAE3sXMyoOJ_*q z2uuNAsV0n|z%>jpBmTUPlN;8%BPv~@$RqzXEU0GA+KpYmGa(!_EdRE}wT#!gMHwG6 zD6|^!W>7E)&DSbYuzfMW@iczwh54nBpZ(@n1g0TMoIdl=>#pkC{esQwmgmdAAdkmP zSxe=%JGjMB2O8N!3c+_Cf9DFRasMy(;>_vu;T<;MZ-wK=-#%1JTzYaHKLAY z5m~*=-)ysq zdFSz$?<2gQqmuT2O=yHz6=|h@G%x9=Db3Bh5lUrqZTJa`4q_ox(>kXbH(sD!vh&aT zX(3h87ouiRiN0JX7`^<>yTFIVR;uY3qL0x#Eb{7&?7(+lAQF#(7{3nmIUo3m+hU)a zh@JV!hS3-k1g|Yc3v_Mjq8fd2}iKFAShsEysErFSu{hs};EOX`IOdrE@sOKe)_wz2=;RAq?&kbIY z5Spa2eFyj3A(JBCE%~RuHOH9VUlMpSB&_NHgnL3|1!`_RN@svAFZsQ_min!TPA0&| zT>Y|+Z567wwZqkOR;Dc~5SoI7ZBteHz^ zA0$|pPn6;J)YsH&O^4e}wpey_SsL6EAsWo{T#ZU`4qJe{#Lt-XZ6^cLH-$UBGSsi4 zq38A+1&Yx5qyk&j<4|9A`fQAgYP4bo@Bxy+^|w3FM;btqqP|v z{Oqn}fdw+0?)K%vequ;iL`XGe2n>N8ne%=f6>MH z?d;2)fhcL`%0{>I+3yXLzg&e6e?Hv%<3^hV!!yz88mXE&UyzFerw!EZVK7a>Z&I5; z-2{*t#|=)aezO?1Ple@b8*kh9hXqVO2lX)1wXKyQnz7N2db70!__n8aeZbb8&s*Kbnsa z5ew+-xPGatnUZa<-^AXvm40mR^W%)S=W>%^_hxAm<^JW5Y2r{B6J#dU^3{!BU*jG` z1coJRPosypJ#aC@AH5>%_zqTE+f@E)P;Z&Mlsy+e>V5ll^5fEHJ5)JNLtI8 zd+{&BBHGG7BbE(Dq{(pTjo|R@ay1y8-dB~;RM!M1@OISVzF*NFKoXYReR{I`$ z?(+K&KOS{HfAD>8_J#MYL#E{9n{V#^6A5QL`pj1x$;CCNXSSO+!& zkN2cd;E60wjV>lCZ!?uYaW=xetM8IyN(Q6{B9PQIAa!{BpKgEWzJHz6Vz|+yX}Mew zE`GQVl3sMrWQmIlBvOLEvC||7S(fza_6j$}#}T;i+NS1g@NCoIA9La^i0;kd-g|3& z`5g4D>-8P>kI3{+kyY^ZI39&FQH|$JA>u>+Mui8#`JMJ(!jCVQ_mH2`_b+`9JOAYU z=V!lfF|PcGdHCex#$jx22o*u5#ge%C(ejJlu8+IYT+;J)`&A@Etv>6&I&kH^d&_gJ zsIGhZo%i3db7xqFliGJQ2PCd1-F(-7|L0I`No?Kxm7VBY#%uqfF3+R{DDCNz0GD$* z%V!g>t=?9;HCVk-^*G^YzsA*MvGeDyp3Idgm|%XrBei)q`ta9T$*wJ)6F(&_lKvU5 zBw9Ta(hI2DUF>5cs;)WQc&GDz_uk{%#E|5}=XX@pgW{^Xw?<39_NL;9OV4i|Ok4%x zD1ym}%Vd!nZD!TX>AWGR(z0h8URhP z$w;L;QS2|CTQ8)1`h$8WOhrSZI6L`7F#IAJY3#@#!4Rsq0jD849ZrZMk<%qHX*4Dk zPvOvIpd*IRQn)lYj>=O4lIub%{zj2)uD%&emTVDN{TjMom!dK6ob!Sd15BEJB)uJ+ zbeC81tQ9$BR-l=X5xRK7$|J#UD66$YF%3F@*<_u54rX~1`upwFO+!q9B81x!$r>nIZM;}}$101Ayn zG}@y3@dzhJkdFmo&=LLI10=o)Kr(>RRkahtU_+aC8a}C<$S?ln5d}-?`~)8_X2Q0b4G4J%C~})$r^NJi%I${+APfk zn=IpIA-`|yP`r!Ua(5sZsENE&vR=tl`Ih-ND2B&f8Z{`^){*AVLQUW~do~g5X3jr- zMgLhpcyo73lT-(F8(kYvZ$GzM#@JvI>Hz6 zoS_t+#Yxb{B+TeB=Q54EJrZdOKsI8zmucsu8NgYzEsC61c?;R@2>&(-YNVhnLgBL% z*fJV2ID~ebMYB5H61!aPwPtG4ud6xW6IqnKrP?V5ll*TyC?idGnfM=j&o$SV}o78$Xe4_dZ>pT(o{ zD5wnzk0Ay14NE66ihFF~hmpuDN8WP=k7*=g1CJ_k3_4Ha?zM#*JHnq1p`pQ|h7_ts z0OWZjSPL6@WfNiQ2>OcWvY!Mmp}{OXr!gKCMd9J;;&H-r`b6JluaC1XHI)V#%k&49a4vdbR*#V69iE}CFTrG{yLu(KoAX~%p=EO=B7 z{4yTA7-jpN0DjIXaA6*1<`i;5A*E2appwH{tr-2b?}+2fX=)+A6ny8ia?F2&sUv?} zpHewcU1;_@7z>Y>h(ydz!ZsMyof#+}Jc>05XF4KFEQ+FNDEmp!79QD?PmQQYktjS9 zlQ6|BRH!F1FddeQ=cGRZRpGg0LLzxQB5xC_1CFr3j$A>JAQNn4B_6@s$&-tYT5Jw( zWWe_(Va9(^W0P8qj>!Iekh{KwbUt#B0e=?NWK2PQa72!w!OM~D_W6a&44z47PEWdx z0R39NNZlHQ|E5S_f)QIVJrdmT2Q^1C(%#_@ePL2I>Ck?Sb7JdqB2~cNNThXM)@9x^ zMX#)h1a6o_IQW~IX^EZPc4m_iRgRLMFL1N*jRsb*Gx_%^Sv=8^6}{v~zBoUotzm4rQ-MXi6lPJ54Yp zU(mc4ok9j)pvoSZA?+@JZ5*Fi_6q;LV2WtTLA1ci8ED6R_zYS#h7Ny;FJMP18{Y)~ z+D19&Yp|4`4JtP6eN%8IWuYRQG({uXk3mZScog)w-OOm}T(nyoc^N!dE?lq9VCX@DTfVaL>9Hk@6NTY0#N`c=~3GWMmD8 zFyuWeeF>1u#v_gKTs@PpB|O*rO%w@mgjI!B>LXi9#H1Y&$pukg8F_}2@NanJ6+3un zKBzGgkyV<$GaF2Y)M>~IoJzGkWncFVQV==iy%-M;M?+7uL_HkyUGTRn>EJ*jSK3(t zGTNeH3&wWrV&_9!fn1fEon=;F*&2Z}c=+dL`!o3ZGXSo)i?SA}sLz+dr9Tm8D4b-5 zunPg^Iyv;_9omJ$*J}ax#0pPVgUJBn#!RgWUe!TIq-RG>{wU}5IEM!uMs?Zjlm;C^*}_}G~F zdY*aN%aLUQ1f>bXXCLp!Ex`-hr3)#o&tispH=03F3>3F9s*i$lVj%v_!S)%|yN;ko zk;pMT%87!qc?Vhq==0R01pguXnkW8xBl{@XCS-U98sakvYitJ1)kTVUU&G&^(k-B? zn;dGCY|x*HJ_h1F{s>kJQZ+_)pl_MxPYwc*#`(x^(7U2upxAHFWSPhh%^;hscH>F# z@+2(m@vD-(OeUHk3RfJ>|@;40?pvy+OKj41DLVX_Pfdk>T zn{T%8A`NXhW7^1WM(ZvG%BG-p(a>3@eD5Yt1r4?rImC)AxJ!m!^F9{ybI8OQd@TnW z`4bVwNr+f|)V`^<3*hpI9ErFx6hh{PGkHF1fk$XAtf>aiK-3@>(V`{jIIVPFyh6aT z0tDk9Be^#M8k@!HY<0jXll%j4?y3u_RPqr<73_(J<~ayA{6hU}MGy46^P=m8UnqD@ z6n1pvz72Q^ov)vH-7{JOew$zSBpPxeYV_0k$3I--#|^wzvs?7mt8>v1<4H&(p6e*8 znaAR?XFLp@gaDVJjjWmh15RalEyuMg)8kFh)Kx)`@tIa8(Ft~9NMr!5+e1Movg4uBmeGQqX11dThscSLVSpy!wM<#cUR$l!_jt2t^XWSMgsd@GhDf;yFvB=HRMy z)LcX3+=WYnr}IU^qXQFffMdyQNNTg@e>ddVo2yfg(X*ahy;q>Ycqkjo8R#fv)UjsL zdUp1l?7e?boU{z|Is7$pK1+4Ge$rI-#<+*mpMA$*+g&yS5L4^AT*NbU*9 zgq6MXDH}PI{qfQjp(~M2E7eEFK@X2KW3@<9lmsDLZV51;hhL#$3LjWm4!{(vcR>;|-h zoBz|Wut*!k#{p^=36^X_(=Mn(fiHn=;8R#(I+<%4CX~oja0hTT1K^7=ctRlfG5}uG ztm;mK)gN78kl=6teDbp0J0Ec0F{NL2O1Y>X!xN_$u2KXEpVr?~_#hi|`n8*9Hl}P2 zgdbiM&Y(V>-4H`u)I6ImdYLLzmxkHTitsq#R6G#=bHM-9Yh}CN;`Z%U0#`R0aqDWz zVK3ha9yFVijqE4Zjxd!yn?lN$*6-Z>?`<5cL@Vx_Q7E?QXlqopLN<aHzaEW!V!0*$2q_tb*a+T-Yl z*uTOF7X_6cw|PjPw)!Th`YbcZ5VwmxU**^=C!e=T{-N$vbBo6De(U1;yN>hApFaM( zv^hU;UGYEmr~SWMZauqZxqJtK14dztIPw-SE7zFwN4=B(izL9mHIxMhdyUDEK&nO( zxY&#H1j&RIUnp3teUr!~Yl0?9V)pBf{t#Rz%?~-lA{lJ6{>ffR)iuAGm``@gl1Z4B z`DU@0W*EJhQ;VxuuX$*(SgHm306!{9Qq>$#RT+Am%J^F+QYyYzSCzD@X~i9}|JSBS zaqy>2R_<+vHTFu_D`NJoXMb(7Ojth)kZR6$TX&-H-@ZsCz54qV7Qv}yMbqt|_3Dir z@}?Ffjg_==E3r$hxP$kV0%`F>sYI;i_!k%KX;e#`#H}}%{@a>{H$As;=_gS*MJM?&GB6Xc?o9yE}vXsUVxM7U~xv&?;V z&HY(pUTUI9J&y)=@69>yTVLF;WH6u5+ma`;dQ+p%YLm~$gl~QD2raj7#4qDssCtzY z>i)(?dtLhIp;A!Qs~-Qi;~@4!^xG?!K4pVtCEgUa`0RrTkG$zIp|^nOnt!mobJN_pul1a=oE>FU(^sATh<4tS zBdB{6Xnu^dxMo-`myHm#%RO+v#dl6H*rm>Ro`9}>{Kk!W(b$1!ox6}Rw{s$cB-*l=JS@ni+~$5V zU&^hA^SohL=MUGfHFi~9NLV5H^i*xlHr&a5%5O1czl=2Cq{q(``rnMdVdlrysTTb> zg#Y00Ey(!?<(I)>@Z2FyQ&KZ+OY?4CjW^;SK3H{eQ{kGSx7?!uf4%tdZCge)J@A-* zzGH-C;ltF^_WWI#64QKj4Yd{Axknfm4tw<*hLx}m8k~ARI6b>GhgzN4>?7aSWkWyLHovVu#aR~4-|ou_`@t)GbZ zbGZG|OR-NK{#2l0<#zRze6xF8mt|x{2q*vOYa&u=bMik3SPb7|XMSqe5?cyC zf90PSYj37TK=uJGc*Y+|ehK@#QPNVO+Y<;(q8g4cm^! z|8_Yr&o-}rKH|usl-_>TJ7QuNxxxHaD11k$C|O$q=xY9|`5qi9g#*Gw9aFhhx$Qh= zYjg_!*(jMrz4cDzK%nh7-zEfj_XT2SS7)=#8`S9AQYP zpTB0%^uO=YdjJ=QALcM8U|o zN&eIaT#_|(IDhpS3|n(h>(fe3Q+N%by%|as=)-h6rfDhs(pkKF{xPUDxsZ-+QmXU% z=+vZDG}#t0d2nL1wjX%Q^n0LF(|bo}TdQOD-<#@4-Lz>ur{L4*2QjfX(3=5{3qlFY z)=n;kd3w^-ngIGMjNJ3 zBFjqLmJ=&}zUB_Q=EiTXRe#Ca8lLo!zON3vh%+=_Zg%lX!Jr!2W#&U|&Efc`J`N9t zF>EtM(S$?MZWlI(_?fJ@kBv`>8}h=)2hd6*MA~?l{nCxaUUFcDQZxL0E){r;oOpB> zkWLu#!lEbQ#E?_z)uxu?EjM_=2J@q+CcejycKZcVvH8f7k!Mbk$A!;K|I1%=QgY3T z8`bd7P+=tV%erADH7lamga7-dAh@beT3@~MLbSCaja`ymIPOP3`Mc8JF-^JnCFpd& z4_EIj6Mf<*?aU@isvXCnuwXGUVyi~=cyOasul*<)lUc6rm`0vVd7O=lYU`moBJlMV z@E!}qm<7)V3*-kg(@fM(}%xF())}gNGpFn5W zH}H5sIdOPSWnNuJBK^BDNymg#T_QWMYWRYq`{$GVtkS-VTIN-kTZWCE3)-6xpYCSU zz&4m<)QuKb8rTw(F3JMB#pQe9k|k(q((FxhKs!QWRFX=pF6%7~ZA^aDVrJB8469&_ zhz&ehLpmd@T(#xP4XoVn=Q!&i#`^RHrjdf)h4u5s1;>Omv8L-5l`6Ixx2o^zSHo4i zipe!Pa)}&oLwFTJN)QJZNNIfE?m<<6XSJFIJ zI2{q2&8Ohe*&xqMD|REEO;7Fs3h3g;+SP<+zO)=;D=+vT_%<8l{O` z^3J&_XLVDRKs8`at_{4Q(p1F>p48*(bgp7K$IsTK;i zD8dRWgM75yhHdLhzRAU8j$i`zSlgZdQFI^vRQ-P(z`5>quYGY{n|tj&vRCfC_P+KA zU0Xs{8435=dl!-rA`+sI`rdnu?41y@5~VVW!u|O@9_Jr8=kYk_@j37DeDw*X`IED) z)`uQwo3)F`L>;}m%c^*{TxGk9x%Odo{F2_`OTA$p0&*Uop09W<1bBf1noAHA5w8r0 zK(t+=L_PIZC@WWfe%l-UfN(YIE8I&`L-&FG4ty*R_#pfz=96dUBM^&e8H<2J^BKOe z*(S!BA{Msx2V&O!cQ+cGW!|osHgLMuN}*`<7MSPME4j~xrxgm?8|r52nI!z_^pMiU z-&hx@8@sg1mZHYLvyUsiDPA`=`>`}mav8CwX?+FMb!vQHNwMudC>)6;jCA*OX!LL~ zw?3Wzo63xzfD9Qw%)r{M zwAx5r(?hA#k;aXSktC# zxJ2BtOgCF!YBg{04B2>IDS@SFKp|JvZ4b6-RNQP;?Ps$6ZPl}FH6Gb&KDX8Cn2Fy` z)Lyoo?|Z{~-u4YRTw~m$bgfnzXZ@3Cy=G^(>|w`63A+EIrB3jXooUA-gbw}Qu5FCW zG@H^y)krV<6Eg`Pt07Z?^UMk9j)`nzS^w|GH~tMeJZt!wMjRm~;!(E90^1SXjP_gG z>*pVSL;>tzEUYSMXBq1eMF|CB`*B+RHRmb#7_$Kgfef3qcsBJtZ`O3#A@~vJF)sI4 zgx-4eNYpnOo%SYc(GNDat)x4qZSO&4z8JOMHBY#r<)qV4Pz~QrLzTj4l!KD?<_mv? z0P%?V>?qJfXmK8EnkCc;KRFXmHQx^frE@?Mf`G}zPO1DX*7Ipf$utKiR#25J!4|cL zjCSnHx~7#tVUh!f&aD3rhtfyRW%qI)d6`*I?)7FvG+G_B+WoY)V{><6lGr1|C1w!6Vpf zcrFHIZb&1)a5D!aZtzun8f_w|R5}0Ji|1K}3G-tgL09R`m;g&j)k2 z>YpD?n*(i2hh$5YU9ZmnN9KpTJO?LrIJFLD#LuUMVL|sQL6@`VLD0->+>`A3AX_gnL6p}0?;RP&B|Y*v(0aL11%chtNk)?KmN{VLrG{|J5HrO3;X7F6;% ztn|~KtPqG0bkz71PSXOyMo+tw7(U~nXDZfjrKnoWg^|gzVy!4 zR?mU#KYkeO-y0l?U0gYsC~i+*eVdvMOZz9<#?PL1!k^akgBG6#!{>q7FTmUakU!@| z@d{TSb|wy^oW6aT!4ql26;gi`vn7L8;`7`eZYTfy0`4%FUwxGNuXcqWp7z6lB|qDO zqO(8+he#6Xs?~A+=hoa7q$O{hs-+p2`6H6wP55~he5zUtmPQjg&3N&Cob7}4GWN=| zkB&?plhiD6{QWa9$e&seH>Kh_A;?`vWkvfqrIrKYUbz-AzrxpiZRgxA>2IoR+^3*C z4^OVPwhwDt9ds_ZPw@&VN*-VA;+#f^savA+#`zxM^`KZMkH2n=d9|GKstaDpu7xoT z&JdvYy#?UUso{nCJ4(H=CL5|1Tk8NfbB>RD!V}q$e7aLR=8IImlhn7Ht2(|DzeTzw zmscwd$obes84p>SGaLVv96d3#tux~{l`s4DpMxPQj@uv=kkhwi_Jj-Yr6-HO0T(y!MsG}>UlkJln3A98MNAE!oRJ91Yx|KD zN^3kT`?W4uF)C*Id&08fdTUhkviEpS%pDVclq*6YO-1GA{ViMddrmq!H(v$cBr<*K zZ`r;Z4YG}6xw_pP9lApS4N3AsT1=hwI&SdRj+To_J^nfLWc@)OZNPg=mYesDsw-IN z=C+W#iIGkOONmq@Hu>noh~akkUxs2)F2d10TKlwsiEqv|9RU$xT(|2~Op89rptBZ^ zznzzgs2*jtI0*8u4qtb>iPO2+`TK)AQ}AYrlUmTtjuqRjceXjkn+L1k3zOA6n|Df7 ztUoQc`0&7c-!(5%mLT6NccOD#%i{u%t~T|pb*T${e6$Q1;3Fs!!CoOr{j*@-RoXye zQe=H{G*@D%I&EN7ie(AdeG+W%pASWgN7M!|lm@i?1DoSsbuVGtHUggBem&OO@3NnL zBV(~xn-M`pK(ut?Apn>-A)afW1q2X6g>vPFa)|?YSO}LFTzsE9exHpq4ffwY|F3=a z*P-0<2VB>)xW0x83x>iz?u+?_!UV(M55^89=F0edzprQ)O)vex5u~@Pq!J`lk(SxxOMsCwvXz|=z+3(Gh zSF0;Q&~C@-EBCi%<6G~4^K zfT#Gt7ui`7I#(#fGqpB_{`}|0=b$0x3H{f*K?6zQgLvd>YT|W*GBMRFDh0GlbB~Kg ztrFymd$OVP)mnUUR46Y*APw|hD6EcaVlu$-?T=x*aCe1I*AzgCxW}%#cgBhq&mWn5 zp>)4t`}xTGzv#HugLm-G2(5H`wm{(c&(Vb;3ncXvPOP_?IUEmQ+baWBhyV5uf2gCD zgv)mF2Z$tG)wg-+ElK^f^iuIB08PI-r^(JeVaOd8f@)Eh?xH}J^+qY2dNNKqocsqQ@MPD8@IN0 zn$7u<9U1VQn^^EGAP-0*-VCx=Pu7oW3+Z*cpLJUP_%yqvr!dwcaM(>`{q$Rk+QSy| z_qJjs)n6okf?tyqa#b*51SvxWYK~>n{H`xSm(4Ae<+{z3uV3)}Pw?Z3@j&WqSBgU7 zBqZ7Cg#Qqk^|UWrEDs=2LOtCHu&rX22vLf>)v)X8Wqlwq6ndrd7NT@dG@->aIiolp zdtq&I^6NT>6m18WtA7hUOu|u4u1P3V_vWjRIW_}4l@j`%gbeE5EFfQkQ}h67zw{u2#8 z0T$RnnWLi#?6c%ro6u?RT8jpY-WlHNDV0Msb&96^E_?*f2)bjyMv2(7VmC~i>eKC& z?E|tia7^`aQv9Khg4sm%FGo4^*hdT#ecGoC?#gUtioHYBOu{Hp_~aZX#`^{w-F^DW za4a@|SipWWKP|@vXT1)y5-0+}m^AvH;Oaa|YwuqRTliusm;V}T?jB}$xl|vzIb-O- z#A<-GeQU4BL>bhu$D+q}>|GsyEQq_t40AZL%ugQVO1Y2i_&r8ab`F`16pxNSW;p&7 zo04V79&|F!b%U2ZeSH7M0;W2^*7c4-sf|RHS;7lp4nV}=!R4&n4h&8($ zH%KSG6}*|*$`*8B)n#Aw&x*Gvnf!@E_pGqD2%p@Q52X}QrLi#RC=TeN2HT-*qQ*xc z4!GM?(#^isC~E|{X@5kV!J=wX_xMIZrW_k}7ZhIP`prN{obn{AmXf!I9jra0$>i?d z#2gMeV9TCO>an}E-@uV)6`uL7_Z8{~m;xOfRLp%oJdC6)rr%~s|4Ub2ef?K7+(ko1 zKa=M?hDp^Kxo^vPm9opxz?{&Zf*iCxi84sfj_%ue8t-_gpn*R+pna|G`7@rIoZtaO zrqm4&dLjKdJJ%O?F6|xmX+plV(X}MN^JGWkFzf!`Im`pdfp?AHo0&g-?L>AXs;rgx zcL?SBJ4}w&N)E0tvk6Y7tUR2fe@h^qKkd=BCXr2( zHN$Q@Vd5lANtAF?a*;>;<&V^KUkIyoQmdk`dLM_w>%4CeUzJ3pRS%bEGHR5dcH98q z{9>Qs+F3_uJO~iS(EvEvCg6*%tDw<3gs7*aG5Oz+4>}p**GQCI_W@QkzQt z_ZgVC^r!R0oKWx&8cDC=09q{>Kd49FCtYTAx{3g~!J@;G_oY|2{_t19cc>i0oTAK6 zXzJWIl7qU<)Pk3-2hOhbJ~141@@Kay*q8)}W6-ey+hdK%EnG25YlB+KdDB|wrLjfL zRBqy$&?zUhn(wGlma{3j3?`I*nG5TM#N9Sw^=ku$`qYohB{%iSohgX&R;bh2#vRc9 zl~!Q=`A=K z`AW17g$RU6geR8GS8}_o&SDUHbT^%Z8!JtOdhGr#%2d&U<I~Pm7h`}EfOw=FE{vhbxh@-+j1CVIF zjb7i7b=tcp{oS4-tn!d2&$~~|rB;4$7rl)AFAXIv?brbnJve0& z1XG|_H*6Fkvo|Xw^1Wu`r!T7$0fd_H6ijfaRM8RtLcZ9gfbMaB#c-Z}{IA)LHQ{!Y zLfg)3+=UKBbjCwuQDBXUqiwH}4M9z3ELa(9WPoxpF!R(DSq*!8O;=v zJlO2w&1??GsDbOL{}lrbo2+ZYTv-=d2zxitb$5-{ z7<&s5Oia=V6w;w;9(cLtmu8`Fr(DoFmvD4#RZy9R&bKo~<-!BR3-qXBQMv!h$KyKU z=aR^J$_?1a^PkuAjl3TlLEe~nVpC@=h5j^`7#eccME%Dq?3hPKZlt>FJf{37hdoOV z@U!y)g^zDdm^vp*I?Pn6PwS+yd47BSp6T4fgVkbbK_h6z9#56lzs1jSn4~~HUZpzq zQbFC*YX|-}Ehk_3FAjpVrY$yuTV6YCtU6rfzhAAl{OG3e(+bPMOW}Z?1ybn%L9m?Z zQ41khb`t;skDL>Ly4$_lt9qZxU7q3jiS=Nm^F)P&K2efD`#BTyCP4IraI=KOqCac6 zY90U~B`l$&N-E`H(@e^r;zJE1u>_?eg4ix~04fDa#BBKB#kCDtSBNsG6qzGNj=&Ts zHCIECpmCr;@@@BxtQF(5%g3~)Z2XmRU&`+^oBRhzqwAJUBoKVE!8dlHS}|B(}>M_ zYG~`ZoWLD`AjO_u-q{4%YES0Dbe{iPu^9Oyl8y1Q^gy!kQomxJ1!uygl}C2l!!Y}Q z(O|5-)J8Qz5-UVjbtCYy+KEzoDAq}U{2qoAg5#VQy>zTuFD*i4oJ1T@`PCQ(2dHuK z;&Zo$x1$leXvF46Lvw;Y6^5mVh{zFUzd`mIC8yVO>!0_^Zvwc^sK#ZA^rJ8qyA0zs zcKp_~ezP`DXMv~0w4RVYFCu_D@3Q|!&Ex{JQ1!-}a8bT?WqdX8ej^Ix!2rtlL9U z;?jd{5^a`z+;Y(JIDUr|tR_{RnmUv%t#LJn~cB{erC{6^S zJc1y&M3C5{7Q+EphB^2}xsTn9;jkpX7(W2FJ};I|P>MTtkcKB| zBU_|kr*$)QJn62`T;uMI#_nfpeem4br!_a$EjPunyI-|d^y>hW+w)&{Vs+Oo7oVw8_d}0}Ts^%?mpJk)Kvkclm_Tz?2E#nstBM0%oh2&u zBx>|rz6&&$AY`{;uEeF;$|o(ROeTeWuV|NeG)a(^>DM4qiPiL~kLq#uBwkYMihZ7Z zMS6m+Af-M$m5l|fHeO+m%vVlkhpZ|<5X6H7B2NY>!$s*rPZ?e(tZnG|)4jODL)@ek z9&rO>y$j`Lro3_v>g3>Rw5t+&1~kBts`dzQDhuSmrh%#7sExOY6Dfpi+E6=iJc`Uw z2_LcP%POY<2kY}f^f{IWb)yn_Q46}2WKaF)&-#DuP2V~n_mdn8nEdd~@{Z8_rDCg0 z)-KXZIv}euQd4DOGANls$E621scl7&hD!sP%K1VJJK%~?(m zJnNOb6s=)Rx4LF%#C9?20KJ7vxj*Gl2W?aj8c2Wg>!KO6C{OeDavNkxHV5FR9-2cO>=l#7mA_Sp5(i zV8EnJ;&bX}uO}$g6LvB%@{@o9O)`7J_jf<3#3HEAWjS}{fF5@qfeQGB76f*w(QvhX zHg9guKh1%0pB_3KtR?Il747dA$e7v{%I>0ly7pfa_g{?eqg!g=azN2Z849XmPG(#2 zR>Up;Ifh(rm@0}IzDY`I<;q{PtD40KmLq>vf75+)WY!D62zY*P1x|^%;y74spCCJv z@A-ktK$-z`uF?NxoWusHlb6o0eK%xNkWCvsX?qu189V7*SxqH}0gR`Y^HtK)CCh5A z;tZd_KFamp7x`IQaOlP`qdC(TH_Q@yUw^wU_}#Z_y0)%$q9L6~iDsnZ#(XALx0RW=-G@-*^P zu_qy9r@1u>cG_R_KK>TyYR#Fz%>hZ|Oz`kOjEq;B^q+x050edeag ze1yQAFF^3DSmc+4s+t0)*j{Vx!lnO)`ufUOVCAk|r;+)*r!+&#VjCisjBfZ|g9^kj z;p=C6&1C?5RTE!*#a%<`;+1}<(vP|_+#WV%V3C#ctSTL{1?rIECQ zBEgpCX9Z5{!efSPY>B|m3+9uVkUj|>b*r1lAF*9UkxZ`oC$rBBKlXIriUfL?ZYbv* zFNu)Cu!VJARbdZJgPwlGI@+QWl-A6XKmbv?=^_UEiC%IiBkuh)H-2F1>aM5P>yzR3QvA_0wNd84k$PcZ? znQncmNGC0F(M4|}l=oAm!e$%btVV{MPGQ6A;?wO!K|vf*rhlf=jbyYC&&LIXM zyh<{Qw)O)&eYr9DHE#=xbuasG{fw+B;~rC#wz2EkvEm!5W3I70Jg4ig?q0+9jVJHf zzYhAo84M((6l+(#KOsLdI&O%q97m4M+*>xP9xeP`z@YO_hl;U2x$rJi*l}#*FKv4J zWv4T3Cq}fTK9yFu{?w-#`aoa<&&(f5?NspH@wUMt#OpeUNlAOG=M+r;#o1wo05`|` zaLc~^J=2JrNgRq0lB6?v>|Lz*IxGz@c?LLL{6q;%yVvnYa`2&!88J=@htC&z_FCzg z)p3<(Csi%;*zlXKW!wLjXTF*ETIb?M~f;-U=_CR>w*9USJ*0l2Pnz7Hy!!JrPr1-rxP;vYgX`PjtGPU^_ zq*y>Fpa+ei6?CgV5$liNM%9-`mULlCqB|FSb(3whpO#D6oPv3IAD?_JkLb)_uTH#( z_O0*|u%6_Ns~}>Y4q{%?o7~$~q-+UZVVND3>p5~6ebEEpl@aNM&IENxwOpP9?4zcV znoptC>usZxHQ|;?v+1BJG02bXDMS8yuxVq_M@7@7&b?#0S#7IK)1L{v!Rkp(yv4IN z7CIdEHryLIT1iCq+@AR16R^&)%rt@i#hkGSOOxkfV5`a@@0|R_*~@x*$?>Xw2EUfp z47$F`lTE4GtrIY_z49jP67z}y$SXG|V4%4dr9KssJR@HO#qxNJIOVF0`vjP?yF6Lq ziZC0MUfMEQLOxOZgb~R)<4sPfo=&Mp&K1NIZvDM|&oy4klu^dbqE_P)X-0iW=H(I4 zrH$7i_B}4dN6J#-#TdS+{IA7-q`pb z?z=Gjzw^HjcM&pqzZIkun-MYovMteunYV&X#0Q6yt{9hwHg#3g%im*T-H~$DmdKB9 zPh-fq-qKLbGr{VzA*jm?cwg%0Nr3Ri>cf)4q$;)Fb7jW-^?QiZZX0B;escbF*S1n0 z(nP-aEzgovM4}yx&%h67qOZHpsFi}AaJLV+X70kT*=X4MKc-?xSgKRutk}hYDD)#0;yq_o-&tef6K6zZ=(I8cL(8egv`3wmcDc_3G&&^ zgPv%U)v|X-@NMZAhihnz+yFkQ_%^fX?@DrA@GNc8-a6k(3Hd-|kTGq znR}CFyN{{3ihM9mV!D8UfL3Y0g+g95X1=w0#%3I*P@_Y&6VyXFUm z+Y;Dpu}C2SKq{vVo<-Jtjq_Sp@{aaENm!Pb?EA3Nvfl-7dvGF_%h&7zwyN_JqkhR0 zpK?!O^_V6RH93C@H$^0!P0SYMf*fsM1;vOicfr$Xv5c@6*k(nu*uYm@2DIOl z6MHs|Ovm6cB{F<7hkv7kzy0^wa(Ps+Xc^RJ2M7J;xM%(=@ zJ4#ANhFhQ4jcG$&jnB(qrzi8xDtM3xQjoc_I}du3rEX zLP=h3)QtR>^Qw0Fv^5|vuA=$jJHLL9JP(mn<`h~`xE%&fb1)XOYawtj*Ay=0bcV&R zXNX;{O84j+76y$GEaMaz7~lPzeOLCdu9m7k+b~7?AKmR(cQB{~@x`(Js&bQ8Y<{Od zvi@c%C`PBwtK_uxeKPB20D-T+L4ePdF5y{#aB?{cT#9muREoK^=n{ zn?9%AM+Ps(4Z-KHWUhCbHMvcgt?du30&GKtL(6Fd7Yhn$1Dn4FT9!b|8S;|29LdXIR zQ;!JEH*R0ga948ANs%jhk|c*if@HTJa9*R1E|5*!Z2TYaG7n*p?KZvf=4wPew&-rh6oGv;e_KN7=mrm_R_hl~|3G|~l1vvmS;-~pp&2OmH z9|0&pc<ZQ;?WX>^_1~XQ1BPBW)q%b*7Ng%e4FzANzlA5L9qq%#rz= zcSBcpTY#S}S$vXNazO`egUt~k(?ayl5GHVVh@JrJq0Ih)*c8u;R<@}=_Dlu#?-M*4 ztzoZPFD6&PM|!Zv$?do%www=MJav08g z)(CI`^W91&ibvqMCzoSF*Y96Xm2>=)7;i|t=YA_sdj?<{T~$yn5S}0i>lP?pwGlBY z5HYh6(Fqf|_C%PoS48ECh}*RCAWF=K4SZloPff#b@dBpvjNXCu{T%A@)D%$N%=pqG z?x&();lZo0UikYl+PGgb02{>wR@Eq?)Qf4Ukv#ATK$<&IYGDkKsEAJqb%0|2aw*#O zyqCB;MA6riUtyDzAEy0$C2qAqWj9Q9Z(3P9O<5)YHnUIvRgq8l)+CTc^1AgEF~wS1 zP&`{YWiCuLFN~kNP)Wj8Qr_0)cYfh~jm6(}?zb%Jo)oE~l|8}vA42z6VfR-B*DG0e zTWABQko5;L3HvHHE5R!$4m%QSRHdp%I3qqE9EgB=;(o*+r0wzWuvNk7O1MH5IAvAl z4nn4sh2^ammwYvy5X5PZ;D$QkKrj~vPm9Nw6lQLb-SX@aRPvRhKk zTqEwrlwUZTAAQT?)Lc>wqVNy|0+k5I{! z27+J?H3e{(k7La5aRPf)49e{cB=@uAqYukY*25EJ<3X zfH?xmdML~hw`LodfnCePP&^n{E@3*f-k&D$Ko$EQHS=E_-zC@^kO1eQ796N#AEwrP zgW_ni;iyPp)nBti=7A$na7Y!S=NfGo4${=da8$)fK$^rPz%O;%Sa#vMLiwa4&HPHb zi-Ax;M8idna>4QS$eZmp1hfBC*hFchuRfh$flL)ZYgS)|4ern*n&?_8=}K@Z+I4i5 zhyW8qYsAjiO;xRrMp`<6t3-sN!?Uw1fThh_hZ3nz;tUAmK+)f;QEWc98d26)t?p?P z{0(;n+keq-y`q~nkoZO+dnsdNfHN}n32!SENQ|x59f8x@a*IU@H;b%&N zt9&^gTsQ>%3QDkIja#AJ2>hLHs}ih9%^rr37RG8`8jKJ$|0n`-u_mSTkq;LxAXChB zl|$3-5J6*E9NVGGeyB)O*wFmj#Ot--YxtAEfvfih7$#9L1++L6$+4Ya=8_MYxWlgq zVPr!Hm{JUCZT%5)t;C^X2(LC2OBL24#s^! zPineZkV!s8St}X9pluZleoE(y3%MLTfK~%lA8?4O9S`pa4pJ+7X8J``!y@o*64=m@ zS;cn@9db=r-{)nt@E-YpRAi0Qg1d}J9EqWcG!*8+9zul9_rDdg!${s) zmRt9{OJqGE#eA;f+(R<$Rnd07X5I4O(p2G3@!)MCVQ(uj{Y5ePSE;9>9B)}^GLe|? zyaJ`H`bDk^;!gQ2@tmDi?4HNo#o?;Ua!-%;5>9Vl$-0eyY_I*bGu}A2z1u;>U!7Hx zprcO>7eMA*Mqufk2%@SOF>8Xa5LW5!$D80Z1ia61C~1^#kjVFKdvHm6T!i9vLh1j^$oxZg=Py~=Vy zg0!Qc&0MmOB>DjyZBhcgt1(?0j=qP;7F$VoWh1#OT8RJUm9npb_t8z;7~wFI<(A=W z7_~HH!muTQnGp|`PTKR20_QT93b*929#MWiX^wMjlB?#9L&^LdOkVmb7>A^V64>T& z+@8;V#F^#$a3e3x-V_{NOci^u3XhA@@B73eek6~A2c#PDOMOo;fXJHW!R3#nf5&{^ ztPnx-W;u$;h(W?#iRxa?nvsL|C|~NXePJAc=uh zwZk4<{q{s&fgsOHmS5CI=l-P>mEL@QTg6jIXtY82S+rs^_pyi?-KA>@L0Urrj3Rg_ za}`s;Dl`K|mvO}SyONHafM_N%Lp{5{a2C`x=n^*t%Sdkr$#3O^I84{5=&HG^tGT&u zRGwmB01^WL&nHL79r=*NeJVpmjl8G?j)u_}P$5eY8I&p-xxfQY%Y$^@FzEmbYUg zwmpPorbHMxn=OqBA^7zI! z)%%AK8KFi>71O#gC$@%38{MHpeG?k3PX4<-rQOJ25?BWOT!TL)?yx5nn+x}y-b&yVwnI%C6TO;HY-M}&4#Z^IHNkgO zNai*A9F!C@C+=uuR{fcb&2D9m_jEHN#}w~&^oyRhTX)M83nf3JpclV--}A-MZC1{w z^CPM7Qldc9XDGT0YRI!rhHpYz*5sC__nzFQbcPMw=4*NMbA#Z`mCn{)$rB>Vpt&V9 zE^#|0l^(aosfvb5^-1S|X>aXF5GS`AEI`)cZinR z3!7cOqTaqKd3EL4688CZ%?8S#nG~~uz{YjfH2r0w(WPR3qbE zk~hqu?5vt`_8@s!Knr*ANJDx1GqDIhT9j|UWeV3yWh~_uX<)39O=V^+TW_R8OH-O% zTW#n)2II%*g?ifFOOkwp;?8eoV84q|oUn~t=dX7@vpjHw(xc}^GE?G}e2=2cT8zkS znDv}}G}e+XiKkMz>&l5>6IPg8vnfn;vh&tPSz;P86aj5Mtu;VvD1!2W$@?9J<6pNWYKf|fl|zY?)7TK#QPDdB|iprsSF z^W6wO^*Z+Qt2zTrKW1tvcNHqMqq(%E8!1oUy}kSU=gglHD}{@*e?PLniwpesABD2N zk3g_oe85%Sy(0?)Va`r^Cvrzw*Dh+{p%LOd#m>W&smQ?v zmr!L_d?USew)lomzJUuCp?Kfgk*f&H;ZSoqgo?x?=g`h2J3cNZqV_)J4u~qdn?qCF zBf2*w?F@{=^r!UbT=H5FXls3I49xrp0fL!Bt;y{6{))78qQ+DDoDpoW5$ANbJIP`L zC?EQ8Tf2cp7{+Fb2VQ~p0I^4irGwx@ZobK3!$TR9J}yp%DV!|MDI0C0s^52CsyeJC z=h69)mM~NIPWUj3*(HyRm+nO-MzQE8Oh)gMz^n0pj$3}-os|3cv*$arF)p6MH}6j1 zRhdViS#6Bhg1cCY_$V;mJ6!Is=7sXj80k+jP&PV?_g=5@2^>$d)T63`dJw66u4%L9 zEk^d*fBlhp=wS7y9NhQ+PTBT!_~zNz2GtZ<_*}VJqyqxR$^qWPc3Rsukwwg4>yOY zaFJRE1@VQ)s7W+?^Rt;_tC0{6f$td1Qu}$bK{Uzi|0Lqp2u&05YS!4A46>BNu;wa^!uznq_!GzpexDJeh?}R-VrTxWY>Oq3rnNR=H+v-a*%Ss z8xivP&BEXBq#+$2>Ak~^vF4b_QZWTQz4>Zkn6k3&pXIbL625W;Mw2X!K;By%siajK zY?7);3Y!ba`D!?*!M1{;-9#F13lJ}7pTNjpLnK{G@!s2S_uTl-#=hSv5x9K}MM-d_ z|93{+^2t68=c(SWtAGUc9GiPAF3x>1SR)05gJkUoL$wl3r24SRQ;6e?_9&3)?`DuuD%T#+e|o90-oW^>g_?eE5Q3M1{H zhFmc64&}`#sSMHh26QEXFzw9D>#34dyI)wzSX+73Np?guDXBg-hi)Xi8LW*+)7bWK zgJK>7moHbT+s)qir;pq@J$OK5tW!ue8TGud(e1Z`{O3FLg8wpyMAB}s8phT_$8Rl? zSqg9>pc&1vYi99wX?t9Ex_(h1_2vHF@2po63hjD%cb1!z*;s5i=BID=XNJ$YLVnPt zmUI;tV&!Pr=0oYD{U8FPpD=HI$$7`XEetzPflGgxyC_%UUj-v1c22g$^dZ(-ji&yU!)l(uGMd^&A9_X z_L~iAUo&-Vw@J;$PkucCc1*?Dpc%bSwscK5^UauV-UAuv8J)%$VXoxea5r^<*ZB-) zj8C}OZ7=J#BWSPg4bvBS-vO7o@eCYn&(acnf`EL4Yac;X7p zpQB3XYu1}pYw&t#vc$y{o%QHCEO>fMeIf%IGjRAQp#RqE=F~@>i?5nbmh{}0DG>Gd zv^KY#jDhmRY1)iEvT4d~CeOQv`Tg&1#hHA9jy6G^-|f>o1@(?C`>U+Smuv`z_-Dc$ zMn9%i*!k&XDxlpTLgyE`UQxzcb0W{K+6*WwKIC$I73e~LB|%hEt$u(d<#loVCO~WW zwrKbpvoBKDPKTYw!y=#leeulY@E(X^KtXdq7su7hz{cbb`*H2MSorrxf9$2>qs>22 zu{ilam1pqW7?8p?lH+sD2gyaKm$}dla!DwPCntT&yr0=que7 zgTzhdJhZxDyR#kn=COZT`%%q%zHOW;_aJ@S=Rj)nN;D$vGX5qjp6dx0 z<-|a4X?DJ-q?!^e(HU$P#q9=>72E;}i4|FO5cs$={!$jm~BvZVYUh$N{NB5IC{C-~n(TJ$d zSpJ=Ucwt`j;dnvMj-D603trsAnm+R^dCWlK(H+dW)={{WloXt7!t!n}bz=F~`1o~$ z_5e@qUI@YN{97-oH%La9^dr_S3292EqvD|Xb>yIJyR>AuF7>r9f^yX7tc6~5UlrV0 zHuo7yS8?v_F}jvJPOVpaSkIM^ql(?Q=|2 zjY=F5Wg9foUsh$i<8`}#FSaj)p+5}&fz#@yp*96dOF=>WptK?(I!Lmx=d7>lp7#1{ zD4IxEXA?@V8~7=pG9h1v!frI z)LvYpTSSSs5b3TbK`rq7Xe$0W97N3kIuF;{!Y8&nWzP7@4ZIFwo{m^i<+$vyiDDSZ z3A6(!#vTRhGLYQIR9UG|TDnl$jj-r0afxA$S8_@bPV(5<#&;;C#GbkZ}-_y`CG-R1{vWlZ1^lMogo(8&;I_vDh zizsM0QTVL5*EYk>+;ui~_{lDn*0qfBenOb<&V0o81KnF*On6snR5suaIo;4EO{X8iwC;WHIX?dy5?GV~tep&OK`9p8 zNcZo`389OmD#8-AI<} zjorHYPy={~E(2&*0$nPfADU@lX{>7#?Y@*n)yVi@*x+_zj<|>4G_K?RAWi-Uz(7C0 zKoCUa55Dl5OJ;pI5E9HuDwM!26Y~%MwC8A=us|_V3dQqeF>rf0U`5RU2D%_Ir66%J zlAUI_odl+qaLJAgWoVCeSbRrtgTor>sXgvFn2Hmh`&XY-TBVUwQJW|nnv)op*`KUL z5HJu+rD>pKTBc@7rZpf#vZIUKW<(B9SBh(RuC0}Y6yW~1=rxC90;U% zc7)-SFo-Bp%HpC6g`{?v7zbenlrRvCfj4RNq?RS6e`lq<+N&m)dJ(CmZN{aT35zJn z0bwd1XS%G++N`gmrv1{OZdx4wg~@JZXkTZLt^Ys*ZY6?+3KlKm38lc3fp7zcFgKJS z1Yp4l0+9;F`59)h3AwNdU-%tCkO~q51~H&To3IBdv4@GtJtiYy+{tKw#~4UJ24z77 z9Z~Z6vML)NIZ%@c z0bWDIi}8}1?nWvnum?zRb6fNSOBn;w5d`58XJ+wkJ*yBw00iAbGT$N|K6{1nbXt8@1bkR|R_< zR$Gadu?Cn>au6$FNg78MBn0Zv0yCDj8AP>fo4Oj?wjS%4zySu7(6qdDIoXk1(d0@e zn;#1C9~+^!zN@$J!MD=15r2y#7+O~DMox(9A&Hx~syh-=TdKd&5LeJPQAZGPNDGS9 zxnX-8mq7&NK(R?-y4i!e&wIX9%DP!99N^fzD%cEH00ZYT9w(a+%hXGC(E~C#OFHzs z{<}l&vK}y`9xaP)Y|3=Sdn3n-EiMv``=uY{hrabSx%o7;hJ>pcqvL3EWs??kWv$@XBY!b!4+(G17NVOq;dm1!U@(OzOz`r_S*&6 zfDO-}2Dn5J29gFcw7)I95C(!vORxm@`$95=Z7^Fq32Y+^%!zN-tq{CUO$@o+Q^BQr z!5mV(f-noba0+}d3#xDnVi3Y$OTw_47HuHD?FULL9L9XCfiK*cGDQ%uum%cY2qk!F zg8Y#v_z%bV!{|{TE|ddfFb|H<3;56lHP8o+&;w(j4{=ZfV}J>Z^2A|0bUmO7w2;cG z5F9Zpv(2)_W#z@j5y31RVBllHdt4BZ*BV;j1!z!&Z#hAp`>O9l73x48fnvU=+sDkD zm~jGAZ+lPwL7+S(R~1XC71nSCKhSKY;0fSy4U5J?j|?C4kp}ND1pn|1yf6&sFvOz3 z57FQV_z(>9Fa!z8#4Kzeoj?nw(+eU2tuLz(ZK`~)9JsOkz_Sd-O>E2Sn9BhfV!CrT zqc_ZA3j`xjTpChO4&BTgeQRDYIneC7(Cc4daWT{J5;wpVKlgLpqEqxc&ZSw-?=T<3 zU<_lR3eSKKL!b{s5CxrZ4Eitz?19fMJPfo@13b_Jw(!q3>B{1{(c)y#^`rw-{SP|8 z1Vq9FTD{d=-PK*rc;kVYMA1NEIcd?P z90b+>9o^SDmU@DBeF1@GVp z<-iM#pbs^`)3#6!j_?j~@Iqls)1W~Rx4;7%kpl*N#Sh}tjkF)I{5TmZ5@}5YVt@u{ zAO`=?+rs_Z#68@`UEIih+{&HY%)Q*s-Q3VE+)SX>BC?h1hs$qmG*}Q4c}>?TOvkV) zV|wh@C@yF_E*VAjH18qp|LkJR} zPTrX_BunV5n4zi9s*nn_kOs1(5E&k=emkvCEfQB?8Dm~CQY}i~Aq4}`lo=>KMZgg4}H|ca8ju1%mC7l+bFtri4jp{e>1OtHv|9}Q3j+|t`=I%Za?;hOnKJW5g z@9}=`^p5ZLp6~p=@9B=5uf7|xF1^9gHe}!jS!)G*a0wdH6z3%J59x^UI>=rLd z#V*(i>{f|>Tw^jBohBy@?>i50xhis9qI|u!P2u?D)pGBUNPRddNYNmxh?SJ ze(quf+^6@($eX9^6S!5J+$IPS5mEFZE4N^;7@!>(2D(F5+hJ z1hBp%vMwB%#RsP_Sp;#69LDS5y+^Y(a}$5@a1S{d|Kl`*?27*J0PHURklwo{-}eHF z@{Ho;1C5hUZ9Z8*2gf)JY48xgQdVWIg{|Ui;dk>)mh0b23?GiqZ?$`@h(r5a=jg6e|^CzD5uz&SQFZ;Fs`UoN7UN7)qPw@OS1$v+g6hjun z&<2uMG$juk4e3{i)LfmCfuV@AuyCAB+wlfG_w64C;Us zG*_Spj7$Y{pbN)93`yZCvG$nXr`t^M4}w5@XjO(H{PJ^upzdr7cL6`nb-{HsXN44pl?%v@oLGwVMpSI}f>nse#Wuw~7jHAoii zTDEQ7zJ(iC?p(Tc?cTlX1q;)xS+L;6Y2%;391jdW-~eL>!5xkNHHI8n@{S%oBIlf( zS@UMjojrdB9UAoG&^d5M`R9+HYJdM63Dj{z$HB1##r!kI>mRRU#2jV81dAY*tp^7V zwvjxi4my4UCuf2s2#$X^tY1HlJh|Y(H@Kfw$nYjXG&h~$GuTY(qkq-L;S@!t+COEx z!NB6DzML87+_e2`gN&#E+sP-OcDexvqKrc7CbiJI;;B#nFiGT!EWqGoDJ#S(sH?Bq z8ml-0<$7>L6Hi1jMHN?MvBk5p;EN!?Qryml!VXJpG13;3%%I77c#Jg6L?g0DBacKf z$;M2}X|>e|dQCRjXd{aXEif5|7-FEjk{DxB`6t4hj;k>zF^c+U!9D&OtdxJ$V}c+Y zZiwL@?*!ANMjL(zLa-PF`>v_*Y%*viZUPZw7J}YU#*9Gx3B(zjRuYChGO!s34%?)n z4-G;5F=Qq&#IQ#yGX!MOz}W&LD8U7fO6s2y&5E#AtU{c%pshRvi>(mh$`!9*T_mXtntQz5L1jXggpDlGRTzWb}kPUv55?P6s1WFNl$f=3{`XD&eft|bx_2xs;Ko| zT!-D&t6s~hf{G@HOWJ2D3u=NZr%fcwXIz_TV(Nde#=6;pY<((ftxv?tt=dAQf{Ly2 z1zOB1#8&IpucO9S)~v{?`{!Z1<-6~)nC^dQJzG;I(CmOpL4As0Ih@`Msf{>cL7 zf;=&3iaNs@bi7e3Qe~Sr(1S$&6XhtG=X?7%@YPcW&9#B$bH089@bi zZcwSQ#agP?U)3$K=ns+ZVkxzuNSn%`)t5pFTvr@gZMFu5rvz{*T;p1;um-lR?N2KL ze49=jh>*4&a4kbyTH2=21Sr^zAQ57U6tLDl5CUy$!)d}5q;M+}j?gUsb6gB%co4uj zi$>d#7D1?`BOU!?4B!CLGx{)u9n_#ljM>%>^Q3cK4t`aTf-U~h zi<)SG62maYF!~^?(oIcY%E5^i{NNn_KNMvTYO_HpQZYLmz=9HW>Y$8TWv3q)L=+M)A<+_tG(&X z3RbXRK~NdL4jJu*Oqqfdx{$Uj2=0n`WXct~aD`Q_Pbaus3KTlHA@&6j3R*y*2n~q9 ztgY>BV7mg>-bcX$W{qnPG~k0O=u2!St$!NCg4=SbK&;>^ff1s@3b~TP6lw?yT7W_` ze+GpBF43Odsv+-eNg%@Es9HhFRvO+hgc^Xu5ku(3Frt8oPUJupaX_MD?m1B=K2ax= zgOcSyX}2nDh!$SD1sW((j4&eqLJMhwkr`39FV(F|5YC~=amdh&glz(Nn-~ZbDAC7) z{6H6b5Tsiyb`w+;gbcd)ha&$$i-NGsBLwk>D*iDKn&8721Sv}D0R;01a*Et|MPf)L;a!=}9N zDd8*~3!#aHQ&J&1c|GZdPHK~=At6LfD1pP2(v-fIR)7>mZj16cBNX-1aQ|Ekkj9`7 zV=!YLj+h=V&M^jjbmAQULx^Y(lRHt(K#?HjDhNL+C#8*s=qWH8MwW)*k+i*aSZAad z>Sp7GHVC351xb!3uJMmwWMQWN@I~Hoat)sHG*Dn5rUPQ z*0mIpP7(hoLE7G&1gueE2Iyp(*s#L1w^bnwVbVgFfs8gjk3|S%2*e1hVBEX$rGqhQ zmH>q?1&1ZJv|%#;1Q@OW20MJPAV;`@89KcMgIvL{WBH3Z*w$KymBI^Yt4)1{*{u3% z<;%p(N*>3%YlG+o(#(Yx4hyHl!v#sY_+Z8{uB#7hV1pk^pannFu(%}h+MeaTC~Gpx zUj2y{3-<{|FhpkvDoi1ms~poxAv`gj*q}~K_)~Sb^PL;in|6J2cXIBeCzc|l-cKlG zMNrj-Jd}qfWYEJJ&`=&SfaE2&X@egeLX$SI?jaraZ^p`l2Rs;ZMJfULPnwb)9HZ5) z?bB%~Ofdy5BvlM;V_{laIlrHU`Ur<`m=V661T7e03q=VvAx_{$g0$fZfjGk>udoG5 zq|hi^U|UE3|FMZQL186yI66U`{0oWwBe7IZ(@G4{!9-933VX2dR?bSV0L*V1W{R(1j*QmI+t*!#_4i1tVDE3mLpZ2er`iNB%(xSJ1*2d=QZ}Pyq@N zu{>RsKnEX)0q|jXLJ|nFg%Z5M>vAuM68>R?z&FbWO5be$TD20Wd%+Kspz~4wL26PT z9EDJCzAE?5TzEVMyUYnXx;W}!AlQo&)*dTV{NAWSR7>8*3MHgdhN zXs-c#aKiSdc%?g!9t^>t?})?2-=pe(&0yH_8is+SJFodJX1y3L#f=IJ; zi4eFe2o3lLDKLl*fU`8y0468_g4nGY@PU6|0&}aIE{ht1KmySVMAa*Smb<(9!j}%9 zLpdM_4WLAWUAc!s~HF|lwQu0HCnFV3spuf-qO}K@>s0J-)gPM>6MInyipo4#KH7*oH zg`tCe%D;QszDKj6=0d;cQa>L$2g=w6M{opuzz15Og=ZLobm#;8+s5SDKZEeU)~KTP zx-wzvpi)4Dl&YuG(T)Y2nA9}e0-OAYSXhZ#K>|Raj)DOH0yv|@ z9smRxCf60hF0r+WMc^zy%a>^6Rc0xQ^yzc8S58_0XAHz`oT@KixgqA-ixK#DXZMe3gJ z8Nv0eNR9kB6$FBf5=eqLD;U(9u}B*~NCmjk0x1v$LvXAhQ;Q)(8l@rs2u%yCNAf~K zSQ`#H1kQ{yDTq)KphYBW!VS^Fsq-Bed5W+0&B>l4%&pJkb+!@ zg@Jgan}|cnDhN5C4%7h5SA-hHixaPFf+^?d`~=z+j|f)WVCP*goQL(C@C0yUsSEf`5QQ3nqwwUT&>JxHu4Y=SKqgs=IBD%^?K zBM9T84VKgu<{M3PFb3gZntw2uwo?zVgNnaklcdoGDG-J=aE4S^MljKYXmn0)oVCEY zq2$=V9jd5p0T+3!)aM+wgTScu0zk~E8oW_6)-nzSWRU(h;*iJE43OoTAlYgkc-nT4l_1w3s#PfMY-GYCo?14_)xD2M_d$jgoW zhf5q;JS;aNZGsM%fi5Tkl_iKVAcz?#OweZp8W?v2+W-w*&dLC zp!I>jYq_?&0&*w_SG0o@kcFo>0kAj(2PKF&C4@3413NJP14D4dBLIUSAcr)23Nd*k zJk?W<3Z@Pkhtb51T*#{~`v!w$0<~ciXSk2FpgwN+uWC4|fAEC82vvLfO-uzxO&wKE zT^#1r3?Mn8!BryYlp^&i2N2)PPd0fQMe128C^;k_nAd?d_TAon2) zGjJ2LwSw!M-UyNv<_i;4B7?ljD^(ILQ!9u^60Q%b8xk0UJ}iOs_1GThf+__9Ab0{M z5CZBTONRIYuWLiK(E^r5f+%1DDG-Aukb*uGMbtq54Ikv7wmc~*C;}gHtU+JYINv8|0(e>q$r_L0#TQL0ol;Y}1bqsXh>$?gMNcz`&#arRa2ji9 z4_Vm@aIJzVU_QT~ErP&Kb7K~+cmzLi1~2deGWfog5M0Qep~C&fU_;#WGtSSbjPN=U zfg62|HfTJho$s z90pP-dc=9?pL##f` znq2liu0SU8^}(oIJQ0#ow9G8Kc`GbP8^2nbCSU?;&fpS20t-fe( zf?|EjR2xa$Vw0%Ks0_$>Xo%JpBWjEq@Zy5-;vBeWx7cW%sDUl60rNr#jn0;Th#Zm@ zRfLdE)i6~n64%Tv3;as1s;pZ|j-^=YA1QbOoj%f@_UWGn>Yx_tp(g607V4ay&qT%< zX|+#B4oQTtk{}$ea`WUowd8Q!iD}ONn-)5VJ}g^k8lkL#CJ(X@eV(`jH4XxrJ_~Co5Yk++72Y8TDNq_HkOCsD0=Vj*S}L97wQ5^)=PTNuRF#ol>0T?V z-r=C+f>xsO^G1X|T!p6Mf^g^_Kn;o3mMEYM%5c);bkc0;f#f!6=3ef9=;&;5(vEJw zA=u&}0I!lZh$R4$9>@XaCWtN8ZtL!D>n;fL_HFUjZnxNC^>*m>E(xE?pf;7y%Z*@6w7LVljF`(SNAAI@hy(pWcvAnc# ztK8M`t&u}AR&DTOZ7OT!SrHLf-tUR>HQ-F>O=ajSt^s05hj-`%i|%6Ueui^Mhd3C6 zb2x`_h=MUFhcX{?FfRwx*z$AegDxnCb4YW7P=#}-fiwW~aae*Ozy~;=U^qXAE}#W4 zABGwjf+Z*isltYGfX5!#@^^5AC~$;f$N_Hvb5$4uX5ex!hx2mif+1*hM*xx>s0>G# z2RNVeb9jemAOSRsbT|jv8phu(&Ftn?f(2JdFyQs1to5b4R) zwlQXL!8+saT=M%@L_1KwIMgqnnMHGgK1YTW2I4>+(qC+q+Sf?9jwNQ zv+gB&LN~a+ZvutsAS?2K+=+LWAf}-4FH;vbq49qA_q1Uq7QfupwpIi@3*Kz@C0efF zyo=%d2gOzH9_WK{0PcYrh9T&KPUr({=z>1zgJB|C>w#W41z#WeE*_{Jh;>z10*XI*N8pAbh=O+z1#lpS z8W^a5z<7?2gOBh3gdR|NOxT7T=z@X5u3Fe4TEOlu&H-%rp)mlj9+(GkXoP2o0*4NB zYRYiWIa_eaj}gfHl4_ivCqivneWyUd?9 zxb{k>t4n^#D@X(U@s$t}(mKpt1iH0TLWlv)3GM}p>trkJB_@Eh@5E1hjtZ^qG?9L% z?Q8${-5-6@rzUzgEqcEo#^=UgV|cr8c*Tvb9>`Y97>6;))^ZpF>jH;!NP}_!FEucS zE~vkBX!<1}^lcc1c`%1`c!O~;4Kg2sa_EC|7%}h~gKba+d>Ds6_wGJ`zadbCa**^+ z0Elh9RQ&`02X0=YVYGVuOP9k@u_gM(r4!XFow;*r(nZO!WShbqInpgT7YCavX6ed- zi_$|Cts(Qqo#QnGWtVa^hy6QN3)8kS=^W7-*8?9#Oh@|+<3(%cxiSByQmr~Qht;W3 zvi@^qRQx(etjRzj1-lI8e6C`iEkJDvp#mf>cnQ?G9Qy7jEsH~XIccPv@V;>VLO zZ~i?0l_u)dYo<=zdv?d(ztgX8|33b^SvGTjp5LxqHstU?RS$3g!wyp=_|Hqj^w2{& zQoS=w4a`ue$}r>nvx6Go@Is6l#?->mKT%*q427aF;|)V&jC0H}jl3h&692rhjT&(b zkx~!Cl+%Y+eMB`6Cd}~C$T)9w!p$(X^f1IbH8?`d5}4!=#e}^4qslSobY$W%z0^>{ zJB`f4jXAdTF-8x^sFFiDL)4(uKkqDIOeZ;5`A?j@ymC?x=S(%u5RUW^ML9h@Q$rNb zyb(u(Sk)ydSN!;6=~P~UCDwb>sil@#c)j&cfd83#DypgC7uaBh9hTT)-Su@A6m97L z(cC|<%pnG4+-b*|XP{9f8dq18cA8#m$nlRHB~az;3^UXw2N6C{CC3aJ$g!*vNL;~K zu2uQ+3mJ5j;_E-nP-V?j-~K}d6rajFFTM5JdvCk<>boz${kk_Se(c#5YG|qwtSZ6@ zE3DUkzWTRtfCCnI;DQW3sKz-GZ+#Ipc^t#27!uDP#?e5EI2V zHDKJyGd+~7&<@4)(#O^3bYadvoj5W~BQ;=yNfh8r)sjq09FwOxOEf*iFsj7=G4eZ6 zI1=H=Z;Z3UJ2`Z6vMNLLqNQDwR<+fonRoS7SUP}5oxBIvHEO8~n|?a#-?2)VVTdWl zn6Jdvb;W+SUO@*ho6NEX6~m1N>}O-mer#VQjA1QRQOvN_R7_Z_g;r|(qr_A~G-1`Z z?s`HM6u(sU%X0sy1==-I#M>|W>8rm!`}C&%KK${^Z+gR2J*;rV1X5)nf(ky^L(6p1 z2SqJ`C^=w8IkpjnC1B$mBO3!Z5;z71I`AJkI7R}OK*47$VN5W)(l*XPH;)Wr-;Y~R##~d!0zy&sNWILe$#W}!{hJWM` z8%sz7IL-dTG)vmyrK_SY@sM}pbAH*!AYVh$1`}b174iN9MU_6LAt;- z6V|A5bg>ksHn%Cyb&4!dn2IK-Foo90t}UdK%ls0l$b_xVRj!K_vCuV|#y|lIdPqeU z=1?0^V4`=L0iLk(Vl30_B?-+cfe)6|ynj4_Hve!I@}yFPYsJ7f1@l63=#UF=eeVj) z@zxcnV7|1pub9R>rur7C%w;ljnf05>{TL}1iS3VK3fj>B0QjIG>|h8v*ya^?P=g&j zXhY#NCqu3XKyi*~o#9N-JFm#i2gQ?|%&UrF6}F zX)_zyI#|I@KAZVtB49xVG28+TsYs3_0d|>S?IjDu+e@>GpoHa3B{Hv^3iUcrgk^1I z1|^_g5lS!xs`#P}xH8N?$S{>_h;=Hz$O0IyVFoi);THd}0y5(&*SUTQrgpt6Uh(4v zEQltW2+QBZ`nRE}WK*5yRHr))N>6|$7Nh5^=RhGV*~zNYpYIfCV;OtS#VQn`;asOc z9a{r)cJ{LHWal{T*cLqcBU7B?)Uf751w@EKEp$Kx7}!Gpmz4%4D>#V34T3uu;r;^$ zq+)4albb45RppU2mSF%0TQnFm{NEl5VM%dA7N1n=1heX;^PD?AY;GKZAWzfiH~w4 zEa3^G&I?s&js37-I>1&_unSu3K=}zkiy@Y>lEv&~6MNV(jn>4Eb#Xljn^?{Yw6u&( zCyY-#+REwga{tJjM?VT%l#<1l|479x=8y$U{6iGC&~Q*y3Kv9jB@l*qizjSg7#zIC zxHiy44CXSISI+(e2`@qaQUM7Xri-sS^Ig0g2Mv6w0uqoA zFD4YB2v1;w6rRvZEoec}Pv}Aynr9m(;NW^q=uKpV^Q}rk!3uY-q;Qhc=_)`k5yxS0 zgSl%T2&cK#u6{McK%L z=;8;(g$u0nE$?_!#m%aoT_vY5h4J|DkH7P7DDM(4Ki|byt(oq6^2>zRT)_%exLygE z;8for!C3~MiWNSNVOw(N!mR1Dor?Ce)zv z{Ix$rJJ}i}HlGRw_J|d0+0oh!it~9TT zUsc87som?WAwVC1l+rTu2c#zyDAspm=5@lcp z>YZB?1e0l8AQf~V6*NX#grK~9N9Bo6T|FQS#-I%T1#nan?A@F+#RazAnlOF!8<&|JH$a6yu&d(L!_NUEnvel@X0frL*xMB z5cp3Hfx{G;&^dI%KbXTHhLHpRr31^b5H}dZ4va$su?&akgN{t%7A4^`bixpz5g`&3 zSL`6!T}oA)-H>$$e{2R7+=3uf7cBHb7nGobq1%)pmv8YR7(~VouuC8yK{M=uAqa*q zfR%C0AYMh_tGv$P?M1~kM|gosEUI3f5mjE08W{!Iyz$($Qm@^ z;9uojhwWUZbWIM-0}_tG81z9WyhA6H%nnpdCwPe1aDyr=L4-uX8_)tX`~x$jget&5 zBVa=uY(pA!!5A0=KKw&eKw-(8VNP_yIPk&}6azu-z&Q-TA*#VV@L?y6Nk|^ULm0!9 zbdVU~12W(P2N{YHHiAC?jLjP7MpcC>zF!`>Vz;4GcThoW`~xBw0vwQq6rdje_2QXT z1r8V&82rE{1eYOrRW87S8Gu28nZa8GCcmX)Os!dSO&~eag}Y!vB4_~`n1U&Yf(xz% z7cFE-e7GAE${+XjKdh<12$|!F$fLV zG{T0wLl2w+FK~$#I)XmbkSg?mKAZzSFc4PIp(@~mF`R>;oI?-1135XuGcbc1T#-K1 zfGTukK}5lEmIKQFa0Bn<04?Z)D$EQMJwq+bgG#(X4j6@Xl9Ms$LnB=05FCRj(BW-j zgE`OwF}w+Xa>G36XW)2~+Tf&zG)XsE=P}TNF~k8ekm5hggK{D#gQNi=?pP|iAM^Z! z*}Ya;!eVzYhc4U#uWVN~a##OZ1(ylejQ)Ud4aSUe*$?F94FmyQ1PGO>8<5^5Y61ph z7M?VYX0b#DDyTwaloc8PlV%=_p1EUmRmBSkm8+Fzk#?zaxx^?I3nY;3@=2(4SnG@>_85jLxH|TG4Npybip~$!Z5%ugE64wj!cn#G6X}sL880^4Yg1?bjXvugHw>x zJM;lKa7Z~2gH6apPCUsxOimAs1SY&gQ3z^sDrXIV-wodvDum3=#9dh4#WVs){*$c{Zkem7I3QK9$`3e_WBP@1AORno zg7{2kp#cmp;}P%(@{rw)NFjKiS5ggG3;61)UTB2aRQ5%GRg9ALr{5Cb>= zIHD-*E*3?>5Qu^~Y{Ly@2rYDzF}M&)szS>EkSb_mA4pCQECDlcLn90UP+-Fww9Pp9 zX)VCv{$heTtn3#8q3{Nz8}4eNW*8(ji7k{?4Mh( za3p&UxK4!(U$P8W1txDYCwH}Z;3Bun zh0!HfRHwtF&Mb zw&1a}?BWHG{(}(wgC~T7Cp-?rgC=qHR?Bo& zYqfIA^jJ5yb3eC3XBS#KH0nU~9zZl147XgvvQ51UwZ33poCX^I#2qAK&v1kw6%)34 zulK7N_7)3ifPhtG&-eCBwtYM7O`9ngvsjItlh#!hR&1R}Jl%`|koK`QH{~%sX`M(U zR6q%xX|Fap)fmwwh={RvH}zhxDV@;$lZ8LYJfR`h^_@k zKIXASl91bgI3~o+4x~XosllPcP}&M_54^z@>Ejacar>>7RX74johap@pkL7VKj?rU z)HGV7wG8fokQ>IgQ$_2rHMrA-TK`3nJNc6*rVvkK!%YWfKnHYiT6BfSX~30+qTPMcbm64RfK{J+!{{b+CT8Of&eNnltUQxKrQG43}jKouWvc9Ey+d& zCY*yY97Ca;!$tG~F%Uxyl!GyFgO(sKF(itRuu&ZU)Id!rr!nA3$w$Mhl6=p^YQ{X978X_2_M4{(C3L1fkQ3iKrL(oF>C{z6oWTd5ifv5IjGY) z6oW?c0ye18HXOq?(1Ivzr6bftI>h?NQ|Gbb5ID@dH|_K}{X+y`Hi76vRx|<-h=sN5 z7DijEa1(B~&ooysw7!Y^Kcsc#mpiz(dv>XNeY88g$F;j(G!15f7kB}qc|jh4LFj2l z30%)K*cVX!`@qjW?b}tsyEGz6cEZ#5!Z-X>AizHWf5fv`@(??QzZ5?K<|KWTB72m=TJVan~zV4DtFW#mg;G z|Il1fy_U0=ng62vYohu}XWO@N=hnUdn|E*DzkvrAKAd=Q=N3$8%?N;J7ecSCglud^QY!xT)m(qym0wt0-GwiLU~v7s!pin35K)9k81 zbE_hYvQUwNj9I73F)e`sUW*I$7RR@h;QE!Nm$J6rB5p`MFQI_j+3 z?z(CJ>CU=py*mmi6v!jbsvY8Z<{4~i!Kab@{^8}7bBw}7G;F%aLA+XMnWu+;o*8hM zPIwU#oF2-#l9x`n8KZ_Vp84mTCxwjZA7c6tN=Q*^sliF{Xd31pY*3Ie8iAe};~{+e zu<@Vuav%>MTKXNRO`!}Dt%h=j07u|XE*u7&E`(~c5shVpK|u%qX+$IqRq2<)h5w-! zh1_D>su3H$@^dIag&S1=tgdu8>#ctR(Zd;g{xQW5wUAxZ4@6(%^wG15@kc0pAp1uT zK~4kv>*3nUqq50_BK4olHbXU4D){(^3ZZDxMT;y}U5kn;Y9nfhv@y?I^UXQ$+;h#9 zZLZnf#=_1jPG||GI;%VhC6w~OD@yA8Xc;CBh29y1nNDQvq!wP{04I)(qhL7=Z2CAx zls@EhH-~ZhP{qk-a2jWcPM(Pan@;`-xC?OJP-PetoTSN^;~TMmSsH77pSXeZw7qza`i7fh{8$KM-HL7&&Pg%(tShmI$9SEW=aNz|% zZlR5TAOdZl1J2s^(6*uI;TG@6Lpjn#iM=R8D3lNdHuPYay#>c@p(4tth*GM;^`;6~ z(8E8F00&xV!4!$WLgdI&Ib02830i=H5%HKuJ?@c@eFRqMm<1iuU1xPe;RGk1A{1B% zWp&jlk5xDjf)Aj8l9UVqfoMU=f5?wMwd+I(P$0fOgdhZ%5Rxj0;fN44jTdV8#~2zB zf-ww(7Djd{KqGcxl2k?s)V8JMJFm$i(!o6lKkS? zEPG*;S=KWD1W_19EqWkJS{fw>wTsOvqX3d%*5W~N7{)7%k~i^zBm|Bi1~Oj}f?H0r zm%SvVBqjNe2PEY?Il#z2qS1|wz2R?GD;#HnqqVSbjfY-Ciyq2RjYsK1Q+~`15|!u| zJ?Lc-TrmYW6m%9X7LkjA@S7Kh0>+_;@l?FQiWd^`4=>Dt7Gf}k;yN?A+RS7UQHVkl ztl&|lE|sZGb?W8-=^R1orgViA${~f)oqzaab=!ub)od7198Oe+6@80Y!1j-KaHFG7?FvYR z;x?g>X>Q*zhE-rerj_azID60(Ou-VkFb>XC5Y zffj5VUh$5XyyYcJR7XcuLSD-%xgg55z(KYaoHeWwctBaVLRZLk)++j?FJjjs*t||Q zIQUg8eeJuI$Ue5ReHAccDw`Yr4yCO4-EV~RJCw6_g#$8Z=xHCSs^wtiGgnCJKc-+f zudJ3bTiIa`)uI<+))l|#uYer&AD8=UL#yl~Le<=ITjb-@4p}prmqqdA%`0XvQgr!>y!xWS2%(uJZ z+PC<@N%L^GjmL}bv^eH5i1G_;1p!+|<6GZIzQL*6!sKp~ap_yR!s6~Ig(@!#I8Fcf z)v=!STm$Oiy@A$yDQ;C^4CNdDK|K%j?Qx%b-P3(7mA&j!>#JY?+vEKodJl0G zeoK^Dj9dzahdEaOV-@2P1}rI+?^JBaEL7ni5`h-Hplq7&YP#b2wj%n%s4%MU+zdmBHpTIVZu^GLH;ii!ZeZUu zFZ`OT{D=hy(QgNNa0k`TS++(y&WtRq<7v1e0yscO#Ou|DVhC0#wElq>zKj<_;LiGs z0!Qxn%7O~W0Puk7Gz5<74vodu;%utO9Ft@DHIe8c#0}ZDSCx<^6~-t6IR$?(9JraS8Bh zu)>kfhQYqpPS0d03oTG9G!Y3t_9Ji%%T^g$gv06WhQLv;e$r zAsB`T3Y2BV_$`OFA_h{i+z>M82(l`%GAp%`78Ua6u+rT2kstSf6_cy=5Rb*o(kyv{ zGR8uNK@iLZC2Tigr?XoVZu`}8aTZFJL3n>(~(Kaq;F#mxt4YM#2^Dq@NF&T3) z9kVeZ(=cO02?wj$=<6SRvI2ur6Gvkx1Wy4I;c=RB44;yCU^EP#}HisfMUvoCWKn%v9k~JlKlwf1|9<&yCOSqQp337a*6;k&(l27b3M(oCX2v5+4CRLQ$FK! zKJBwU@pC3^k|-jk)>L8cG7~7r%oqeg3Yg#&ioqB}Ln#4mGwcyL+3z{2Vg@O+LM`+{ zF*HLpbVE6GLn~uL$70`-Y5$y=RwbsEIRZ|(KJofbWJU^H%K)9Eq~=iKXMOQv`+2R2T^kUUeq)tBSxL_ zZ+^f>iQ)lZU_TLaI4-9q8?h0GWlE*S)@T7hD@Op`-YkwZ@N@J?OzRZY)DM>Nqcl>KmEJc+_kBXd_3^E{m-3hreHYBD1d z^DzJ66oQpkm6b5p0wj(@V;FnqnyAW+>jF|5(m(QhyQ?3GGy#%w0n@UEwuO14qd= zFGaIXWJ|VX|4>#ZLo8}lC~%-=&GZHWb1QUJD4Miq<&#nSpb>|m3*f^lo*@dD#u02G zV=c8DqF_;d)?wF^b6z11-T{98;XtB+d!WKn8Om2eF7E_1wboHLPSIsk_51wo2GO={ z-Ilyyw$x;nLN9~o?6xq3B4@3_P-l`zaYI;b@Ta|QCH+A_aZZmIgaRAM1!>V-F zDrRz78M82LatNZ}9e9Z-oHYZNpg%3O|7dWxNO{(F7jsy8S3$ToD1;;(h(RAFVJrGo zSUOkaJQkwJ_BKXWb$`Qj+0}c+cYHxdUIp=4+Mp1LLaTmFc4yae8a6(Kl)DthCbl9r zcqSO;fqVRC8~Okrf>v0iHfoJUa$$xjgyb9)P$)zLYc*B|JXbThj%696d&yV5DgzJ0 z_kuaNgMWo}MWyv9VgA-PtG0svs8lHUR$rrbFqw1+(jWt4qj!5|D0pUggo2lXw+k3m zCo7Z^k7w3|AmceQ5Cg^b3;APkBL9`_?&S!EI5nraBV@7j{!N5 zmBW0iv5Rv9JH(hP_VY0rnLgJzQ3H2B8Fi8u)p)&8STXsLADJ=zwvHhfd#yE(%{GcN zuY!XkIk6LbRdzQhSdd-0WVbk`#C0vQBaz=1et$ShDOp(Qs1e`uJt_H;*SJXAQ-Iev zJ&kl~YnP0*&Wyb45IYVDtKN@&M@vv~nRbELZ)Y-5i=cLQb}N=yN{v~7mHAMQ z^z^QGhQ=0}TiM&t5-M!~{|8_}7yh9X{-N0ZAs23-6ky?XHBK4-K^HvX27aI!WY7$J z!76-V76Nre+1ZNY`KI}Jo*`8B+SicSjQ;c)vIOc0%X4bGBA|V^jfZtVJK3M<(~_Ba zSmD=)0~%Lj($?(H5+~K6)={EI89B>zS1KbFvY;8zc@``MY)qwUURMadLY#9!od1Cr zzkQ0hC(xD&^k&X5PYF6V)W?TD;Gv_C<2wOZy=}aG_UED zuXS5|{hDM~2e40v|9!h-9H;uI@sp~F0-4`4p?_A9lT@LLSxFOGNh7mbftkbdzbitgRqZ#}ZGWNh1Kw2_h*HmWu7jg>+%pefzdcCs~wV%FPWH! zxp<40!(DhV&$9-un~1%v61BQd-txP_TQx>+n$r>o+$$Mp;TL|O6xv{>8|tHfKr^IB zGRWYif1wTfv|dY+zu%cr`dh%E+`I^!D_)P{h=L_K!M&7?pZ9qjpXSTA0?fsnD=MkX zD=Ey){L8I6|IIf^&Hv#8?kvR_s}Fi1gY5jy@jTDk=C8lTL#oO~>)m{D7VZAG0oxnUR*0-Xs%4)3U3c?;husG}2fj!uTeb|Y;*o|GS&W^j$(YwE! zqg(MES(e7l61gfggJ0JxD3qID7eiT;(~rgK3a!aTugN{V+!qDZS*MX)$AnqO*%yny zJnjHvlI?6y_v}6H)Q+yQ8AGAOUt^gCf)EN9g?sbh! zC!V~i%ITlJ2d|xbr=Gbo-Vd=p>!W<@->a6VrFB%tbyQ~)IN|K){oXDA@-ZLa!R#_| zkL`V)3Z~%NJ|PgWj10&C5vFU=k$&$x7z~sgR0hB55C7I?AMpcR@dF!MApaUWdj8@M z|E%&o^M!x-iNE-bANRO??c37lSH&2d{~v}y6v%)Uih(FVkD?vE{cJSp?)Gk7^;4um z$&c>h&7ko6u=Z_Vx6vK!OxSh6xH`;0*AHv{>A(K%|Nikm|Mh?W`M>`Gf`h<;1PdBG zh%li-g%27w?zb7IR6+o|K{j8 zGUUmRD@(Ra`LgEBoH2Xe{JAse(V|O-KCKzeKhazT(r;S0Gz=ahab#R_%0$Ul3alwFK6&Pd~Q+gwPajJ!q72dN?KrH-kC9}IMY931meezf(QbpTstMzm3C?=wOw~P!q}7<9_6Xl zM^aK67N%2bT4<-9ehMn6R)U0OSu)*#1SR>cT3CN+X~}A=u+A!Lt+d{1Yp%HN8f!>-Gtgoer%qg*MP z7NgujoN#RR~8$LJU ziZA|n;*Gy7R?IU``q33tuyn zsWSaT(+wEu$@fd$RY>^Xg|{#G`|`U_fBcWiO*#7ObB#a$|N8^Yu9`5*1{1p6*FFM; zD?kBBPyibFx+N1ayoe`z(1R&B0uDnc&tQQV6ri4Vv<+S@YI@MaS6FAX9f2!cgi3`b zj@OYvfpAcQz{D&%s1rfVqZFnnhd%y+2-XE^g1Up@j&h*~oDffBgxXP{0#%B1yvuoC z0bZl>r@pL3N?zXUq8Gmi#xUXqNNN)w1kZ@ZG^%lpY;2<&-w4Mzrg4A;gcbso#I*-P zFm)6pktR5z2SFghMT9z9?jG?EKJWq^e7M>pl9z}lhKp#$OGF7Bi4s8=f+yVg1r8~J zlTA`E5j>d%JSYfCDjH`TSNn${5Me^tB@B>yfWI}d5Jg8mfsKFQLlm%+;kXci4vq-pANc&oLOFtu zaXfSu_`pXxQt^*>;DZqy(I_U48Bm74V~{bV=Qa4iN_=ocA10i~A3O3j;sZ4FEda#+6e+7&TWN>OztBQlHW|M%< zvf}}NLo>0Qj!$5KT~CabJAX2Qqouf-2@#>v|3>zL7vq2-IDVJ2=fG|ru-nEnu699= zB%&kR_=O)-x@qe2sGR_(2Ce`{5!t_=rmC=4e!ffxX>s!Ysn zu5yZc0B!MLs6)S zYH&ouv$*AY-*HT3fP)Vt=7TaC>J=)c|9F|WUCs}x0 ze;UM*FERHm3$mt}9w@$XVotkg;cj!hi(fx{;vcsVi9H&ePu2!jpqenDE*9HJ$qIuP z)xZXA1;G;+YeEyDQgmPgvK=95i!h-Nj#8NqJ?q3jrc4Xg zVgefr4Ja(|5eRIcBM`sPg)_hrh*V${h}8fGIK~m$f0&}71yknkT5LM15OKFRZndjl zt-TzBrF;M*jDWZzrXXu+$hw9ut$v&!Y9_Z&WWg>unOqhp*TlQ;QnM~PatcE0!yc`K zs36dxi9KlJAA=nSNu_906N2n%{~=X{32(~UlR)|(_7Da-+KLih`12p*NH9eI!Hp`j zju$G$hbj6n41pSFvF!baI}I+3M8Lz9|NO;CIYLsGNHKP$wk?Z`nrav$b;hvnxW_;K zDOrDoCjY>}e^5do05M3{Dkqb#jvSTe%6#Uz1~z_(eO<1~EW1M5ZqT~L?BhL+Crwl$ zbS6kNqS2F3Eoyp;q-HWSBP^NHk-7;1B}~?tu!K=YVIK03JLqKnAHRezbOHfi=>YG$ zyZi1=0=coB_!4Sjhg!vdcX2G9N!86}HOT)C_`t(Q(2eG`lFZZ=z0`quR z9X>!Whdh4|255B{-v9buh=>_ppks8N1!Wj!m@b>dStTwb-kPV(%1>y?+~@s{tragpoe{T!?PmrsmfV6}N$@A~t+hA#P%+*QZc zb4~Vhd~z_i*D)T$GznNT#e+1>Q!uiZW-yXwDke-CQ$qAqTh+ES;9^@MgnRL|M3a<& z7MFc`cR1X)al9pdE$D(SNPc2rewF7E@rQE$*LcB(7VNhln^!E4cVsx|fAOb({ec*l zcX^Y?e?Yb>LhuyU|5Z7q$8+XHfT_nP67)JF6oMvWflhOKi-J4GQ-Mx{5?{Dt&Vxc5 zs7whnC|n30CP-8$m=P-IcQ0s%cld%a=p8UOEG>6~Fc%oO1IW?t0g9dsyTEQp7}D2z6yhr;4((3Mv?^LY3%e_hdeIY@cC z78SOJa=JzsL1qoEk_(CG63&2aC?O1+@DH1C3@C9|E+Go>G>+o9Ve+&enOG)4_76_@ zf28+`M^c4o{{#kSr9!CakN*gesaO_1v0}R87WAZm*Y|)Zp&QlnOus0Mz&MN(=~Tto zE6)h@K#h zsSpaK;17w>5i6-B-=I<)VG7#t4*CHL8pe4pfnpuu3kOG(j^+}uU=QGMfACmyfI*L) zIBQZUfT1`R%0_Z(hcW?amS>5UBjXd-7hiFKiYcZ%UH}9-fP(JQeMxnP97mCRNn;j? zEXRlv$kh?QKyCc+57jVn`oIYbg@c^%4IN>UoKOmei4s3FQ|y*kl!*?TAVoarDx9!z z_|Obd|KSh(@C(T0nB&Nijo66d=nNm}CH6O(fT0ava&Ub3hghk8TFHq3xN~1gg=8U? z|3U^k(UxG6mi}0L)JJ`A@s_7}GA}ZhZPF2=S5$YYmwc(6+i6XH`C~N5Q1~7XA&SuA(; z4e)SWoNx^;Q4R9|7{9=dOZh9zs2`kw53k7)+vW+Jpbhxoh)AiMV6@l^dZK8B zDuM$#;00CX65PQZC?TVb!Vxt(qm5FdH>#r@fulaEqiv9*bAh8m>J>kVq(WMxO3I{6 z{~DxC+7yRFIZ$YqD;SK~$(>n>V`LOQXmN5vmR}svp#G$c`I(>m@C^@Y4EE=q(4~2y zzzyK=4Kt;bJJcWe@K7A#4?lE``f-`=iJ_tQC`CBP5x3w8&VXV<34|P)gUpCes40$&|A}wc zC=8rn418J`+vs_lT4esGtA*#4p_-x&c}Dd(is0n10JSgWwO+O-@} z2y|h*ZIK3D@wE|Loz5XmETeI3o4pMD<|LWr2h!u~;x zW)g&9A$dj%i1Pxb)#iOmZ3Qiy8aDTg=6E5yAnBeqQ=2>(_!goDl}h6$lK93F}N0>k&(vW?9T5D&+#nJ^9;Z8|HuiIY@Jbfk9g$6ZcN3> zEXy204dT!X^pMM7Pzdz!%(~nWw4SG>(xjF;i8(ksmoAq*3Npu#M@7XM*B`Rs|HddfY#z}<2KPMpW$&<(NB3mh@j z(VzM1eD+<&`$_biq1vjuJro1G<`@`j9#8aKoU+W5paM+I^ z$%I@ABi#sf&U2|z<|hlJRxXp z(_ggKR$3QrZP&96Yun3J^SB2Zq(KZv+hPGq5#p(z`kOqAY^luCVXMbo5ydF+z=-_B z&ppM_T?mqF2zPwEg}@lppxIM=J$+2aQ=q)8jmF&b9qiO1-rU>i?Y8605iwxa)P)1o zCA}5`&H(cREfd^1x6ere*b5uoWD&(h92JQ?;A7F<1s*Uu@Bi-Y(87hX%XfNYdXB)T(2f$b)>yi@eBq+~Rx?3wS); zHQwTVtjL9c2h%OYIo{mfE#o?l$ca3}4_xCc{}TinLA+k%;J=#EA}-}x+Tjmt8?Op~f1%(;n_F6A}X)5d{C>8fI<-GLYsRVG%I^6LhHqu3-@tao-9~1Q^2PXfEe4 zvEUr>1FkW)GQc4k;Q|D-;CWt6PmZxsKIM(hm!2%VS}y66PU+mlAw!_ z!LH(W(dGR7iM(Zq4r9?C$Um@PXIs^-k~w z|4sLf(_U`eLL<}t&ej1B@!&V`22b%7??wne+?fuRn?CGO<=;6{;(w>XtA^eYZ}J`2 z>nHyf;Ev+r-tlYm^4s~^9IWy+PmI`Z^YOv*`M&U$?D4HVtTSKoIZyP#h4V$<9y`y* z9Pjf#Ki=Fa^#6|ZQ%_APPxbnp@W$Tr`yLff-@#GO=vOcHVPy4VKXRC^@J!$IRy;nY zK0xPAZ0GJ0KyOuGPwi%p_px^LdH?Nbuk~uLA~67?%0mVip&>zF_+uUwbkGJiUt`q#Ags}C1SkII1W z938j^UclF-Pzpd`1G%sV8bWd!Ll?BBml|G>b?^$$m&f3T1gk}!C$2a9xQbOM~r_REtWC^ z<{ueP4XbGScZ1U}Pd^O(`z7R`u9l?^LL7MG;Lo2ngxUaF)aX&9Mv1lr3K5K%gH@^| zrCQbMRjgUHZspq5>sPR0|HY0aTh{DZv}x5A%_7xp7A$M!&ZS$|Zdsu>^qTzX*6&}x zSAG5)TG;SEKYRQL+S3@!(4xP*{G0_wXP{gY75%-*uPuB4l-;&8^}nkF$BSg zK`2d9`2~%FXky8sQYhIY7oQrU#3v3f+UOsGX2R_sh(^T0IGoy;g~N${zySwOS~5er zjtT(4kIgo%8Vt_D$er!2+tJV`bY``HAVSJgF z4n~Ff2P#fB|H_P|7@#ufhIs!;CCDtEgc4I(r#yC8jyv|au3A6V)z>P375U_ji|r5D zzuaVYC?XJ)nF#?s63Ry0aBva48}{%8xS#a8Xs88m{wIifrQ>VML!6wHH>5!+VNKl-qXuZMZuo+2pwE{!-<>SPo2C0bjNu z2BiNHLkusND2y<~ePTLjq3LMD>y}>B>oAL3`VQgFh44Ei9_Ure5K!cIrZbf9kh zjB~3l|2Lib{8A@T?rpkt30Uo%_r-_gPxjd zef#_OUoHOq4=v;qU;)8`KJ|5veQ%22{Dv35>b=i^V9_6WCU`*%X7D`()L;kU2emY< zOnokEpaa|IKJO6dfe^%C1q0|o7{*YBTH)XfJBYvplCXg(WZ?%(__7ST(1t@4;0uXZ zl^Py#f;b!@-x&Bq6QYnRP=r$u&9FZuX7P3WGolual0+~1kBPd|Arz4!MIKV|a4o!| z1;hBpws8@TRsrK2#WzO1mGOsKS>qHXsKmznM2L1IWFcQyM?=~Uk1W%p8XXBm;VE&D z|B0let`u0we;^W*u3IFs8floxeP$>lDherqViBhN#FVNG6i|K#HV+0ee{JmICT)qI zOIA{ow~SjS+4RZ7*?80qX-i$&(u1tyor?mB<_u_2T6R>YI~5B@d3vjlCaWsFV-`(iT2hmyl$|I&|7la1 z`c$Vz6{;!yhYak~$1maZpFiblSE=GtuiovTA|#^|eHYVqtfQn&1qw>j`c|376|QrY zYhBaY(0}lNEDkhb$F%Ckum(1)U={3^g4!~(zHCwKBq?KMdeW6jHL8=Hs#EVe(i(il zVw)8ZSNck=Kv#jdfch=Us|IkNx|Njw>b+`j4 z3ZAVy7|ht&3b>&oWp51Kdy?hiSHqMA`%VPd=m9tFdEB_=2nzJr|`U|K38U@F)9jSrwagcZ%M8*f% zhdc~y*_Z~pwiSlqh2dM;ASW7zUKny`Pon7VjE4+l@WN8soXesR70!^2r;bw^PkQ|0 z&U{v|g7@){KOcl2D_*g0*_i{HcJo(NTiC-UcCn3p zY-A@}*~?~jvz`5HXh&Px%mxY;YW*gmAvA|?CQzIO?P)yALmu}y@ILNLUZc<$+>#x1 ztUK7x`yQkX^QO0>%y4gf=Ud%l6{_iO zL-w~zwXHo5T+clJ7AWxux}X_LUJARLpFp8?6`=5Rs6)L8QKx#5gd)du?cC@Em?Q3Uy+ui}LfF9H(8ix&Qr(cYjPBzkYtGpoO0x0r~4^fBWg)ge%BA3-hOc z{j+cd{O4c)S7^)35v`TK@B%QH8WKyWkg@@*LJAl|y-usA$@;tio2R#8D_~f?LIVmR z3JkhSf`eFtfAGMg_<}E3gCzKZBp^W(BtaECK^FXn|1bE55{y9;oIx3MK^eS38hk+= z#6cNc10D3igZP5jb2H|{DCeV!>oSX}7?-0VgX^P$$#4`$`GI2pp*ZL%p_QD;Q9^41yMavLLsB0wkD>8~h0m9KjbP!47o6541rK zxBLk$pi9GqxX2So|0sw*&9u1#)PX`kM4=-|k~}@$!cn7us2upClXOk8 zf&!C}O%F_ipKt;n0EB}u0#JOx75E2G@PXol!QK48B%lFBXwHAw0utFl9lXik48oga zQr`SYGhG7>0Kr!DK<&(u_C(M3lutQj&-kR%IgL|0%~L$xQ}cY&_2g6c>{D^f5-X66 zjX8)Cr8DyWWscuWn2Or+S*qF@Dp3{hPjxe|rFD<}a24OU#3fjb)vTaZ#{|f^3(`kO3V4TpR!b9e5FY@fRF8T)`~@9gqPY-~k!%(F}r! z{6PwLeNGiT2q)lzBRB}#1WJM#1W&Al4p7~HaDon`SED$ApU4CaFu{540HBavpx^>} z-PcQa(tpSV-93m)$k*O{gBDy=ksaAby$M}FjZ~Oaqez8=px%REiPEs%gNPA@aL^{8 z0oXkVACQ3Gzg3^cw4TpU`aTLLAU}`t%ACRQEuCz0eKUr zQP{(Ex*Wo2z8c>1Yb%IOXf=UBvX4TF4L;v}fyg8*L**wPMIfezq;oU~n_w6*0;q+hXuYX}mcXbYU6 zJL=VpRLBgVzzJV~g|7XF{ZtR16<;Uu4E$?HC@|FiDB7cF-(!J-xVQ#xXpJe@J}_)Y zEO@%@8$T+Di|ud*=g1E9jpV;1(LV0K?VCARptx2&RIbfX$&^giI0(u734cswTAkY~ z0E0fzgFYY+UXubiu!1xIgDen(64L@Sh`kmC0}IxQVFn5|ID;&3P}-xK0^GJhEFtv3 zTo2OR|4H;;g=j@9O@cwl*L@9MQuJaN6v2at1XBEoAvR|&HG(0=-48qhE-(T@;8+)Q z-G2lMaxTTzr2(Hk0UuBVcMe53*g@Q@yD+XKx8Rmb0g6I}1vCB$UuXz~xCZ4&65?P9 zN=Onfa8M*zfjd5kDvgTbyyYv-YvE4gJ6MwQ0>;G;S-?eLC}DFJpstJ(w{)ef;J?nxPt9iROKj0U)Y2! z(20{sg?Zr%->6>g0E+5BzoN(lj?IKGV1n2qS_Lf%L0(7?6ouA6KZB_T2thwe{y12lkxJ_u@Fj)Ux=YrEFVIW`IlUWE(>3V8U3|4}ds zJE#&UtTekFY`iUOy#*rETI|MQGq}_z?|>~x1A<)xD*w%hJ%iIWiZHNUBb`Ao&TT@P+WMS7NA2S)K!W+B z&nnP~Hvg3tZF4K&zYZT@ENB8SxYU1STij)W5OvRg`xs!! zgiOgCg*F&w*|lI2&{VF*RRt!GSLTC*AOl{O0x94FEl`8OIa#UDf;7lK|JEtya6rQ) zM&+Nlgi+w@y1V3Me(`6G@#C5C!$2Jsz91Vv3U@8RP5e#c1PXZt#dd$e8E#S$EJ1n~ zXB(8wqKrwP%=acGMWGZ<+fBjAn_KfV^DGJsg;YzW<=;hB$n1y;Qyt`Faf@Ot0gZ1= z{bYiPu*>H&bfC!YselM8U;=~ThEgyEQ=kJD`;aTkU8UcWKqC^W{?6c z$c0TX7%Cw3o8UE7_=ozIf`c$?YtVwH`=|eQ)#~7CuO$RkUJji6hhO*TN##E{h~(;! za4qNqTpk=azyeg|wGW4aCLnTq$b?l`;vEFuiwz&%|65_%Pkcf#1bc4SmrcebO&| z(?5N$jG^)fnYbKCsVGzqp7^40-(Q4+$YX+=e>#W*`C=6LpCI{}9`9=Kz*!IkVIUYO zm<3%pYD1WXB(V-p5Qa8rIG*Q-e?UJ`;FhGGRO0x=e>iGNAbOM221G!3|K3{snEIm7 zT~<(&EnovXh=hNz0H6SN{QH$T_=zr{12jMbfas$ojTbL-z*wnLh04D)R~|O`@^9k5 zQU4_U%S4eP8;;>RZe(-hAr&eGZTz!g;|5DG8x_KgDO2Ib|C$?bOjN0Jr_P!@e*z6E zbm-5NMQs{YiF7H`rcR$ijT$u&MVAv{Uj5hP-zopl-X}sP%+wQOpyVa zO*vM91r}9IQAI*lWT8-wSB#eA6)-VWl9a#wGX)k^a4<&3tQ5dqG@z1P5o)Jc^6P>XJ68|s}tgyopTdc9iBAcwT z%Nje;6gV74)kH33QLVMs;;CewIC4u7w>Ww$|JAnOep{}&;651`MS?wfuDf~e8Lzza zddn>m_agDGzU3|jZ@B3KT$8^O4cr@21tWa0!U1oTFvI^g{BBfMc<~QT(0cbDjx8p% zR6%Lx((o3qY`c$hQ9&*S(heT3#B>$wXw%cgG z-L~9u(+#)XbF+PR+7tQl&mMXJUb9Vm5MDUpi80|MRMP$fh8fpF9(m;dWU-O86ID*R zgYcIq*kEgc29#7xaj&0i4)_rG6k%b7U{{#mAgK>} z4fFMci9MoFHKi>{+I!=V(b{YuV*f<-?+<|g>t6r~I6(jLFM)^f#6S8L2tPnDf)bn{ z1uJO53t}*X7YqakJIKL_9L_L|`$rqdP{I?EFokVUAq!XN!WP2tg))pG4QFV>8sZRz z6bVjnn&-nGf`^ABG@)Z|Xv7>M@rX)HA`_SB#3thKA4HVm3aL1eDPr-869Jx%xRtyg z7LR7ld)|1Ua-Qh1;!vr2ABCWh|GjcOgihKKkDtP~kuPZ_Q&`Isbx5U?Q+$wWGGk`uY)*~*5=NqRyMelQ#em*~~sY zla9QMCN-I9&1qgUnb}+>HoK`!Z*udS;yh-mxO9akSYcnb9E>sBNz8Y;GoJ9Ar!e0` z&wIMleELKuKliCmN`2;c?t{V#p(MzIA~d0tgWo@_;LwLcG@=rnC`Bu3(JBar6&l?r zM?30KjUHkOYfNaA#2^MM|2gy_SYpce1{Ben@R2$@0i^o`$tw97a+8Wg&>}M_$%|}c zr%1twB@;>1qau7%L1R;n$NK2Jco$6F)w1;Tb#CkO)DObDd)$1|kt7081S<7nH zv!az-Suhe?+v?W0!ZogPohx1IYS+8swXJo6YamGmhKo(8H)i;U845dC!XCD;6HzQ; z7n|6}IySP6oh)N3`&crNVWLv9C}%tC*@|i^Z;H8uEZ~5K)1o%DX!wU}QJaP|%ts7e zkOCDHlBtC-M31`Nt!{x9n9wSOA%5&yg!=lvn}R4Pn^dY%*Y-#RA(gol*`FhU+P~{s z7rKztBqBF~9H?IP|8P`IrQgO&O7M_!mQNWW8NN3mw89s@VWkidmG>Pn*0*NN+iDgD zy9YWTB@crmZ{f-tUhyLMzzQ}ngA4571UDGM4_@$uBTQilWB9@vw(vjl0N{U!NlGFv zA7|49*iYqukaa$@Guyd+%}Mmt3F(^^uWie}2lmJ6=`Dc>L1+PA^sHfFy>17-%3P zS*<73JHnFTu#g_CWescdo8vs^I^Q|ZbxskQ_dMr_HSAJ?K6J_k{pOLSIT*l{W#Xc0 z(O&lU|8(sq318?BsG^-N+Y$+9I3IFe`u7 z!Kmmvf(`V89yB;Xid@xqP63U2x4N;2Lpt%s1uIfUJmMuc+~G1t*J2j8);?T7n4d40y^Y)t~Y}@Za9oLu-^PmeaHR0dfE34A-2_{L$UU!G#59ydG1_+M$;8YcM8%j5Murt&K^ss-%Y-1{fsg}26~-|j?Wt1UmEPQekSkr) zD2*2fB8C4^m4U6Dp5dA5;hWq!Mak@z6@UTZG#zOKAHbPl8a_rH0nx1m$ofFt;&I#5 z4aND@1a_SbU>pJ=$lp(`&>(2tAP@q&Nx~o;!XWUJ*$e_8rj0D1TTe;CCiI^l%mUvP zVA~N60P4Xk^j#A6om1(-28zN4t{nwU1mIvGa#$b)iBczSMBmh1-=qTF8DJ>-|DS*j z;h#zYo;OvMa{Wl$dFEk@;_Ogi=2 z!Qe$X+TrRpDU5L|~vGyv7r9&>k29A_T%y zO`$2u9t8S9Yg{1&N>u?4;m6(CdF=r#l!6p)+$-wa!s*s%EWode*2GgD$3$=<1c|~wn1UdHW$fL;Eg*taDqvTN!Y8O*2VN}so!OL=#%#tW3%@C&cSxCNEh9N8*MGc0FWC0eW z4mNTNEM!4bZiO2z4}Q(pom|m0YDqdSWZ%$&D7>W~U;-ZW<|0gG5?Wvsww+T=C0xRS zAH0SY9?mQ(=itO$c~zhSBIg21r5-fpffZ-owVg0%<#jSn5(3`s^&kKFjovX}-^{{8 z&Yn#qpo?IX9{qzgXoY1oLw9&2V*2NQ+L!mq6!=A5!qK5ntfZLb|BWJU(ypM*L>z%E zfJ&_V!x3bMAtVwLjNV2NLKqx^FC0P>0AiVmRwC_Rd+Hk{paNXZMk*wrD0F3ZAOa?I zW#1rzi<&|r2*O*!%S>-H;CLH6E7(y0g$3GatlKsj*v__&5j2YOeLsA4-UYaMQiK1=RzoT1 zql+8|nkK>(^bndp1sUKc#NAp#8jc^R!YMpp1M$K?+=3{?|LR5vLnd4+wz}T!j3=%|swU2{47(REz~2 zQmqieh@ODS+Dhgi(A7;uQ=w>UbOI{yLL%q_CbR}GK+rvYLMkM}Th4-#66ZuP!XwZE zvzme^FanLvW3PTCBOIw8^y|vJo~Ift%xw_GW$7joaCKDC3xB^eTtWeCGok4ahAW1+Oroq9ww&POkC3q7rxisj<|1H@Q?4rzW%KR1+@1{hV~SigcxFlcrab zs-WV1{+9cQ>Y*XcLuEByiXD-?@L5J`3zbRf9JTK`;Wv4y1lE4LpZ1Cwljd%dNh;AR z3k=l1uB?ErV&6?@ew~msHc5PrLn5b1s*+J;2JzvrUf>h8A1>-FV~M1}CqM+>8dlt} zzwmV2PS3XH4vK}_zMr**c=;*inz75?$ub*7(KY!A{@3`S{A=M} zYBZl~Z%(XyY~QrX5AV)ZyK^w^7O<~6w#rqY=5_=T&-uNzQY(0huf6PROaFsVGH8obBq8-Qy7F%l+b;Lls``-eC*Oid-@5xvhaZEEsv~NQD1GQDGD5M+Jf&I_Bj1d%!>eXpKRAdXdb}6NBq!w2% zvgC#k&h0Ok7`5$N3E@YgF7@vO>v$&BuH1GqoOIkgq>q=>t|)5WO-k+~zIw*Bt98Cb zSg9zHihE6xck_$1O1Sv#0$QdB^jBKz6};$}{V(=#pR1}}yc*z8TpUOx@QNgIHTS4X z{g$>f4B6(z@B6Xn-RaT06O;k=eWi$zgGQ2 zGCi+W;(>-cmRr_%5k-QX`qgl%3A%S74kue;<_Z;^FR zPhK^-9nq8tKJJQRkqS~KH_PMPly>$C3|=~(PRS2&xfsvewcnCy%e~fl11_jw$}f>E)Nr@s z4xAEJ#GjnjWPG@Ie<4{crwg{MmY4SPtv_|rk?peuVf32L(6^piWCFj&(|dhfJO|NC zarS8^xFw0}3mUKAnsg5GKTgn&G7=Q;to?4ya6{HL-l=!%S9AiFQovj(#JSfUto_u{ zurMe)M;$MSJ89M#J#yX_RkFskD8D(wGhD7}R`j{_d>0)}dG` zVysp}Ye;o6E_IY7eFVwKE9D7jS@^K6F;A5pArlPpn+qcUl<;%n6_>gzIj~jhCgk!s zxTBbBtyhXi4Kb}uvmGwj>L5}Q?iVlgt&rBz)eGR3XBk4OmzC1=+Sl-Vgdey+gP#aK z?^7rt;l{%iXsFg4l`@NiJN;Tgp#k`!0x+LTUfcI8YVPHe$ob6s-KwVHI3!;in~(}& z_=i$@iXWX|&bC6-Gv(F@SLff99@ik+1{doz7Qd@95&r4fb;&aJq0n$B6eV?xNc^uNw zFzc%dyu?gBGezM9loin1CH|rRkCvB)GTqzzvNPms;`G*Ksse(XbhWmw<$oXon=fx( z`j+*Tn!OJHJa`1*i=UD|`Q#r_H4l38P>C;3N;bVnu6Gtp^xBd-CJc0mL?3=09GlL{T)^JNQRu3@-M}BKPJ4v-9oI z;dXs-aDq~2dO)7d{T|hde+-#js{4F{0XfTdpY4P+*8)i2^Wo8)K`g3;pRGI#jPiK6 zb|PX7C}Mj9uKpUhEFIfM-N#&7&yO6q!ub0$P-D}c+S8peX?}ve!wVV2w`v9-GBg-I ziqT}bFswtypZS5_wBE>imimdhKmQh<9(Z)fL|*QR00MrU%^4HaqnJ3jj(oj8Vk4-? zuve!rhk_(d1t0SYpLTD!B*@ z$M-boeT(`;$&KgLrhpL(VVykdu5E>cTn>g0Sqj0dPi)`2eQx&u$Levf&3Eg+V^k!XneEx-mRPS^T*^jw1|wcLX^e%WaO*%W?nh zwDEBq?bh-IY9P>hEz*zEOJ8ub=yp6Ryp(frXqh9KMIf(-a0Y(vHHOO~J?3kCBS!(( z$#hX|evu0wlpl8Ae{%BcW8C#RuG3(@8uEP9^^I=Jo4zZ?!!$)Gb4QQ!e`kNbt40suYkhsq0@|^EMT}!AVBYBp`D|L6c&mXo5KHOGf2JlG<2}*kv2lz?%8J z)B)D}D!;^5j`V8kdL}tMTAQH`iP}T_>cg@lvK@&!yirZ=jT0gF;Dr;$)IPdX#)rGy zb1ptQ&CTr3Qza{?WLCN1->G)hq2;1RZJcfQ(#PM8L@MA+dsnVkd&8Ca?S-=1Fa{!X6w9Yfp#UDL){@tkW;Sz2 zd@{GV|7ncV>1*{M2Zg?{xx(B+sy2D>5(d|q64y`CnJS6gZ4kU8mo~yD$2TfJ249Ip z#~Zs67F^$Uv3_y8Swxa*BT5&4RQ7hvyvMTfYR7;yax6FLf6)|wLpEO-s;U7KmlQU* z{*k;&XL(jmIpb@(bqyyE3pFkIVzUIR>Y-b1h|8clM zkP`QNE!^jLQkOCs3L(kJZ0f zYd0A#k*=1XlJZcq6o%&a zlkEV3|5<8#%!#KP8OF{%)D<&r9I-F+k>|P2_uu+d*1(xIuhZgMLgate#oMbyt<^U? zB<2~3GEMH+(qgyA^zLsgmnu|;*0_9B-yEe;(7Fkdo9VkXFgLRA_aQ>={-NqC&p`i~ z^5lOzwT+~+%BGgXzrVk{33?$;-_ZlSbXcTdu*Oi?Qi2$cxSv*G0D#-ja9G9?&DHe@ zdH{`Jo5j&qpcRrucY9jOU+%t@p}dL=?S63LuS4kn9rtwA!B9z;_7O#SD8=aa)hOoV zbd7oOA@nx{F2Zc887<_*QqR}Vx919JMx?SP)z_3ie>Qy9jmYQg)Kl5AF$!Kpyg8fQ zxP8`U^bw$y;cBo%ra!ZmbYeAkb*kh-@F3el11Oca^;a&Lhq45>UB$0Y;u*ueB6!^8 zQ`iApI#^LtLi84QApe$*S)OTTzF)EGk_*@4NMj#L*@w725>rUQP{KBl4ts$Yblzvu zE0C|yeX#-w09Fr{@X9FB&oE(5s5#d}k#=dWYR+gH^f_Mz853?EC~DEO$Bfp4xS0mW zLwWr`bc6r2!QFbSoCONBrjTvO5xZr3^Kq@^9WkR(J8G11+0LSG!oTsQrl^`dhGuAbv%J#cr>j|TCr3SNb3^7&_s4hdepzH~ z33GoXoJ%gi1hPY0ds%*Yk;@Gp!I5nrEIe{u6z=dUO%_5+VVfF?%7V3u=n$0z1K6}> zWEeP5mPP8$776*X5m?SeNsY=_(AWz%czYM}nF(xCx|`)BljjmGDf+EBk4b}J>#B>?G=v)3eFx3izDy&BIceepQmYBc}ji`{&etw z{L?vm;&FrT>qC`Cdk1G9gMJ;_oQQ8?{;@f>PzkeyQ`~?_BBxWeet8Srf2{xTt@tHh zIK6<-{kUj@IOC#`D{zaD;WWSK;MN~%7n{}UClw<^ zm|48DHD$Mop$uDXveSuQbp(qWIVylgWzRiIz1_sTsgayM8zH=eGOB~AaG z*f>&i8jt);d@=er<Gcu;(X zuM8?u0=+0$eXzL1-^eiV7aW$C-@P(=VpY%h<&~1mb+z^om$hdB~vlG<*dz6#=Ou zfj^Y~>#m#W_bi%#&M+sfPkw~DiGeI=l$Jh%79}P5w}0h~Am>LBWanO}OUf7FUU2ls zi%YD?CWTTz6<8Pz4Z-{eC!s5dQ1G(;0ucZ>}0o^c;$xsHy4d;F62!a)XdW@9{3e03HbX*wK2W}*bXa&iMbxXaVsgT|tVuZOwLN~ZKd7$p_8@awWl^FT2>44t~ zh3*vvk5FYYuB+4%fzU_$)0MyyZNc(zFgYmQ&$@)E_v1{vBokf3#Dj^>?erbjk=y%+ zw-3`*|IDZ!BQXEWwxAK1o>7bm5DSvWGMQsJGO*l!SiV`Tz!CP3EIL+Z{ZjasxVTJv z>Fw2thImHoa-xQl#N^3D3V8R-(okaaK-|zvM{wGx3zu7NC@|<4%zMKRu zPPD)eADt%zttozyz|4yVq)S-)R)}E>uTj6X&#elo$yI1AS1GZ$b5+f zl~7cb5y2{WM2>01p?fOk2PqgnRLDJXjjb#HbC1<6+Xv%w+}m`U1%09T0^&qAZRT ziUnbS3JTx@6KFIgy4xQC z$AStlkH}XYYK)~rf*SKA53B^ktYN40vP?6c0w{lcYsiz|#PlP^!n~TbBk|Mu0;9C- zk%Zt(-B@)cbl})klr~I3a?4i=)C9qyS=Oo~AJ4AYA6woxUk{5|{iR=J?C;u;<@xVF z&rvFy0ig`2J!FKLp+5|1O3CVh2I<*72&6>Ek1$0SB04h}-SMnM7LYI=`Sm?wFbrwF z%p8pcOD`i0(JWVODnmT#5({+4vY2E23-!Q}ct)*1gEbhCV2h88B=Yt$x8Dh?GnP4W znK{uMxQRh2FLRq>LC%y_=Gn|w>zPP92&X7Ia+$lz0#QN1>QacPX(?1LWL369k z=4Ys-B|c+!l!hJT0Tv~{%-Up#np|S$nd>dVeDiQeC9*!gsq^^ryT{)UP^^TjzRPXU zlq<*l_+_(W6YG0D7WP}c)s2u+_%dAq#XP4yf+mf*uIjiG$E0VMg!@E$fIgE zZi_;58knn=Xt^|LVQTaz5(WfZFD41>cn6v+THyg^?*Y;IS$lge=op*Ri#JhU(B5%QWwS)fJeG7XZ+*wHKNRp?qzM_@u|i5K=GLhSkOrr5^RU^K+iDkdS|_B|I5&WK};@oFxi&0 zybLbBSHR&sa0nJ$RscD{ad|V`H(BQ1D?lm_SJ>tl?^y5r%2R4wLJs3>$U&%D3{n~k zGQgs2QTJI;LWp3q<@EC!P#)jQ4^kZAcRn@NvAu)TGH1|XpGX;m8PkU>1r_iVZprxc zy7kelR|^^x1;l~D_-tpV0oQ+Y6#r;1-I%tk-XVCA3m9ZKjX@*E_7SD~FljWSLl1|I zky578$I`j;?3KNo;<)8XzHPh1SrJ6WvxcCV>I*{To&~qXvj*8&9%S3dU>_ziGtjc7 z$k>%U#tTxLB+ZBQ)m3`wj1_Q86jhUiqTZv*XxFABXSM4*8@yO&qz!J=CkN?%f zu$p6$#D1nG9;C-EuqljnR~^xQ<@F*m*Ml?ohFCe>gZIOb6}Y2-IMg0bn8z~fCJ&3S z9oIfDdga)AuOLLz4i&J)8sc`#$}!jf;BoM@8AHQ|mtUt2c}IS%IC$|C;yvH#Qw|Vm zY(ppvx=U7-u=F)Q(`0^hc^I5l*~^r`20X5u<#>e0(%{MOIsWcd{t%{$5vwP=bhWte z#QxFtwx3)@wPa|9l#++|ujZvtu1yobw5G1tWnl}Ehv|UFeHi0&fMdEH2OP#gH!(g< zILKs}F7+mh5Z%_FCBxp52;iTzFH69F3Z{&FAhB#t?)KsrjL3gWz@>sa@80X~Q!tHD zKoXf*$dtd{;~1@1fYTJhJ$}GRBDjoVj(lbBXzuSVAvE$_5j+T&%Md6Xq@M?L9)`?e z2K8eO82r8JDHw?qkeo~4Iz=|onedJRGD%cQXKT2a1YN#vcwxGvt*}W3$ecKJZT^Pc zXOYGdU^izCPZi#30`cRnsvpWUy9_$(uN;x9eq|FpdMw@NkL>yYWy zpG$5vXT0mAKhR^IPpyIlWUp;0zCR3Fgr1W$m46Hkbg5;pIY`^b0bkMaRGe4)lJXzw=A^U%abP9Bn;AU0#J~Wn&W@;8Nm#hpV zB!ynBIp-O)oJemlq21h=@GI_aXiA3aQmBnHZYTy)=CYpcD-V`FBbA!;4AFMQbwGB ztd%Y2V`1nh{5x26(s_Rcg=H@?ctGd4c;iWJdR+l9_ogUKKe@TJf{Hbt*UyeSbs53N> zEU#hfvo&?)byhi}dGP#!008H8bS-M>-t}ReI#{~>IE7JmvwkJC_ie>$vdYQkY6^|0 z&b5>UO1A&709_4Dgn^H6dJuObE3fTA@-mUds;|&uZTW>xV&aS z)~KAx_-&(YpDn#Dt*`fYzF6Nxu=Y4Je!RA9Mpfteai5`b?z}*VPHB^Ew$Ng9#1kxi zaZ(n1U~dcPR6i=2N6ujHm$;jpsm-;imnmxXZE^c|4+UM~qqkHoc{{bhW6>wUQ9!pJ z&5Gwl8usVs>d|a+4*)bta29l5*4y_3TZVJZ&V9w2g)nN=D^bxtrn$j_bjFv?XG~)+ zC%}hUFeE?&MsC`&{~&v1I%1OWXxmi9jGbo5Y}^(z=^%5aeVE-^^fCiykWnm1!8zLj zc#kNn`^jgQ@-EI^*A@xO7+{2sa3&*nkdvWTU^QH^T_^IR>XDw`1T=B8_~ZA4u|6hM zcwrix?@-52Pnn#UIxUA$L7b^}ZWe%4|Gql(?t<&eOsJlJEmB`5Z}#cHmUQF|XHNIt z-4TTk7^Z!HKD-Csc2BJ`75s2{_)E{cBz(BqgmUV-z}TT;^Bt#-Cl|-_k5rkzEIj)S z|Jp5UaQ!LM_p(2Vp;yo-f$OghQzS2&&?a+p%&=CC&d$R~jYrC6=Ioj>QF52PG)m`u zuulYf@s(pH3zc5BSX_dtU!j1AN;tPYF-FE7Q)e?z4IvY?zh6?ukS}^y3`E$X!S(wo zx6aj>G)}c=;m0Xh+)r*N=?8j_&eZC}2tPCI2*gjC$ej@{KC_ekCu_K0a3Ma}@QCY_ zl~#OY_K9$;Pga&+8j<^a6+u2-mJX0%(i&H1Zq*->3R_R~n|I)fJJn8lHOP7;iKP2+ zs;!WLCuJl$u-dlcRde>3zFiRD`{|!mtt%o>oDLlA!ZD1ZWz;+<>4$%Z0k?7eYHz2E zdBu!%8GY%Ci%Y1k*%rsgdr+u7()cLwuZXL>a*|!K)hp5@gmIz02xR%vo0-TxCbRQCR%-vp%3gm` z=#yze%WtOtTVH0nmUv~M7Imq!UmSEyMIB3Azj7+4aH!3f6I8Za6 zPv^pk$9)<$@6-jcR6n?>peT^S^2SlY zY+C1AY&_&xtQeAN^74Rpf>TenI8er(0Lg`T8OyrEP>yySHp9`e2zP9&Fy*3Y zg!HWEq4w@aUbD}`vmZTPM}2tIOO}3@c8^!<+CYbhNkdw1N1EABY1$&$gv6#y zPS$_gIoA!}<$=~6!T+=kG*KV(_KylenejlYy@Uduo71q&-<^wy2ia_!f|nUqS#_`8 z6(OILD7u{rcz073ZXHerwDbZE`9rWej;^{<7 z_n-0KA^-k;r(kL&(i!dr-AxBastms+2cNCpf5u_^UF(^7{0d1OVY!0(7;x|Jr(aK> z(E-(Bp9KO957J(quL&Eqjr_X>5Ol#ZhwMeLil-I2yDfZVs!JJM_07E1N|?RL)IMqP zm@~z!0%+`Vh6vkx$E$R)Wt`GJTW)w0Tta{QNVW-hEVI)U|EJ9gsKI`QbThm)-3i z_|W&aU$ePcm>4RezW(d}dHPx1lB$7xR*)p67Fg$ZKn{7n_C4w>+W*!aT;0!k92V;4 zLLbde4mi9B8CI+~|1(s#&p{~shR3LzxTp}$ZtKXjFP=O%`iR_ckQXKsLae;LZ4mjc zZOtkgTZaL@Tvz;t^j@>#UC9mu(|cUUSlHOH!Fxl>%byoK^E(wnTh`+_=kZ*pc%Dr> zHJ%M^9WEFUE}RoC+8Qq28ZKc6fEDup8}jnwdsK=AWMII37$fVwYuKkI2-Zk7rAQ6y zNUea#dj3e=fJlS+NW;@eb@~u^A)sV}jtdrLRk~edbw_B5U=aYZwB#RX$OYSEh zS*M%?q-^BCW#lE@yc60^QxaHZMeXcg+Xdj3pb@DAU>gDanZS5PU}%FqH6c8D3QJEl z0pEZ=A;1#m$+7aMTx4mkD=bhShVH8lm_$K$JC+rj?%3MGYf*9Q(Q*ofP5NU&LZ>hc zpiA3JAKIvOtuPy&PwDurA=M9?ikyPEM!;E5;iu1_IWQF0mV-GwZPF5KZ3FIuT9E2# zN%VqHYJ&XZbjLskW?@*5j=-rRTKym)e>vneo*;owMBZTSb_uW|q858$A$B~4Rs_If z7~2*+#V%Ek3YM<~U9*FhQ0A!F!LD|*@#W9laA2FbOtLiCO&VY+jauH6Sd2+(J%9Fp#4Qy8L+g03>*=5@Qp%v{3(+s8w)}<+bE6< zNVZD_v9UziybM{6vo3h?qZewul%>vw;@sj+`y6VSo7*3j%b!bUiwj-Sb}nK|FU`&8 z^3TIh<gHr=mG|x8`-*niL`|;)4jRsmjFF& z*Emn3x?^9j-C!PQyO!piYOx0+ZUu=>y^6#~ziwb5hXEX=!@8lbX=J#fYzlHyUw*!k z*4TSz`<9UM%xId%zWGSxH1Zat2pK3$% zji8otfIVR}I^}tbg&B_n3OaHNyM$nE(nTh=o)S|uY}-h@47*z{n!pgjW>1Fek#Zz# z0q2o4M~VP*BFb7izu3w%Vn1PW3mF{)XjuY8mXw21r9VxA4ZHyL1RwwwlzNtG$ELS0guKF=2pHI3YVhJ`nMsKnI&w)g)h183%RoGGMa@f8R6ODT9pEGqfKw4dNhV z!kvXBFtHF2;sv2I2b5wkRE40Ch3k%lQsYV577=7%F0@UcTt*o7RXS=Y4PVW02V%%66FycB9B>Y~Ydp8w-?)>ob;l zL!tFM574v$FAmBVDgwoY`&ae8fd$KxGtwmQsLs31Id| zy{)twDefkCCk zLKwZ%pRCDvq!kEI<^{5VCO&||Obgy0Y}3J)!Ak_d;3Q&|r|#1dAfg;#O9491fLk6j zQD*?>CJSI|V4kC<(<%lXW8f-9jomibd-gijvKp%xtOWz;vH~soL>sJS*}Z$Y3chmGPJmBbh zjL6p-o>7wDOuPR{u6VWYJ2x?KbBMDEYmXw2JOfgrK&OwkpX4s~Xev;ns?>1_6dltr zn+d9%ROkWHw*7$Td5QNJ1DTc?y2EZ-=Y_^qKr#CRPrctGml+l&!RMm13kBtE3U#Fo z;74T;$9l|SEA$eJ%E!>n5t_{F$1Nwp^c9n}#3%_9t2jHMESYd@ctnFwAxr%2ax&WNRXri?d=Fqk&20#uLV71#q zq%7qF!U$i2_e(%-UFG0~@~(1#>14#c{Z~^WZwz<T<5lPpGWQ>)^AH zXf%1kA3O1I>!lvNe0V%hw6Ki8z>I1@|FJ9!u7Vx0mM+=>{CEnqAkCwp=Y3LMhX`B86IA=_FVs`n@8bwX*QVR=AlJU4&ZAY9t}RZP ztW4jijHxW^dE1z9_T|8tO9UBF9|uMGu8MyPb!P}oqnjb^foNvGU++Xb%n>o81hJkl z1qy)ghf#aL(r@>PoWl5IWWO6w(^xrwU#WoqN>ksmcVfJ~?)YF`r(r3~dHp@-vU@k# z{zhP-%2uw+rpL%eDDcro7W!}P9}*)d*|}Z@nX)fLtKIJYRy4km7>`A9RKjjb26N`( zRXsRxWj+1zOwWnp3HE%JPpMOG^5q(8=U#3pPwFZbQ12fx4q|TnJ$fjW#;n)~8E%m8 z%Ye5kOTJjs9Yk9x(5&Bxq&BWyCvxq+U-oI``c4Yj9nRk!>E0b%+?}}Go#gsCef#I^ zgP#N{eNT_nXseg#*v%Mh(YO-oflm8350rQSYQt~?i*II6b%-_jwM-cvZ}J~QZ|nnf z<1NOmB4zIMOB%OAYVGHO?& zsbw)Y+KM3wdot}r$U?yt*Z4+XJv|%-wy!sx*rQP)(0{IiZ={)hDxg!zKxh>h<7)5Q zCGY%~zw2^&sHS?P@$g71^hoE;kzUUc<3t)F2cG{K(L2A~0ZFwCJq9t*KJj|}T=Llb z;W79#52MJ5^}`dZ-+7R@6X0VRizL`o>yO&~^qNP{OJ6XjO9GS%sB>_S;Dw+QX;9Z5 z(_8`QuQbRH_vrT?q&yi@pD$`rJI(Q-QyZ|&oan_f?_^n??#O}=WtMZ8`{SV^) z-(cWaFsS4Wyw&XN&=1tVO_g7AALpUY5T(waC1IetZuRP4=M|=m{Ex^@J||tx_p(m% z(Xd;a0Ee5+tcN5=9#u#+(visGzmTYdlNo(;vCwnz_4~yl`C^Itaz*uW=}qDUnRGXp zV0&>=1Cz(`c*^Am882)8<%gY18=0RoIk?IPX5OJd4{#%{JVsw!0q2xq{e=Sd5 zHF7AgGyK~(8dAN_5&E^2vi8c{PqrFboi<`@ve}Xo-da3`xX&RZ>Y}ccX~_x zNNRAhkd^kW_0-;*Tcu=k`S&o3ZSyLNw+{yL6vSZSwp}3r4$EEZMyK(7&6k!xZLhqF z-BBD?zrI!|U49ZU)AVE!3qBUT`1kQQjudsFsF~QRm(?E*QC0j(e&*%Smn3mh@OiGR z=cc+$(K>UHEWu=$J8{KC+Q`0vvI zCjPomw@dVy_S!>^(CeI8X0DxfZT8BJ=Y8{py9!ClGz!mI`-^IQ+Arhw%Zq;u`pK{< z2S01%WXdHg? zuEpP=fiTjL(PXi5Y|unLjFi!0dsNb(#b(z>0!dlUVCkg&sAYA~kMtq@e4a$Ku7KyT z4)B@=rDuGov zjf4i!Z*w~_POoxf>)nRm{3cFeGyQ@LVq-$mrwm+Gss7zZv3LQ*F~b~46WZe zL4&Ir%HhAPlQ$J9R_1gMYTXc@VUf`{*Kg)Lbak ze{5jm_KPvOxDu~T4g~kbCM3J3@b`}AZJBeabk+0Fb8hmzbD$8WbT`GzT^e`Eo{c#b z@$$alDEP~-q)cmA8&39Ja*`gnshCI=0lB(v<@T|P^`wx$9AD{Sr@ai#P(OK!epL#S z+pIx#_*JnbhMz*WnI@!SRM)uA`Axc6sHVK-!9|RR&w8Sdpi%1%%M6sl1GEpIp&BJ~ zEU#VqgrCCVf#%;t6DycyYzN~2j_QJ1%bi>gCZoQ-p|i8}Y}xn9R;i^dyr z|FQo1dy|DxkySeKuh`1=%AYQ|JkJ!5=MMZYD*ELb>?6rxF$_B~{p!4BsVJ2hC*Ec? z8d=SU%Mm!*X8{B3C#n9+E_}2mZG9Y7zg`$Sz6O#vVu*VJ9x3C+4xETMEYrb$D*qUo z%L=P=?~*C2N5cUbdiH^Qagb`TTq-VAsjj1E8f?Jk#Fcx7WvaDLf;7b3G7#1$KQZ%n zZF*P^j~ls_<(-mEUrrJ%&DC8lMxV~p-9C>?F%}(oL-~zP6x~qxpgj)q{5qni zf|+T7uRK=7Mf0SN+TM5U#+POQ5+cux*|jKl?7WcSD#&IbW8@i%``x&>*92 zABp~eFBp#~-MXP?Ni>BQUT7)dLL{mA5+kHB>tu{JkhPJ8$hTIq#+I02+6( zO1RnY+FIv6u&@1ocm0ox?JU0{fBGJxT0^(PiZyF08S-KG)cjw{xdyL&N|(EtG+?5? zHM0>Sv+VDA!;YlcR5YgX#67o4d5YXPAL9SI8WH7crMo6yBr+itJD_L3Q{)*bzy4Tu zE6;(X>|6BBvF^b9ks8w_E6$*e#zv|^_eE!2OfmFlxYXg57lbX{aLwD{{Bdr$z3Uj6 zqQV!3_}V{a;l0waCR)|8Kq@mSiu%TDkh`txmt2&XwCk9b4yI>cI_1vc-KLXyKhCus z(R5Ji`LxfQA(Y_H?0fr%>wxf}KDb#V4&lHAd!hSHkFk_X0&H!-h(8r#%Ej2Wle}mUGX)Xj~Vf zHKW&*d^u3VjG;Q<9=h{O73|^F#-6>Dc+=s|Z-WgERyGoOruy;R$bGOOTanv6v3DPC z9gyG3MZ!7`pxO<+u&QS)zeo4_8QS)zgFHXH?Q$w#QBgB~v)4q%4Yd2SkN)v)dsTcP zZ!iA%0pj+T&R@qalL}kz6~VLl+}X_+yo!tE4g`_A&jporUpz|r%^rz~X&-F~(B$HK zkBSY^kAfKX0T_A6~AHOSOUXM2|HufiX?0#8e!s7e>)b4T>w z4JzBaMK>VZ+e`a~u|@Bj?T3cy3OQEpO$*(7_FSVL`RIeP?k+M`E&J`thotU1dhgyQ zyE_d;acZj2n*Aa6cZq|}mj%+8^18Ae&Qy}sJr<+}zMPB5%fttP|E8VAyN8@~pn{hp zm}B}n1NOGuFI*e32OZg6e^J6OBrRonvt;b7Qf+=aC*MswF$%qmiV2-wenYPNr+R@P zQohQcMH8tth&1LzfFtHtFP>r(`GtW7w`le`Ni>>Ql9KprrV_75WJmo4)vK`pq?;-?_|G-5)*K%57oKsF7i4eEWYQ z>(Q3F?>)|a;s%F&5Yomfzor5g=~E&er|a;s2LdPZsOHG3;tT-kE>r_I;wO zAv`PdbsobV^0s6OhNm4&T#ivf)33zxXSuAz371u@#EUm?t|Ukg3a=*0 z|L3xrq_j@I!l3*=ku~OOz6;HQJYGxH5v*KGGf>=GOE=aMDNVT_r}QJ!+PU&a);+;b z8risLk@XzMtjFuQE@hSLdG5_y>o3ioyl1(JtaDLTNJhU{q8zl=b-93S7zu_CDVfU zh*UdKq@D}GnmrQu`g12%#&mOa2>FUCjAfo9P!A%R{Pz3V%sTr9>F|k@(3AuDeH}5- zk+&NA-5QzUYkZEf`nnnhEX-u#2*c)y^Wu-H%A1bf$kQ?3WKk}ouYCj3*5Ze%H#P1b ztKOP4l_Ab|no)x(`=ouCST>*v^Bgn0dP46xuQo0>`X&B+_4DNXGe^}c{ce=rjO?xm z{?d8zagOX-W>6oA7Jy{LDvDj&K<^kpzfW#^PWeVT<(aNyMdvNcljO&qc zf<*I?w*jXkIYO5+X?8kB)EjIE9be1-F1vjrR&5mZS_N?h9-o{ZlAD^DW;kgIs{tOp zVE#?7*ay{QEGkIlR4PJL#ge208X|9VYO$yrM~Oxk(mKf7)2Ulug(6cioPKJ|-d_E3 z%FD5NPbMU7d32hp1e8Odg+jkuzo`_3FknpmVV7brsP<)%N(6S*}VNkm#=vEP0D1g zR}KuPo7C5nr(%4LmN*?ybQ00~^0q2{N%vz5`KAk_eRh{PUl#ym+^4j>_z&2s>NO#Q z4Ky0?2oBerp?+mMM(rh&lq8fk--rol7S)eM2{Rd;C_2TOz+`stDvLtB{Y^KS6twvhj(H+2+DeE_LZhf3ex%MUm z*sroF?`krQG(`FpNU|$f--qN(#iBVQ9y^)|OB`6qnLpLAewz_5-7EmecTDj=)uFzf z6&7bG?SN9x(Pnak(Y@dl49{88xw!MUVx6>Y8e9kf#71 zM+J0CsKuKTQ*@t7sZ)~zh7^N>5}##6y!aguBZ{L)eoDS{VEA8by$4g1Vb`_`BqWp& zLXSu<5_*spI-&QXbfhCqklqv|A)&V*NRuj{G^KZxKtfX#kgkAHL_kqM5mAwBp67k{ zo;~w@`30HlPG+uqo##4^pLK?^w`S8Kr}b~dw4_LJKc5zSt;baoHx~9a&+jsKD7MU6H?iBy|hL~t!nMLL}-@-SPWWRs8S@fZqL45*Fzz_(QBY4-yC27%G9 z)?XQi@r`8VtcNpDPE4S68bC>2(ImL*6i;=v%*$iEKUBr!V}k?W_MPL-&ZGL2c92~M zZFCsdGvtzxBVjLmg{(%|fNPs~f9gTy$iI@hP_+br&wd}jej3bD0`C>JfJAGYrRDjn zz2Mt98P|AtuA^OhFD~soWsyCK>cdVPcKb51z3RB)B;&h~pWolf*^$wnI>7v{r0A6; z^Se(1B#{ejo-7e!uPYl4+4z# ze~)IVOyRHd`D;l4U(HsC7c+mj&U1fy>LtHo>D%mnLs#{e1lQyS;lHJ`!s@Pm2FleH zn%-7bw=M-hqD=fO{jaM0S{S++l^tyvgkLLrrJ|StV;3EG?Xv1$-wscnB3ra39t5kXpyo7&P1NM)wRJ&D!tBER$pe`%Vwnl=dUW!fisE$wzyHnhw z3wv@)&*DVCmdy@s@OuF*%h_;A(_`vrh7+6s^59|V{&`~EH?I2XF!%Q9rV#7zvF%Tm zaJx0p3~Gs~GF$+cX0AE<^9~V!3TtbadaSMpa9-0BlE)vA1W(}%;@ko_`1JcN=iL5j zQ5bEh#{Vs{ZqlH9ftIL&v!h|ve@TK=n?8%Sk%(f^^$xQnn)yMiUjuLdeT$p9y|lR~ z*TF;H(^;;xuy~aHp!fY(Xzt(!&&>G~+&E15rGdU<6@RDUpE&AdLe_IG3@N1jB9Hay zj9#fX&qURJqRv09Ghx;QKI>DO5|~vQGTKKWZ2U%h48|!MQ?lt_f9y~H zh<(d0hy`^+q38x<$qgQ-z-QwI8~~Mo0svw*60D#^_dbcjgONhOE`!yoq9eg0-XeZ} zN=`VH09*uU-vc|KzpsFc8xds7RaI3{q=1^2Ygi+bm&ZRs7gcY)dMr z{UX?RBWGSMD{b02qq#&ubiZTw@f_4;iR#Gpg!>+|#DPZ6z z>kBeMc!^$01LosHCR6C+GNW-J1-+R^4?^iiLIJ|p-mAb|Jej+z>FsE;a(CFiU&+ko z#&33BegCZde@VM^ z2}>^->a~OAOUHy40rn8E#1q!2>&`hQdD2)qUk=rFZr=|a1P_p(AMozSE`?(;6@mD> z$QaeLJ|NbJAWFJc3i1vxQ1p-T_wDl8rXD$g4s-u5o7D;BF^m8^1M)er`4NgfxkQ6N zn3lPUk3o!=(2qj>SunSek=rbT4d{B=v9m@!lMm*ur?ZhlEx=C*;KylS;_2IU1RB=Y zD_df$AR6e?6q^ebDH9_*w=FwAGUO7$W<`ZD$66j4M(WP6{RZbQWS&6=yU_(zxC-dB zT4Tu5O}_^~Q3g)?`X3+ps5lh&)d#70dhKFZcoog{X#nOFAG1{5oLO)e=AIV(en*Cv zs6KsKH8e>VM+t*~Q!aPWK-cUcszA?a;(aw5-Eo?7n^n1SBqVWG?x7m%OdAVvm*EeE zL93c+lgPYH0HK_XQqI2#HLOHpfssnd$qHl__VkTXbo_w?k%$mC8|Xfz{KQ7{b&7!- z4K$MC+Cu@|c?|S{t)5Mha6PQ2i(y8eh zg|@MT&%3$JG8WdA@6S40C_(iJAblA9zKs!*NGt3KK~VH@I5e>ouzO(sbsjK5aY`_~ z@5@;U!m>J;aM5hX513psSBF^=^ma-s#j$ksD9}E|m;_@XdqQlHmISh07|?V+(9Wlt zHHgM|g62U`BP+lNf?Z%ZnWb+cve<4ih%wxGqcTG1nV3aOOvkKdE(vl)1BWA8ur}c50aIP zR1MB#alsq>Ay^L-0D1v{@U}O#zTp$5lUI(;G49~^3%ZI5Wm067?z zwF}@GPwSOg`us@aNE~wJK*gKGwnX=yeH2t#jL8Q^PbTWx^!T*gf>qJbTb6N_c{VR4 zH}f*uIk*6FD6G@E%<4x_Af83zXX4vg%VGmfC9;L|J!s&R!5$<0S^D9h5DK*m zFoXmpQb6GpC(VcX@0gyn**tMP0H_~4;vWF8r08zK=${HXX&pdv!yxqc&hMd2aX+E5 zDUQCJwNxP{zzD611Aro=_z4M8J^+2vWnP;F8`a&@sN!wFn97SAh*pfcnrNtRv(xLw_?0VNb@@e_u6nxW|xeHbRmpN zb-EY3{Oy2P7?a-tKqsuQOa(MUtaqDb)}T1$96$y-0d6ps2|`oQY_mAsA4}@4<@$Xi=f)#8Yzww6_Z8uzhg?A>KjQGQhP>9QlU5FQ($<`%8Q$CnxB1s zF|dkudPXkyjC@ZeaHMnao=jHs5XRODTR7;uICXl6+KC6CE~0_hM^G0G zJVawJZkr=H{o-j$oQln|*IV zV%^Cn_q>{z9x=!0ejfsiMr%;!>AS;ToNrh?)&!PNDWLDEejM#D1Xx1$AcV6O|8K#w zW2f_4ZdSXR=H`T^OnVKu7*i_}6bb{|hILDS0=dy-Sna*k>Ys0QSO8W`)0RH(iy!6V`@;NfxN^xyD&TYYFsYdnF zH6M7|w2~jH0`_eu>3+7Xujg|8nx8xO>-fIeUC8wPdwvY2907?7@egkhrk4YcM>Jsp zK`Sc^;U(!Uye{XV-+RXT16D^Hrb;1Lhz(N)vYB3C6>H<%EepG^yDB#qxKnOlkrP;x z5cnDL#$#x5(ShK8ilfKA5lp~Gtg~%s!p5m>yv`K*%HoNA>;%k}-m*G9lY!o(ItzAx zWA^n1o$$Nyr|grm)5V`wCDBWIT5kjt*11fcS0%2myaZICf;bLmjQ(&AAFz58xLOT1 zzPIa@h{H;wVQnVre;wXg%&pleP_ERB@mWsT9I~KE?-3guA{%V#>zvEFAoj`+m(P}~ zDi-P57cFRI6|JPQS<;sHGasz*KK(Q)T}iQXTGsf66nw~J*yY^`u`3St(Q^psiJWR0 zA;hn*=B}@sK2y^tmdkQ1V={0qw&0(2V5+CyZW zw%J*kWkwQNnmiR6Xty)(*z=>8bDw&Dy&0;7=H24WpY#)DH_B>{9+Luy`S% zVoT(3rK$HbGe_Az4Rn*H{0|bkU48Wjh9&$KWLg^%mdRokwNqO&%{)1&rUh%Y++);N z35S6<@T|6&R=W2fuGB{-e>A>U^1cgVzXtslW2I1{c8y`)OYdP3%~h|1S8ET?)&y!O zXyg6+qG`b;`5iT1`58XQSbYEq9@+~NN@NbXsqZj&4Cm(Nm?f9!ioUL#Uw7Y?LmbNRMF#7N=$~YKB2lV$X4h@ z2s+otLGi8=z-DYk=H1L$!bj(k939q6^=2+kB*?#?UINETHNRQA!l13wcT@bfNS(G{ zu5v54IqlM*eXl~YU7-&50ij5!Ef5gv0UfWtYc1#7E=dcU7=}xItyk~2a0~S><8B5crt&~)~wa`eo6o}wP_nEaQk+;FLHv- z4bAIcKz;66bAFzF0KNt;NPrbzRX<*pj_nVUXq2i@?0W@kxV=p*!vm)`Tg!n z(+`a0(7|2~lJ%*lVGmUU+Id~~k0-=5>YrN}luQH7_@QAT`X~saabd;2pISL*mn~weI_yzf%m}k2p$CJ`{l%=cd|;OLe|b!*<>JcQN8-dQ&9j zAjj1IXtiC~?Id?s0qSf6|;+Z?L(9N~zD!=RTUalH7Vh{e~$$WoQQ`_QYa9>_+(vJb(b!_Nlo4;GY*c{K8?UsOA5KG29 z81#5EEHJjEOzt`C=FK0+VM>?G288z?oHpB=FV6Wl6^Yf=2PNcLg$F2KspsgGyJgO$ zoJy?Af2!#tSrM!ES5A-d{})+D?Y1OET%;3pPapxSBF8WIRchNQ7&m{swIjlx@H``# zC*fe%pjzP1NuF`99GW5v!omv_X@`09J!F1sRwKiicW9{+D- z?Hb4wJ);#%iJqyA<6^MoVf*>5p$Xaj7%Z(|z)(|={hgtp)6DJ1e3h>BH;0hkt^Y>W z#SNM|Z|tofA6YCq23Q*Ya^laru3}d-ZuoK}Y=10PS?2pzuSe4D2dXQz-2b9IvGK}G z?~}g#+pdTQzV`LXkceSqLL9?(m@-vAm3+XMUWs;#$}#)79uf(!Emn0OoTxHTPgVPr zBvaJycmL_XI57)0hd$pZ%cUhp>}pCZ;TcuRrjS2k&-ZBPo$ct&M6OS6{!H z_-f!r>o7R z+_M<40p+{dho@0>B>Ns|%ilm0n#o}{mXYiUQtm_37XhhCU2i?Ec?+SLi)Qf>QM_RL zK0WU7(A(>OH%LP1db~@sshq)H(C9w>t$TPumISc&*+}|D?zwd1kNk%sFj@hXxeR!= z+ah;dUOXR5h9lXVyMo)0qBWQ05#_PBqspE{NEJLg0k3uS8L9NNdsO4F_l#7H)tBaS zW63@OKl_ZeKO721a+(Ozmrm&9%7wJ)XK=0enHZ^bICLoaA#07b&2&jE`~pj)_Ch>wA3a*FzY7wRp%r3Do4cAZPt6pRetuSZ2a? zWQyAKKK!zHf7gYXC&{TZmR8SRuM%U z`a~%g#+g2=$e#I%eVGhCw-23uSfCvxu&hbfXrQ2ly^;z- zechpZ!2U_hVzUQ*vtu(r%B*3NRg+RG^}IdDhde1=62~m}dpAG&;oV2EW76!2Wi7(l zw1Phx<`g3ivLhhTa1t_2^nAD)4zC5}(o9fQ#xdpYkP*3?ZDYQq0q0jSOP%-ciHSe= zWYOQD@zRP*;~ghdSRHJ`d-HF&U)OL|`DQPj7?SB*sQ?Kk3i0Qbq=_O&Sh_!XUTi8c z=Ch;C)v6bl?t+st2|t`aJ1h@)Y@ylWh#5Bceg6jY#&mV*1VF)x(=j@Wkzw8#} zGThYZ3S)luG=r&YEcA|o?_2W6OHBKoAjQuG0Kd8bMjzCKLTWw^QHK@WKA*>fw$>0w zUJSWALm@*7zn(C#hA?I+LgsB{i?T>*+ue5ahM?wNp5Hu2d5;Et z1m5|!GQ6~8u^VCaJEG$YjWZTJpthGr?isOc!wkdh(OGYgC~BcZ1I{3Y$I#f-7v<{! z8G}>YMb9mnA+rfM(l*y9+XwP_4rygOWu?BQ$E-S{M?RYM(f(B`uA^;!{ztjb_7lTH zLD56v+5y`O81A=iW3WFM7Qf(+S6xHNA^l|nKMF3UX-h+&h zoA8Mpyj=69zsvHQNDPRxy-)Ko+~?j?wk>DQ2gnv{p0_LNedrE1-tF{nx0=<&ecVE{ zLV`jevpu^J**Q)MfJ%WI!hC*og4KZ~sVwYIGTR-ds& z4&CJ}-!e8H42xsdJWA=GzHN-NWUXAM-yeH6Sitm4HlZ9e94FvD zb9fFXSmoF^aUyzu&or)tD-XxNirx581y0;C)VcM#c;o2NFU>=~B&|u0XJxO#{@u^y z8H806k9#K)zeNw<-uOk`_%#f^bC9Bw@PUW=>u#3F#-j^=QNq~YH^cClT^ONzWe(QoYdI#pdlkWnjt;mtfd-**Nyvf(biliwa6sG*!KC^vB$!{pGiqW zVqMg~U?L4CkyeaIr*s}!>(bP5bEfy^X6Z1u!?VMO!9%c1-b8=fk_6X>(Tsgje~VKF z8^?CVnIM-=L`Rt7G0a_z*XS6z%i%Bs)n@FaJmdfeS%ln)cEzGgS4Uhrc*9?e2+8#B z+#lhdZsG{i!V)xveMbdE^>Djf=c*VEy3tErqb>#7H=m1ZeCUxo()0PtCDbw^Ek;^> zu6Ipc(jCsG`@50qd!fkV?b=ZKKy~cEiMbOlg!^hn;4M(tc;{@ zKz84ywWv-xB^0&Ljf#^=rqc*5JMx-SvN$pIwB&pzD8-$U7O{hiN2Eo}_81t9g+v0S zUXWd8r8MfuPHU3pLyy-e9NwtZo@)98IGGO)wLi(S<23U5g7vCSvD-~?wA0SIJLZR% zZ~->OQVPO%@ct;d#7WxVgp|nYl#j3Pc>yP&7dd?lN_@|ESq+RUMMhh`H+RsaiKD`&vZtzLRP=sJ-Y1(@8JKxBl__=!?>8`+Xg*IOkn8H6%ea^|eAnfC zU0>Tb)pTU$RmL~(ELxlXT;cS2CnpMv{9&_t8_kh*DCb-lX?iwe$HUq14GLpOaV=G#xxhLxNjZRh-H z(bMdV$8}bFcGfgZrMz+MAEm&-HYwrh$?+&yco|ogYh%o6#^a!j#%nV)-4`F5a6Izv zQfRo`k}iFk&Gm1=y7FKqpI}Z~Z!?cCx}v~jm|i1He%RGG)4jh`xJe;#HuEB@#N<^SJflXXk zi|c_G&%Yxmi!#@Qq@``UWM0FSuk#m#*Ufoe&dKMLe&^7!71p`VcJ;#$r=)!YRs5jv z`+R{>AiwfIj_YiaLv3}pld%LkPJuDbI+5XC&q4#qeyVw4E`wyQr@ppqU2Hpd*2Tu& zwm!6SDZgw+2cIo+Y$2h)P)rT1jeJd)e;47D9CDJ`w35m&$R3PJ^KZx$yO1U~OO7I@ z+LS7RL>K*G3=A4zCwu#w6jlaOdQ%)Ia5p6q3GS_-my8F%YdU;r9A4Z?b9{+K#Hao> zSqgV@$lJkzk~^X>NT1+p`Y!;3<`htqgE9@+mYA9eWAHu!U)eHx@kbQylm{}y6&}1k zzh2)#rz=(GtIlSLUjP^%EDP@dEs*0$@KhHRy^jzQUw_$qvLzh3LbZaYx=+$7VzK?G zG+soiUm`SEw~3FCEgT1Oq0rkZGYgZ_#B1(ejY~x#(!?pa2pj2X&pfgXAhHjcRiCo8 zL$3`7dz7yh_DdCVm6PLAwJE6z7_2#MT1iOmXQ8}kEwC|$X)=hF{wucNWj+d-`q`wQ zq;D=!*)?Q})*cQTLZu-ZSR+pWK9rpB9c;KsfdWlh1wSZMw{1L~u9?NY@*ga62m5M) z`6--E74;aV|bd2Cn&4|8;@zbz6f>^lCzHk zORSnxjxJt?;X41B7gnT4l(a;_Q+cb`T;Qn@#4H75+Erqz)#SBbCXisERDalIpK2$# zWXsoj_T!!AkT9SvoX&N{{UK~dI1V?LVysMHEwy*`L5^qaI2jA2j(u*9L^O$4r+As9 zZNlxn`*QhgT7iSt>}?3&&q0DFtAF_Dd?u0Z82e**KB{3UlF0PuBR!QL42QLd! zkO~`KZE=7aOWi*|enH;B)jXaN4*-VIc(}ts(wnk97fen%Re8QXo$T334Z$o+_vE}|U**!z^TJU0c9LUlQht~2jHZgCXS)?vFz+;SRXgJC}oR_ zLKv<^Yz3S&$5*FB{9|Hmq_<5^j;LN2j|Xi8JT?+avU)W|bY7!aD z;HDgak41n#W#S~-JHTq=UOPbHbG;X`YutCyJuYqXGwn@OS}aC7$|_BjCOdq^zHjeE zhcXLaA8r3C>@vpfijlcNMlzLbBW1)kul2RyuT9~h?t+Cy(^)gq>uVf3_MA3e$S13u zW*4qX)^n!Y*rZRAb*?ns8z^iyL>QU|8uhd5h9lD9g%*6AW+R!YC!8(1>3ES>z32Pn z6#@57eA81uJDHZ)d6|AhaXyeNvilv7a=Af)p7HVT(r(ThXPQ?M2ClTJT)8V%8YS7d zCtU=-G~|Pl+Skb9e7dh@Zj4m@KE|o zR&w9lbZ^wG-_2|;>Owb}XMD+^yy+U@0yy026MM(B+$3)&lj<}xTH4C%}bK*C28@5A|sQ7sxA87mDEr7OpMlMy3kM7 z-IBuzceQKQBT5=wJlC|->B5M)v2o!1M8{1_z)>6h0i16Ar-86^ni7TH?p2uAH#%jL zgIHb2%>y^yL#FjM8L4<4;rO(xle9iNWNjxppE!ci30T4!9Jq@IdferV2mf$N#;B}< z(fIv6a_lz)i?H5=fBRI$8G;?-2W>XSJvTa6-6vKy^vBoVSRufvC6T>-TjGQt{_tcU z8&@fglmIwja0_5T$mFF-JMT){mw0<-FNzK zl7=GUy&M5oKaOR<0r`fG$$!8XpPDPpG+Y=6mag4SBD!<5Zz3kW9R%s%o(lFQQlSC( z2%0B%tnyCk*cp8yt+b8>P~e5K^lKiF`qydMaJHK!t>OpAR!(%$p$xWd&Mvy3G?epr zeLf16rX2^S&R$FQ9>Xixu(_gAkG?nG83%ehvEO#=mXt_!H_2vH*@&OLb`C>(TAkwK z2~rgToj#^@Ur4+23JLnLt`%Z?V_%W)qe5-pW^KURG}GKC4Mt;98{)7OZLuHBir`yc zk9>A;1zgTuCTT@8wA!f?!KSq%>9}4SX!jVXsf0o7-L0^a7S`1qtm=pCeO!|6D&)~G z-+qQr40drWb;$a0u3Mg09KBII81ofidjRt3%M~u6+@iK(3@9NvfZzb2$vCs{75ZBh z;G;OOk{aWgpHby-L*o0v7u@L*q@1X>UkGBF$fWl>-8`@5HFru1pHM2Q`mGX8T6P-N z$`eFYUd!?hz&rCFC7FPK;hVqzWa%M-#y`^gG-UVaf#8j?H!=2V+&MDuHyjyYnYtXA zi&>X{r^$ILT!ii<2eN zq$BoUe?0L&5Yof(v0o0}IS?kNvrAlQ2{;rP&*oK)*xNZ2og|1D-<1jcF7~`o%CRH( zcladKW&61r@9W()HDl_nMcVTn_fD5}p{}L&bcnY7n5j(sF%p{H{mbyz(cpNOYo; z8orC%T2Ue2P;=F=tJmO(T^WvujPR8H)jAJ#Fa3LDlQJ(Q-*-NwZBPb{zl}(YsOwpi za8rAxf6MdZ_Kd1d@n{-{{LNF;_m9tu6+^$BsvYHO1)YAOjWo{VS0?-QZfxF$w(A!q zyi*W(82jZz+9`)C?C&veT5OBJ72KU;VYQ+z*3jVzcH~FhcQH$I6K|ku7LK@tW3{-I zC}cov6&CR97k@mX2*N7{=r>UvbFzqZyFHkgCKS4AdZZgAJ8&YBt?(Qrnxp(C&L^rl zvG-!4$em^WJe?*-ftZu%^oqDQjeV}s2Crk?@=v^e`4s#r^`9-gs=ivAf5m9kE1nAA zjsJ)j`MmQ!za@G?yky-L%$CLSPemd(`c1qa>=6PCuA5kFf zcN;m%C_RKEv8V!X*er~A!ftB-7kxR8QZzp3Act1w^9hoJxnEJ`X43Om`4;HDcl#Z#@Mhkw7?Wt3EwAp=CgUKAfW%^kp;-5A8 zt8938XN2AtH&==heRk*8P9Hyiw>CXLp}7{u@m=l7@2@Z6`sIq# zNJ7%DY~H69uPj)$jx=AXtTpIysqR)UnyORI8$2qvWpDDTz9moOD5z1~bEVpHB6ATw z<%;Bxx8)?kZ@c6}BQ*`B%Ax4GvPA7ayUoMee;F2M>3v%9_2X(M#4v~~)zy%85jHeC z%B;;W!CVtk%j&kHFG2Lm*6#bpuOH^=#dnx(b)?HVL&R&R#y%BC1TYTm057H2biAI% zaaZhQC95m2`cVKEY*FKi#KTm7lsDso8d$zGPs)4}{1}4Z6>0;>RBg`95Xz1|OMpVQ)%i->O&gNp!C_u30erCp;bd6N zRen6zo*OeHDi8=P5Do?i2JT>k7f_%C3J~nm z{61F8wAES49(a*L4A5L;m}vC$A%5@(!_$N?=Go}Y;hP5N+GXjf6@@{JF*1mz0A|$) z7=2S?a?M7=I;@SYBcuTvWR9Rnc(pxUU_lF#gvO(E%W~I;Hk0P}^iCp>5PPL=Zs(Q} z_CLB$1AL=z#+Dj$1|e;HX1y7^gp8mEws>zSwT8PVz(H?kilFw}s4C{EwEK_D8G)!# zxPBN=HQ*59w^Pfpu_Am{S(C||tuH|_0VvqD1Co<{*vt`u61neRA!I)AVfJtu6P{Cl z=aTEFHaN974C7=xPV2SixU}~LUY8>xyt`q<@`bIdOZH_J3Pu0TxJ_>ID<8(K1}ty+ zjjGF;? zjm_E1sgw4t$4}+&{K$H?$XUzx7OsCMbq=R`>ceNEyo0jy610!1VV+6P=4$tXGKqvS zTv;2x*y2PPg4DoKV&@Py{j3Q1LuKlFUI;YHrtI(p&oh|cl3d@x;vOXojs1d8Nqf&? zVF%;eh$H!)-cL>P9KA^Y@rD=`l^S9Jzb4e2i|(=Iu+QGS(6~8vN5F!)9a78pvOo$l zE~MIm?ic=Pn9ldJ`IB;I|I0hCq4Cd1)ofF%nrG;l0dlg6NXo>N=IE;g_O4dZQiKi@ zQ}J+%=p}=>AXVqLY;T~V4Tm3%P1bp5(g{GM^G~8rs#)PZUb2{^Den^owa7?1FPKxI z2s6a1`@WCt7w6u1n~xt}-#$pG(lP$5Zgp!JJDDOb9MWuFP1kdeGo|jPSEk93*TNuS zOk5co(W*om=Brpu+LO3*CW)6Y&8ctW?tF% zi*4J{YK+?)e7BO@+w;X25X~_}0m)x%%iRj~iqD)Uj&il>(;uezn0?@U=g^UMFJDP; zXj6cC(l013-Z&L(ImOHIOy*^+-j@Fr*b7 z3HzOf-)yqAa%@QKWOn6dCvj+J`>TtX(+U97W7a^pt;6C0>o8yA>j5I>%3m}PlhIShfm5mm+_cYs9!dYr&|N0k{Ukj zZ-Bixk!~arH@T6!u{l(`ZLT)eY7yNoQNiEyUz$Kd`arWLxt;7q;+njunk5m@Z zJ~!ll`dB{K#8~|{A=d{(8rvp3lfCQ;i|-J8E^#Y~Rqv#N<4+xrs_m@M1wbyid6W%0 zG=;1KEY{)DY+?DkI7`ZG)YR3_%GCgEApu)s79~B{V_R0GWD6{g7k?F6j^oAHMtjo9 zx7>ZVir3cE&tVyH&Y@LQ(&Hf#fzf)OhxDUoVX;`8D1;L?1P~1Y1h-U18=^TAUZWDg zCSCx#k@a9Cbr#-`ER_SeR0u$M0_L#*RpdAlgWHQvRtp0xhvU@5@;SW$@log-Kj~c6 zQbftLDlPBfvwEzFSKurF`J-fu3Vmo4cJrgI^%h3;2pu}h1%!$Sb9*-rnQHd)EY6-& zBK260QWO+ODmHA8Y?8-&z@c*fM=VY|3d{5~MKl|rIy83HHbE^UU39XRKe4xx9f61G ziz2LLm6ByC0PO=hda3mD7Oi$L$(4pdeh1+55#tc8CmL+cpQ$G}UR!8u>vCG56oj%w`1u68Ac|+6QVv@T$3@o&mkbpL%d%Ri%8^ z;{ph!G^yb^Dq9Iq7}7%$b67X%FCH!`0s)r}z}k~|i447RejLY!sDod<#>x4BuBcw0C4Dq$k<%@g)|mw$+efS1Naqnli&h(@ zc?zIQv9=|m)zV9;iL6drcq&V(lo*d)KiV)C>wJvmEfl}_Y!pStGAUC>H<0?8$5=y2 zZk~HvYK?lLnjd580CZ1Bj~I(D&I${ea>#Ehk>4YN<*XYI2`TG`fve> zh-W6~NwA=&K5|Itk|#-#U?jl@qIbCfiK5%G9M8U^02uzquC_NQf!B=NDK^w@Z%N zH9Ej)ACR&)8mi7Dt6%f4^Y7l}Z7i*9%#+)`D-u`}v0LDhl2EvN*JX^1lB#*NT2t1T zz!zBbt)WarvRp*+!R7Rc6GVgG=X-v;rQWX}RR-02=QM~kVS=0T#}S5mjoQGbC*PW? z#y^*zeZD^sR6iiq#(iVL?sGZ4q+_?L2R=}s%@?z5)0LN2Hut)McFCYewOYP|-=#Jl# z8RI3Bi}t4UWTt|GCnAEMSGJIE29qBIzlhj--XufP4(?BuA!i1UMi?jsh(@f9>NL2F z2*|!pW&wv`0H-8?rfinX;{_|(#U;naQ<9#H?2_5nB?sBXn6C@tQwvh~rMt3PIggje zr{*7gUA`r|5)rbf{`GC;g@vZC02FaOhWz@wZiF39NKBRjdNQgMqNgcae(mv^5&pfp z?1u>adpS8UUUy9Z|GrXIYxS#v%o9T;xlK9h&2{yg=LJgUzq0;(8 zTmHzX^~g&8r$g&ccll$#*5jMr z^p0(G9!QXX8z>Zce2Wg8gk-4A15-&1X>E*ENTx?^=WRvi-Zti8BxIruGJ|AUJ{Uc> zjIOjn_uJ45bdeOyrGqxue3+WdK1`6Rz%J3wF0XLjo9B?vR?uwc{8FG8c7u}&kSW~Y z3{~L2*Vg-LlryXy-khgGXhS;zdbt6D_(OPa`^8}ezKM3e83q33cK-AC+wFFNeFfIr zZ9E(@eh2MB%chKJ$>`HVA&JX0`e6VG3E)LCt#pT2m07>|HY=P=wCuRlY9_|B#}#}T zk=B98yDVAUA=$b5uChbQe_x>PyVUUIpReddh?ixTJ7nKomfP--+rKRTt3#f8842!0 zvMMU@bSiu)K!hbn#3h5JI}P#4$}1!V>mP2rdQUboB&ypHHj1j7^Qyt4k<}zaJAKvS z$gk?1YL6m6htsKr0u`GTHQ!R%M3M|7ZGgN5imKCk#wU83zd9@9!Y)VvCBgtKA_iI> zB%SI`1N`V^Ujto114TZ(u=SYEH4@6COYRy#A{&WH(6`?il}F)(Rq>ap$vo8L3!!>k zq6Ws1B%P1R=mdSq>@J<j{%by{G^I&SW&| z*qcZ1`tpdlM2}xDl@+#wfu7ZnE;_eNQ(MmzRKd#J|v z_r`>(#>V!>CaE5c(_Fx)#y>KHh(*UgQmwj%hBo)!9#&0w;o>l%nz-DX_^#k=qxX)6 zvBZ9F5>*ug?!&O6usnTOK~%CtU-J0@pKr?Opzy|hcxzOOV_%8~D%HO)HS~PO-Itbx zN>A%c&qHMt_hnR}G9UG2wxY6n`?9K7wN6P|lls5S4zm6RYLH1fJ8^pCxMP(O9o>;@ zjc)Auh?c}x|XwsJJ@wfyy>I{kG(Xq3Vxf|Db)b`OU25t@?$4jl>4WHWjeb>N61=w?jO>jZeCSWT ztylhgv=0M0pkb|6VI>p&zYO~G(6Vy=y7>jeLPHB%!9dep&v*?W`1>%t>nL>)x-vNU zcyJYSpF1Gj3_gf%_>E3iGql6z>thMHQ#3>WV^Lt=FVn#rf6?SydI1TfLRaw#;;8iL zsKhVy!jS%&F67|!)z#DAWFqq^;Nm0v-HQeVRhn~G2Ml~^C#V4KfRU-I=N1nvmoDwN zHI}DNuVH(tg{t3s;}6VjeIqy##|l#nWTE`uM?y5?>KTe`tR8< zTvBvwd~u%6Z|m4EwMl;*fBi5{`m3S(cVakdM(3Y?@4t7$r#es1j8%0pQ{VGE(Ks;M zCA&U?mwpo3yj+{O#l3j8eZ ztA>AC=r8cMuF}DR?lD{qu&p)Dzhpm97?U~n%V`0ZBFD%{JH_~x#&do<65gLzZLyud64^^j{+eK36bpn{bs!;4maAIYK*{( zh$~X>$OP9i-cJ1c>npcooTw3`RrSa@dC1 z?a-@dHq`r&$wcjM%anqMurWdSEy86!@qM=z=CLQUWJo=nO%|4Eqn?17U_1{9#(5D2 zffG%R?#{)Egk2UyJ^!L!{>> zA!_h1l9c*8m?d{x=3hOCQoH`Z^=xj_G9?ZTK)SGZgmWnFTiDGRCS9iIkh!C|Gt*B% zO>!nr!a>3k7i7N@Q#|{@+`2k|hKHy;Y4FPT%5`pr<3}X#71`5m zUr)W+_WnvK7RoDK@bsQ3XSwu0Q?NV!=9|F!!V#}cI|Drfp6uGc68T96Y-2(emA}(I zCzm%CSBJOl_6nPMj{L5&E}!#aO1X96@9yB?c#zLs#t!%c!8N0uG}{o$U^V>aiE#P} zgI>AN*~jYvZ>>GT%17YIG;~`-YWwAqy|-ifh3Wa;cTRO*8vR`Rx$KqacDx$c zx_mW`5ZNnK5BER2@j-W*TpDNG|9+My z-TAveQap7FnQWnW`eRNfFyYI5=(~UU>9;)2e#>93{e7}K<3UZ`kY=F%qlN3zLJ1gp zB?>K%_hq2mfs-?Z6Cli>?SvFQSJ%4>by2jKZzAJ)KT^PGxE@+H&V#W&%Um-d10=^NLl5p0B~-C_x)sp%6NWm#^{93 zCnsYqv)vr63n}_%D{3m$c&<{|b0Lx~LFb8xNHakMC@n{4n%SnuZsBZriOzXS_R2Kk zF5H(_IV0aj?o)v+gyFx~5XS#tLuk%F%K)DL!G_T5(uiiBV?#Kku1&VpkkVkHX5}XB z55}_Kia~3W?X?qmLjMOgM5vgEI$$O0K#~884XM(_G4Y#qHO!rxE{d*=z89pcx3QPY zF#9hyq%&y!d3W<11LEO#JB~+t!>G^=^6!bB$8UQ>*C#8!fNr`D#Qj+6e&KkI4Y{+r z^z}n`+qvoDzt|83lEQV-V*3JEs#AsA%9F&a+g10wZ~xBxUu=lsMELaoVnd3a`kIy{ zg;G8Vh#q%XbvFJN8*;LW@0%)@l|=}KiCk&d-USS z_Plc#%Xe$IYaMNx>l|S@ODg!n=4!xt2DivHVmH0J@4JzPGAvka^aURE=|83mxgxi~ zbKDmhQ~#L3F~9&C0QJy^!_!2&kn<*jS`LB#!GdFB-^VOU16-DU z^(tUL@>EHuwOjvVy2$H3ak%5b6mI}Gf**R7;kl*Wlrb!hb5~}oeBP;rMVOXdOdQxE z5kiFmcOIrL_1FkD=}LWWs4IF?R##h(cCsF*pA&x67D4^osLxy$^yP8iC$j|(om@YG z=CJi}?-ueywdN<2mzwuFfQ(yu3;2DENOItM+|a2(ySi4)Vufn1#&{>$F$ON@Q;_M?Uo;} zG=J^=n9&8x9?cr?gdEM8NLWVk|GTUOnzzc@J6fWS|&vAFSTZ|WxlK<~?;o-!;U(3mC7iX(atuKCWzRte*^Sx!_ z;_vnHBp#jR^j^f-fg35-A| zay)FboKbTS4~Zfth=5mKshng>q>vM3EGt;-2fKON$w`O|(U|MUY}^hwjF!Iz#QGzO zyP+>xeLbCla-rNS$}yR&sawgBf0oTDAsV5QQOWh%tWVDAFwLQfmkV^l$o%1MiU!!7 zV}Pl5CiXDnftx#Y(Xd|!KVuDc_uHFeG;SFAp_(-79cuKW>f9V!$$iWN#DeS zoWkfhzZDno-&D@6C(y-R(1FsUmbx8_1eINO}fv3K^;!oFWk`>IAG0UGM6?}b+b$V^Hqv&rG z1Q|%dr_hWbs2G?wUZ6G%657X+7-2$SaMFKY^AeYv3bSk zX~oNLCGOUs3=KJ~d${%l=uV}>^QE)~IEW=;kN1ePuE8KYKL<~or6sqj6Ndrqqi5g=`uq9PT0QKB6?EYx6|6EJEfiJ>?E`NM&xA6F**p-Sx(EkiydXN+hrO|^P>uYAZ2W$a^K^K*;FY+>e{Th|&~e`$U55!c{sWz^p}{{Ehmqxv1LNl#1_jDQT%EQDdGB6 zZKyyM7ni1?CruuLtAigjsSyp%my&9}H1B+p!{|}xYmg5&(_`qTnO(QBlHYBq-PG6Bh64y2l%IN9wbDQbe)tp)e5@vZl@A5P8$EM?F{r-l}c&xi1Bh0>$<#I5BXHtls`Dp}XY&&S>yAqmgP|KnV@9;)(^-JC_GHS> zA`DNaPomtPzuB&xzyIT@X;OkJtk5RodA-Sf@jd8dgAzPl9ODU}kp;S${%rC=Ljsud1W85LjlOU3|U<;E>9NTzt91-517t59IZwAO4macpP=54EJous6 z(|`0{zm7$%ZZopBo&NW_;{LPsX<**#^TV9%&UI_lXnRv7cfLs9Xm)vKF=dS?c==CQ1rXTYfX=FrEli5@f!bq1r=%aaJsJ#k4S9)QO>Ltr{q3v6ngGQM~yZ7 zBV1b*t`

H_HXjfJRuq8f8(xw(izmgh}~gLAdI`8B2(TeF*H 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℞*DPH|248pm?0l4laXCZOAsA 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 Iq5|>%0$rR)oB#j- literal 0 HcmV?d00001 diff --git a/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-2.gif b/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-2.gif new file mode 100644 index 0000000000000000000000000000000000000000..b30f0d078a0ba063861de70210da9e086929b740 GIT binary patch literal 1195757 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⁡ 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

l8+ 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

>#IL4BydB(=}=?)Dwgh}0qGcf+cfa!qW$$} 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

  • R9}69HWS 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

    dQetGy>|GnkeV82KcR0wCh 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

    *A(Q7S6#V$U=J_xO|nIgrk46#Je#rqK`|nH2>` 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 literal 0 HcmV?d00001 diff --git a/images/smart-contracts/dev-environments/remix/get-started/remix-1.webp b/images/smart-contracts/dev-environments/remix/get-started/remix-1.webp index a0b9b327a9e692c12d89ed0817f05bf00a7f3d1c..06dc648f076137d0bfdf9fd8a8efab5d3e35ce57 100644 GIT binary patch literal 432120 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�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�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

  • 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 diff --git a/images/smart-contracts/dev-environments/remix/get-started/remix-12.webp b/images/smart-contracts/dev-environments/remix/get-started/remix-12.webp deleted file mode 100644 index 9d8b1db3960e8c1b85b16d4edea0d19fa2b610e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91678 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%0APkk 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

    X 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≫xe= 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 O9JqhmvB5ZekN^Npv@1ja diff --git a/images/smart-contracts/dev-environments/remix/get-started/remix-2.gif b/images/smart-contracts/dev-environments/remix/get-started/remix-2.gif new file mode 100644 index 0000000000000000000000000000000000000000..b0c3feeee6fa355ed3d02226bd71d53acbfa4afe GIT binary patch literal 1533379 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 z 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

      ZIg-cWKk|Y97z8&m@08h7v(e_f$zkT2* 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�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 +to`J! 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

    ?JaR%L9cD0W>@)_g5sn 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
    {D{3`!#M~81ynH-Dg>;SIsUG^R2gh0~)V7 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�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%0DN}FnziG5m|N~27tsG*xdro6^BgNC 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
    ~>rMOBEk~?YSs~Xi9V%sa>o^ zNcDE1fo+{&twkaf@xn~sf``PMEo=bNQ1!$8rU-;lPOwuKi39KV!mLfvA!JcT?^+xY z3?t{U2cfR#dCPW^$c?c2#6(0Ix*QG6bfK)8X9Z^E%Yq1iCm^bV1>M@m2jYHfT5pZ= zAra_ogOCy;?#N^C4Tg}{7OUq@$0dwO8KG9Zk8fwhEhW=0{1|OX`PQmsP;zTD52)fA2$F4^WnY%CgC>@r!2CL5`o3* zysOBxIid;?4CT#`VRA(vOFaZ|9Z!`0@^x1Vz)sHhJSHaH%#TFZ=nvCj12gL*=P>Rk|}Hk&Xhp zbj)ZdbmXuF9!9!1Z4PKrxDCkkcv~p16ic_x?Dik>=b=mDTCbzq!eP4}V4nl67aIj- zD~y}a5naUB1F}E6gqq9R1PG-31It->8j30BQtUs6M=v{BydyJuhilTIgF8l?-K7aj zYoZVFxM+g-p!p}TZxYtCO~9t3B>R@Oa#K?=;%?u>JX1gbEBtI8cZ0QD0unBxjEQFf zR-jTScAa&oCQ4;1iOZT_Tgv<0BRYnw+&Is$@S68o|p}*fXId5nG{c+ zB}%4_#z&wiw%AH6ehZ=9;Z#LBr>hm;0prrOlG7V&o7n8QdF9&}Z+UxVW2}MZ$2Bqk zpQtjP=qgAeY=ynGDncz4(Fbrph11KDDPb>@mWP8*cA{TLsyc@q--)vIFdi)15Lw3` zYmw+m?-L#k7Wtxx5a6mQvn^9mq!VAZ)koxRV5}&mjFT#xlE%!BD2E1<^_*QM!8Ku1 zU&OCAXeI_)*(GZyxQ?s_4y1hl8>XHqEM{bnA>QfeF|Mosmo{wG(lSDjC#{>(bQ+YP zq)!Jv6DM$euzG`2*t)R$s(p%i2AWK$8CkxWYpLZT)fRJ6hd>i6D~2!7^|8ERfyGeu zt}xVI?A`&z*;l=_ByrpY(Bfqpb&@1D$$Qf@+snuN2W2Txo9^C5L^&R#tYa{M#Xzvi z((?PR(KEqoPdI@}y&!6V`pUSGFADCy(ZWEI%D&x1w64_~j1(1pMFA(lj~L_hLb8+1#)<$K zA?){gXfoNhm+s6fsA3=Zr`-pXuBz0mxgU})^iPnITo5w1d5=Ja)d-%UyyGROdSI(4Z!G_<9cf`gcz+ro)l5GPEuYdRfRG_bTGRKQJ>_FKlhZr=wen z?(~S8{W~uP7KPYi#=c{OlC4DiUy-r|?Pe5`L>jmBaZz!2a$v4bsw_Iq1ND$d1Cg_`#xv zP;-U?XlmTM(sMh9iodcIdz=MeC{Q!&*SFBRvnv931_1m2ClQUhkww)J=+<~cR_cOT z=#oi@_0|qDUR#JhVX#oj5zf{mwGliVe-BOr-@;?c&m|`dvFh4H3ZU|c_ENC0uu^Xr zhF7jai~+9mcCdzZ^oYtGpSCYPKwOe&x%+4j@t6*HmWY)InGq5}qzR`x~wj*$KMqj7B-%E_+neJzwU<59C?dV7kk_59O7%KGhSLVKk0q_1nY z*B|RJ;NJ1n=(4t=5X(8mV^K7^oL79d$VMS*mbo4<{}${{yvA@r*>wwDJ)v0=Hk!?0 z{KJju9PziEwQs7X1mB4=xnhr*wdj)y#a9dqRiB%*JBbc5?EUhae07pH_vj+NC~uWo z`0?#lPWr#IHH6`Pu&5WvFihgEEC9wKbUt*t7ZU_6 zla>PveSwX?98!eUE~g5W3-J8h!^y?YwOQeufN@%{KZ|6;#SOTpH5VgE^J$MiKnRlx zy^aDgYj2Zn!1Dxy{fnmXuWz6i`_c-dup(7%LV2Hs+Iz75{4ZUEKU|eq+9ouOH2>fB zlDZyJo~%+qp!;@5tDzyV*QQVIIg%_XZRJN8(xys#zF?!l>Y%Sgs=c@X(z`Bb^BTcNu8+Zl6hne6Dj591zo8A@BvhYPd<#vHd zx3|waPVs3G9h6=iV-XdsbC*chm^5Bv7otDE&4f@$t!VGxC*7CBdI|9-x&#_~f1RXk zT2I*p5YBe54*618K*KKRoE(E19~Ce`Q2T+cw9%6cdGjQZHt8_#uj9yV;ZGA$7?TV^ zwrF9AD5JSWeY7(LHN_axQ-cvpPxmt+%>Vv#z&e`WrMYnZfjz!f-1=<)6>#!Jt`gCU zI!?#SXBF<&;!%MrXyTh~E4zszlgdillYJ zpi3VipYG&$LbmQZ`JLH+lWFYTnCwAqTOmf zZ(U);3zxa}ewFP9Kq}a@gxac#bvN8HIF)V4+1B5J1%{Xb+BXmJ2v`JHnIj}45i|E& z^*rrRGn%p&=>J3Fpb00p@?}izDJc=Y?QDRY8;L&2$Y zbQz$a^18OA?l%7|HlHjy{qW^gNjJgJ+ph*AdW_+ra?(%xK+(vrty?L~@D#k$ied=b zlhJN0>C(XzX*UZ6Q2(35d{7?F4)r*v(03+v&Cl|P$;{u8%>HOom#0YsBeLRwp{AYY zZKf?|+Rl}E(`%z9s8VyPU9DC*P9dB`V;%NSM;V@fBw4Jdlazxf&=jICm&;d_r_H%H z)c(<};f*OwLk2LXZmBs!N>p^AX%zpy%-;{-{>xK;`;SR@IiNWg?nq>x6x0{aJ+NB> zw}9*S1Xm?T2di)_;YI5*8-y1(40b{1G1gDmazpULE}YZ*`*_^>QM zZ84nSnSqN2RJe8QyZ65JcD#REo2u1j5k&;pi&7l{kJ2-x^`Y(OSdsAn%N5imi%57Y zyaMoT44Qdu7`wPKPR$b&mOFC&fgZ{cAh%|F0XYPGVI>N76As$hM-90eacoAR)O1Z%y22Kc*Gls|6w{%jW(5xAX< z&FOE8H&Z=DnoRspC33JRJyUVyT34G&3O)}(Uzxh6eV)Hi^trZe3MW^L$*jGGeo(3p zTS4*Dk9t?RUp)8is+v`;sFlUpTY^KV{IJ-#1Ym$*{v5sZROM%9^sGUiVaxT0 zwqEZ3Kc-6hQ%<3}i^h-6mfEds*%533j~Jfcyf82CsXluaTP?pnS=V6dGDue!*9ZOTotK@YnoS$0oAsbuCCJqXw%=6;tXt!F?1d&+!mOIxx0jF z1~OLIooo9+F(vf**vqIUT-#f@#_tPEg9@*0Uk+(2PZLF0Ymj4a$Ioa!%iL`t2dq3w zARzA8`a)J8Nq%9UVYcd?9s1+#e9Tj85Ocy@tE_6=NwDpPS=stFhZQ6;s~`XK{ADjT z7O)WY!&h;jp#vZ9}DWmo=DL{ag#cM(F*<9lv${<^iH!^-h*vf+uKX)x@x3BT3Bnnq>M;5;p7 z=vES_G?;(r@=)OB4lhvB`LMXfOr)0yq5@gyXLdAx|3o$upGCqnJUQ`I*AUeJ^=>a#Eq# zPG&2ysW}sExB~o&dLibr`G1}eTmH$uW`{sAZ3p@w?C)4|p=ih@$;7UzZGVcVxkh@+?SeNDBd-TaAb zHT44fW#+r=#iVQ`+P( zUT!OBjF8F=hjoYH-xJ&>#m81)y2j-(Lma5TKCu-t^U5hIpsS=0ysu3+|6Vs$ zm-Vr(P7pZ#s|%^Ag@R$XiND+Gm~|w#ev=;UWFTi&qBX_AiNF%5kh7pipO5wB#h!1G zwE{=iGi^nM@6I~@R~%xoD&ldFwXFn6@@fVfcM-W#6n2H%YkB~CjKaZW{)annIDhJv0wGz?>^7MuPRYxu@N22VZ zW!}LX|Hj9(=np)e#LavTPC?^D;)ew2W}5vVN32(Qk7EWc^+t5yoG|K$=d!Q4ja1b< zQB|(@gM~v>rbZq=OdrRd*M&KnmbYgk95c^1GcAW(WA(WY{c7Qjh!j8*z~13#B$sDg zkI3`kl#lbX8ILW|XYe*Hw_uPHMJ;jg^IcZIe~JcEYa~rj1c-eaXryUI z^0Z$vI3Q2gk%y+6c0tk7g4oLLO|TTOXLrn!N8Fcp)bdQRxvKO{4EvV9i$}BcijXHQ zCcRQ7C3+j0Cheig$ZCJ!!YzWjPP8Bk>GC?nBD}rhoKlH0zDq+PKGXDAg%&n12mG{z zd)>q6L=3VcszI{yI+E$vDc_D=Y)^uIaAS0h!&QL?N_b1r3o>sRxcW%?26E+7+eMH> z7u7VKMqvF^=yT`xBrlu5W5p;kGIEL5sO5|H@hDT3LPZS??SMgm$B)q=zS?mh@beLq z2&{lkedafKNUmdAUodvSU35P)UAQ(r94I;DDtr?3ERmL*iuzBitSdf<52qF6>^c&w zJiO@T@YpW~WWZ5ZrBtE{1x|n^$XbsK^#U_<7}Y(6u3U6|93)lrM0beiK34Nb`q2cc zEV^mX>dH;mZ&RZ>S_$A?NH?jq;*i7#bGWP_71KZd)skG#F7qx^*We&D=jaDn5PPfu z``aouz5w+cga3I(;1t0ko=I*me0H5r0v;dUeM7ib;^TB?L7cC$9rs`Bu{^kxTyH;^E?w`tJW$7BZuJ3J#D@xaNoXU zUb8JqRy>sc(+0?3oi)T5F~u@d9B9tQ2x>tEm3m z&C{7T%ea6CyXq|n2#=JxCfv*E=v7J*Y4v{beGYiz)6{!ZjB?{}enG8luT7i@h@}T@Ty~(1u2Qbd*bgIQfWH!`! zQziVSc@f{>?RWHh)%0rFps#EqWe&JD?dh_l$1>Id(q#|ozuzK9hW)yWUQ|EgY80a3 zB?TMk6;2YP3{t`ek6?RE>peB1u~uQuh?3?aqmdN2wK1`KV%?v-VE>k6lu%UJ`>?QT zN&l0EvmJuqadZj(5`O2xW_E0hS;8$j`uPxrKyIyN=;XjVY0FOAeOT+xYpqHSKda{K zZ$(r+0t5o>id;1F_0?f+pqgQVH+LC-sQTkwfj|v?=i(IE&(gu<{6+G42`*=fDzO>Nz>{u}v-05#(Zk77>8{Nlu?eY>NNTIhBzZ8iugVIe;D^u7v+jsceuo zyUZ__+qDT8E68DKYNaFz>&eQ0y`?dXPOXcV0000000003qJRO1T)2(1Z1BV)@Nk?D z_^Pn3UrZnKz4mgAu&n6OLK)_VoXu6vA&!O|DX2MmKb_i;h|<7fS4Y&Nje@w1IC ztMWO-SV6B~UHDhHZq};o0?WAY3)P?oCnL9u%ya3%JM8!n@>3$`hZdC`>r{~U7~%w` zBM428Cpfh8rW&wIraa{qhItE(5O;&NCa7SWd}}x~|1%a@dln?h>1xnvs>#_weHGCY z<(w9+F9CcSK+3N%sWldWW%{tB`4y(0VnD#~i>wWap=7mw48v-)W(4~10=** z%Qn#FtvkPp$H5;B4ha)Yeu6XQcK3viz$i35RJ;l-uoL0bd=6F4oU)#6AvF|-%fywu zB95WC)6|s|6$>(4@bgt8gz28w!=v3IXBv*LV*&BecT4X&U(-3ZqVYF#fD3&W!NZ&X z78x)WRC9SkQWGr_;8^;%b&_-8Bwdyj9{jp9i7Q&tOz@ukq4T}RnUteQ$2l7I`RtyH zKL8s9hKhk6HTHWX)0AGHe_<(L46b5fd5l5AlfC|qcaj3x|4Ax`Xi?N+P|-PM%a_Rg z$~y}K;aVhSHe8d3D^}LS6S0Eh4rI@FXHU3QB!S1CyybF{X!p1?q?`P&FGa{rfiC83 zwsF7EmC!mg>ECw4aOO=m=Y7|3a|2pF2tC-@?sFkVtY9;gnbqVE*!e_qzcP>@ENqZFtf+wsg0VsUtJ7-D84 zkyZ#k!YlB1T=M+%~IST-hT4OCa>OT3W6&k^=_d00008Z}k#=J`A97zx0fBdyy=B2Bp87 zYA=y8JgTOt2=cMHUxM=n*LJ_j^58qSudX{g4;Lp4&O$bnLE)xs1IrEd&dMLl5tc;P0e+#Zt>duS6isPvG7ec4MX7SkKoX!rWZZb* zBf@=kJV_WKlHzAD^eCyTalCP~NgUZRP+!b>043Kv!x0;(C0i(;joK#>cgbyMls5aSxSsLXyyJI{&y)i~UR$z?8US>DEX|LDy_#lCDkFJeC@p&f zTw{V^sXr&IM>$#10W_fF_d?O-x^h4>4=)@-%YD`2L;MEb;kx5D1_w(`R2E z%#z+%Iq4wsE-Pi2-2I+NYZ~s23nh{FQ7?K6i+wC0+ccdtx54Cj+R$>|1b(yq-xz5x z^n{9tfKj#5`6neG$540#JOBqo#^3<^u6q@s@lrn=!|X@_-#pRRT}^@T<#$!z{`j4F_;uR1bPGTT^&F&XT?WQ$g!oikDdhD|(?43k{j=_F90o!Uyb zK71N1dB?ZX-7FTYHx4E8PVkLTD$GxbLO+;`6$gjw1K(n)NAOCsyT(W_eAKcy?9SVT zivm7;ZuCM+v%1c0751CmpwW96r3wUpPqKy083f`l(s3MW3W4?5dydzUP*TYH-sm98 zsM7SOL5V)`EXkhxo$};zlwoyeaHV$rh62=kZY8vOJeR-S{cgnz6dLSXe%c(h*%y8M zn&X5KB$+rHe(5ks5hr&qWv~|hjU>?_ZEnpCu2$F^btP6P0}5dz2%%Ow!ju{CT^Mx$^d_hA44WT0>?Ig|={-e$Ya6D)P% zE6BUC8uaIva8K?D-PhOc`jdY&61Rqt|3~9>DnQs75A8XWi1vha_XZ#&K>hC`>HX(A zH3TZNbjRa-@LM%=5gxBN=c+>&zTr3{F9HL&)>P+IM>Cg$nbhcKCw7eOozc2evQ$&< zhiH%CpKusi;L*4l`(z8F`y-h<&z%fA3D$tK@pW(4U?X2>!AL_xmQ&H*mq8Yvep-4; zMG?FUoIRQW%&48wAtJ$i{g%J;#K=Lxd=0S=g}{>@bI6H@n((+e)g>)Cf3`ygrH*dI zn8C6_Ae<)T#jnhO5*3q6kZ*&pzqL+A{==JBYm%$D(c^SlCXVzBF3VN9M%%nycCrnf zT61gOBw|2O)OL|FIYfMjt3)I1`PP;G&r=FVX4%<5`-E{t4*;DQ*sL^8J<*%h@aO9b z1|(USA>?eD7V;F6c^GjgpqAaFps0WV z0Bt-2xS9%P)dG#|*sGr3r)cR*RZn16J;Q>5 z;fG}TD!CoW4PU36+O^pgN#PRiQaZ$;YdWbT*0=D{N~atRf#OMf<1jt_+y?%I^k7nA zQ4kp5k}jFZRX7M?Vzws-+Q?2%Dg}1&I?N?Q0ZY#6?OJdQUapiZaOKRn0Mh0qni1!i zPJez`n#7{3IHfFSH%Q_&)FggMm92N8D>wF_!i|FzF?rV%9oXq+c-lS_YG9*iVPr|G8Akv zdBs9QrMhw}brFTKZ$-2&KQ0D%B0jZ;I1+iSu&{)dO zUhi{PcJ7Spme9PHKGcsPB&op|v1`eX%tRcLz~KoUCj!N!9pt&L$siOYSzAE|wo9U4J>0$0y`I#4`>0X8?MTB(wF zelD;9i_#X7*>~e{jj7EY5C5Ll>f&rKt&FBUmfAOI$S#tnVKAaC7)+%DX!j3`Ompo_ z^f4`oi@$XW#5?*f|%3j?jyyFu$Q--F@ zs0GBVaFsjCH@FHxsk=UMO>nvJG)UQ!;f*;2DUIC}uW*?Kk2dc>Yi6-T>o~l3D726) zMyYQ5H%5Ae{ko3baGCaF;J71rcwqnq^Pq_inv*kXruQX2#wEgUD_QW+>emAd%XRq0 zT?Rryu0c_*4#E#?FhQZX_G;<<7PPIM%y#YrD!f5Ak4E~dAKPU{mT-Nlk)RGz5chMe z24kCV-JXy;u6eJg&dfo3gPcqpedI9H)NNpQrLL3Si3B9X1q3CrdK5Ky=te2j6-GUv z6i{7AEA_19md>$3i9NUh?{Iq2fX7Ip6YC}a0YmWxJeyA;u; zK>TDngBD^Klil?=%eCCt69kaz*S> z4&+TW%-U?uGbIe23BAy4vRwb2%4SyQas}{pI%eIioc-h~(m?urGu_)nBG7Ghk>Wqz z=y}t--F3t`8?^GYkinO?zous+VXehf(Q^hMB1rZnE@PQXucfWBfB$dQdqMO2PZtSN zbGgx=)B6#|Z+g7Pn>e(4f?LL-a3AAzdu`EBR*s3wJkH@#ztVh%3KiG=9m3cyHwj5s zj#zAvSQbgk{-ng@q+_oj#)|*ld?B`VZz#fyCx2F1w6RmR{sV!5Kx;3yP%I~&%BZnw zj+|xt0N`ZLG9qG)^zVlLMqHc(&lEG3ta|2mbyt=Cg!AeR#0j#N6w+=RRNtD6kS{El zjo?QEt)35{aK9oKr0SY+@M)ht{CCOboWtgV&zyx zmrS&Fg?0MhOK+-X;)Oo*WySav}I$l4~oG2&O z#pjJclF`sycjrfs-)`539$i7yE0q%@W1!iq)`AR#rzAg^P6%^tUOjCR4(%C#yYWnh zPVKdMlY5xHOJXVm7^kEmbP>$N#{MA|6l3gY4w9($b7A$Ci_FP}UQZ0bu4idU&PAvV zpKtf?lmH3Ee|n|~-$E9`fa>pEcEm$3qb0f1H8ksmspdvH3mFu#)TWd2(>y+XQ$m68 zA%+`nF2*9H7*y0`qoiMV5fs+MsPGSrq>m+#-y(!2m4XEG7LLSF7rR!803GR~PuSFz zN+|$0ROS~X)oQDp-ub?HW9^UlQlh+xMqzzHq_-sdABp93fP-pzZt7 z2>P1r6did@hhc10Sh7fattHn`gM!vzktig@otg(&$r(=kBpU;@$C?BAl?Pbhp0@b| zO{cyIVXzT zplm9x-JnKWo1&2ur)tJ&RXui<+UVP`RO#|ee-LIgo?r76piflsolOa)gsOcp8jLUR z0C$1sUEXIDB2xSPOVq9_W7yd_#;FCFeV3=AmqUYb_>uSmggO|WWwhyKQz0RSZA}Zp zan?GF`B~KGwsd4AK(lbc0hiOo7wh>=^a^q=xyi_QwbDamIPx*{xWy{9Zrk&0fD5ZO z53EGrK_0}mkEz*y5!BWxN1iVu2hb>9{Ilzi&xb$CrfLFam{hZJ5IouMkcT=!(k z;dIXtx#&)Rz56!432?6)+9@9Y)OEK`oLSs>^d+iF1-xtq1FgfD5W06G`#GJK|BDOU zD-y!+skEvJ3oNA{WrRW`uN@UJx^{AY=qO+ar{4!1%RA_Sec+1ffc6X_*S5&94ILVO z%hl8nUYH4$NJ=g_kPTh8R@8 z%(N`L$)$Jh$5r@>Vjy{}aBabx!5e?W%`Kjfqzwh*U7&feq0k}}fYzKtG6%`6jy-MNzcps*b3?x+MCRBh&XhH}3;>jUP?o(tOS{DO5fyw%C?3yd@H z4Hu7mercHx6e+i@wwk-W7i-Wn>L()zA{68(%Uq^BP;ecCrsZ-$FclhH9n3wuUC?VG{9(n@ZR`G>nX~p}X8L3mh6eD$>mxj@Gh;R4cki;R-wm3815PEU zgv89yQ!pShnme`kwC~)u9wUoHV=j({E^q2vD~CQyg@RBTLVY|X_a(A^kQ87h?jP74 z^y&3pxYAmZ9QX4YUTJOm9=C5j4T1hqr($q68ZBCNjN{4mqV|F)L(*TB#0jx+_}LsI z02rzuf@1Ubx%`RW;eXJRRb2#3!R7Dc5)HX(fWrKYtYz_15d0z{<8o7H?gUkJ(GJp8 zL0+nG#~>lh2pKBUfP9%CcXo8hKT!Bg&%SPp&81B=U{Iaol*y2jVL^y@?6)$Z?yL(729v+vU# z>9IIC_~PD2Kkrz#Agg|7K<`x$QC?)SZZzBt-nLWQZTJpAuH=MSG*}E^4Fit<)Zg;Xmukbj9y$*Szh@6^xgB#v}30lL5+Nkh888-dMz1?;o5W zlhb#Onb$T+2Ly_h({nZK#{N5K=Hn@h>%!fqOb*FOiA?q;v1vJFj>{wOAhoeYSGj`~ zVkmZHRx5LY$QNa%?UELsH)5~;EVZh>j-q@A_l~vMJPa@te(i+kZ~~|?$9z2Hjtp%? zr^V)U){(qD&}>9-bo%0U?^=AC_0bBiChx_z@H;xb1;S9m`J6H?|9#b{ow$nL(K{g} z@yvKSpyO#e@u||6q~cXuZHY7x6_}HaO&K65Wjr&y?+th06BQxJE}!Ea&=!Vx+t7z) zq0ESjJo)ILkD`^AA`G*a^J39e6UvX9x_lp;U8!pP1+-fR^xHbCxLr#r>D@s*+8cfA zti?Pf*)2eBK>`N&u|cQ4U8`Xb>bxkq<_12^GJ-mKiaVGdM&S9*GVM_0SYA1+{Ra~c zl7%&zW#>*C2w4ZcdxSN*Tm-f%evCaHK!G68wWB8KA0fR?1Llb6-bGbnXNGvC#WdER zD)6%Ih>8W9Fem#6AtSr0m(9eS7Si9(f>(^cFSZFhE@>=TEVY73K2fYN))6wb{MN&w z4*^1CXT++^1Witki>~EGpC==GL2xlGpvaoFf)sN9_i_;e7>ia*HuAY~>#EweLEwxk z0lO%oeS%+=PFmJoDP)4{-f!g4-r)2^2nc@tq&q(el~`VhNyk=AD1dnE?i311;z&f@ zU_Giy)z=8rO9-N^!hOB|o{Sjde%YktwVH*Z%y0*|S}YnBjGBGqRx`_`16+WsDg2d8 z101*mBU(5OVX%ded)Ki)$GME~&~ZRx;(Y=?FBbQ{6b*+Fa5Nw_agTY71BrfJ0){lJdD;TC5aE?`o&{%Y0;?%T8+hy3xSnQPG3CwEqJl)goPL#ZE z8w@a*q`Bm+>?(J2MM~P0<9`1TAeF52?=xg{2h>OZ#7fwhhco`0f%5xK)TieomZRF^ z%9HYCuobZWxk6jP+q^l#Ydrw#d2jUC()NiK!}#KhXlU~7z%0nHEuj3(BQk+310&7m zM|?{5;vdo-20+`sN*i%B`D${flOydm+n~t>(o%E4wP#d^6Zv#Sus6Vb=0$Mk(@vuA z!xS`93F$)Raaff#brEoAn$C$ZW9~Y~YRMQ5A9|rB%99+x6C%7Muze)~Lf_QyO__p^ znX6+%_XVvO#5OQ;Yj*)BTglml-&j6-Nhk*CHQ-14+l;%zy`w#u=Ad@As1U+b9amSS zwJUj;!R}*ocPb?0LifCxLE0n9GH^^D9PxKeKGfZICO%YT`wQAA#?4bEhWzlDJ1mT2 z)UTbnIdL)Nhxk7(hZL#{&TGtlhw_+1ai<6r*Q@OL013+zuqu9xC*f7<0x6mq_&nnI zzlv}IdQONeg~XX42KO!9;L;PvZPkp{`5ldZ68c}BM!j65HSLDaF4;pFSJhuc(R0pbnT8YarZuX-{bza zF~1;E=c_ly;y^-U)G}%|47xlV9yST>vdvEyFn5RkmcA`vL(>0?eC(kb82Vz5Q+q+I zGavk0h2(|l@gxb?Lu&(Y_Jy@6{@>Z@*6!i(X+kKU?9R`Y8d^@k_KPwgYc!Pg@V(gy zjjF-?K^s-%q_x+sUpj4(<`o`CFQEYRwv&tdCn-R61_C3rZ6CSupxW(4$68*1_PX!L zYS32SbgCiK)R;rjY-}dMM|62E`Fj=D4eC$i z-v6cA>VDjV@M-=KV@`xE*P8GVgI}Xorfclx@ZH&g^{{-gb7+i^3ZdcRa49uQ){joH z(I5y&ZggJIYeX2kf}&7BxyMWk7$MyAH>sI3*e}pW%w;KX8vnc*Z@QG+t?=Xk;g7R} z?qRm!IQrsabS$H5`44<96N(|F1M&!1ccTYb{MJ; z2X*w$jIB>K(dU_{TDzuI2VcFz0mJe#!8g#oT2E(Yh75szfOLglEo5V*>gHS%K1iJ~ zNb98*A6X$2U$pFg+x}w3VR0J(@)avTq&Ev`Rn_>ub`fT3xFC*d+IW=H#O(JP98PcR zs!zj#``Br9jVZ&}KrH{uo{^zW_}z3YCMivl9H~j~q^#{@7p_Tr#oxiyly|ulG^rDI z?KjNCD!T9(mZnTS!1AZY;IELH;Vbbp^8el)eU$(?eia@uFDAkFJKy;_@qdzH#C#(& zaM^`z(N*O2WDeL25?!;Sb!C7alwq90KD^X#nS-AhCP>d%ZNlz&vcQb&s#%vZ7Tm+N;PAVA8 z78Qqx^yS(->j0@<_;n8z+TW~ooj3@=7ZG3f|7wm7YCz*aa@YLzY`NGw=!WhD# zD7hRP6SX}+n8Q!1!9t#9Yu@cfp6MH5eSUEgNWxST93UW(o8+g#r^3Xo#;Wb$-#t43 z{VI%4JZ4YCCP$19)ltl)h_jGYiw#Y*6UV5-E-N!U*(6C*`rcTJnx2OqGpMcBd!Q1` z6$^WuBE-QdBZnPTj$wgSDY=)Dvrf3uwf^;HgU7A3?MmIj6+*-LdMr+15ir0qT8^@g z-rL&cwbEY34QjFa8T}7(0xWT;eb)1kF)-I_(gUvivi%R`kHh2<$x)D&ALLN^UNM!) z^mZ~-{58G!AvUG-yE-XyR-eKz-5(n)3b4&ahxzA>-{IUKJXfGzdr7=8{u~6C-%@c$_qa`Vb=^9Fz$I zjK<&TkvY9$F4!pY9;e?c58|_C*DYWXM?xl@V{5a7qw$OKw=R9643HG*XL8o z>^v8lt?rZYrqOHjW?GKGsVav-;JL!ur>6A%hyvWmy?Li<=)$XGuigL;bb-zCTIjfa z&u5fw{b)EYzAe%Mn}FW)d$K&ok#jU>1E|_}Icz>Z9SeEN5W;gvQ6?nw=zSK}sps)Z zcna!&9~yB&#YeG{>8%?eP>AB-q`odPa|j5{R0xuko^{#tOb}+8xENjdvZI~TThkZS z!+Ys~2Xj(5J+$Tr25ik7Rq4n(s2e%!R;RfJ>b~j~IG8%K=+%PlV0Y%TPFq{KcVhJn zkuIQFNBg$$U=}*8CrqtYh5P)05!@0LgRlASamH=GVr2fXI*t zGh=`e@+!K&#!$9xgR|3qpj6Qq#OAZoMHJyukN=O9!e?Lju9aPoaHfHuZBLJnWPG6B zH)3Elf1SCx`$uI-epwU;g_1&3;l?X+9LQ0KCm>7#f2RzXL$2eaAxK&w+R8YazPTFb zj^4H6+cNG)jq<8)H_r^ut~IHfVLh@?hcy^Yf?b}PXS(2Nfp28-MLeDI15`mzQ=H1I z(dV*GaF})AArN+70`xUN{Ekb>Y}<*pSXg3iGsF=llj!_ybB{HMO)~LaHWbS$0dmYzvDE>wOxn_-9diraapY+p7Y> zvg##_j-+)?1=x?jnQ=RyX${XwK{ z!$y2Tz02+=W=tUq;AM(Qx}6SAyq(P8X*Wh3b58keAwe#QGDkYkmGMF!oHe4Sn(P@7 zoniYMhLQ(1;~ah5g(;XQ!1U zOp#jjXf^#}ZteX!87C2!KEV6s|B)gM(P{+Wjz{gVTr#!xDVxr6r`+tg1qhCd2^RFQ zT0+5LM;*{ zcRgpNp^6y?gTq03&@`UmD3ZuDKV?RetycjmE3;mdnbu@R)dv_OX%|8TM12ATn@C|_ zSEG%=D??mZ?wl+ZsCI7ynvUb8A#wLGP2BMxj{3zJx?x2faGn3si*OG~WO4X*P96CF z69RG`5)?0ISd3~zHD42%wDu;8{3+rQqk}UUk?dH1Gp3S(`2Pfy$m^Aj(f9bajfHH< z4~lV=h03jmfODAHn6JD4W@;#yxZ1?Ce*FkRjbbmQdCY8k`B++$PbUXNgGezKd>wrL z`E2sqV2M}G&xiP??&@WOnVJfN3!hZq9|S*=LX&$;5_ieGayD^#S)C%klZe9P$*o$w zZYx2Et#rp*2lrVGP{;-K2tB=%kxVLLTkMP2)+>REuT?bu(?1m!_4}oM*KYIOw&54Q z^y=ere7GYlg+R3W+|lZnIuWg@H=_a}87G|CBlH@rCxDcf7|ws}8p`i7L$A*zaSZZa zumosjEQr8Pc=&q&Xl>uE<4^NWclOsEuwJ8I7Xgo+KN|; z1hq?W3c=Ohd2jm}zADBxPZvhe{BYI9O)LI2=+Y}aM4xmoYs@o=v8$HEsP*RVt}9b& za-wDdwKB`ML2)f7qeLU@s|*+&zmCiJi}SjRonJ5&Q@nERwj3sQAPYD>PwPcUYA`^U zxNwR#5&986tcgX|QfR(2NOF5YtJIsdFVhbhAi0jVsa&I6cm4`}dMDWR4j(UQ!s%o%&d=T8XZ5lKWLEQ9cZg3R`4^@1p7e(mnYC75Lah5BWy|8vGAiwaP4 z2}w=UIE)@WGs>sBv8#!wI(N9^#>S56l%ehaeoz;haaLMYi&AHV$0U1xVo1f7P;LES z+~jxGa_CI)u)I(wXllQxgRqSsqPDI_7ut`KaWLg+?@dc+%eEN;YaSPpq$2RHzs~wB zi80JymKKu1jn#}0qg38-csu-o{S8tcUUd0gcdFHNJs7QNndDVmyDP24#zmXF;nd%* zb*N>vQVHZ-yo%4_9HSAWvgZW0w>$Jn!Xhqtp`-567{>e+=2_%tC<9U=5RLenS0+3t zyg$(A=hC{O!0*U1wD4Ic&q`VQM2Tj|hZK92%Wn(2*Lci!FFZHKc}nV zr%u3EBh2(XTXG5w1$j@=lgb~Tusgwi7um8t*2G^9Fl_2A0l6qOdgf!*a=sB`rm1jLeGOlZu5WUC;co8u!?-(A*2xqd^&X3_xb}`!OGdW&v!}A~-f@o5BtZ z6n&u!8EM}MAF>$W`t=)fl4!}q_^P95;<*S3PVI1(_^Az#rhm$d8i)v4_D|$gLx*^n zuA8`z=06m6U_~Y7-$V=mi(aYMahy&}b9q=gV3V|4=qE*+H)d{;)e`NAtfpG#xdt{7 zasXxz;W&J<6?I&hiMA_xSeDaI9bHz|Jxy@Hm+9cq^#gA^`Qb)MJ!hZB4!aEaDXvL` zLe>!_87I{X%<2@ssXPe73{Q6zT~vf}^904iNROT{y9oxBh}Oe=15U%-Fs@cpr=?2J zRak(F0PsYJtX^GC30gTzx-4b@V@+#rcBW{5}5U8(lU*CIr~ zHj#E2DtI}I;7gMZm#lD%+$s85kA9P;1@gi@9AYB7>xKDM@Z3~$K1l#kW!_Qs>}naW zcP)ZGhNY%S-iCTf-F3#*WiUwCrgF(IE;t8mx1azXxrA0^DugG8j4!rS9wOzbAM~DN z*WkaBrByWqtsItVO;dY4Q^U!&;$Z)h<`eJx5%V#2n7%@wVSPK|zb&ap6Qg{^I9@p- z{v@E{O&a%jGmmqkvPbzEnw^5n`m`?7>_Xwmeb17uz3?X_HxKGr=hj=1$*ccFP7r&7 zr3G6;&!KD}gjgnKZL7iYo+@tlEr32EvBcAP5x21ey>U&2!G( zD#z_;-JFYvdNMv;>J06E>X!{zUrk(#Db$NL817^W7M$WsqIR-X!Tt*1L~`RmV|9^L zY#Kmad?a*tDwZ_KeB%k8?zgHKWv2HVTlYPFSS4{EE{g~yj#T4nQ;(sX9e}uhl6zxcb_~E z|NqcZZ-!@i>=mElXLXf~lIcaPVfO@rYjDC~g-T#DA(SUJOa?Em>OT*``tyqe)jhVI zEhL}}$vqN|693q{$}>KifTC;0To$?l1GsMAM%pT*JVR#_it2LWr|BTJX>b;FdMX^p z=($Y1t{|-WJBDJds+JI8YPSbA3@zN4?Ygttl#zN@Y~sJB4-YDE7IN?D_J?S!<!x-cT0sW^zE+&32S!HEcS4CbOO7F2#^(d>t;zcm0 z{hVIAMp3jnA3LWSLLz`)$rNJwC#>kLxACKpd5{<-&ch*TcJcLTbed29o^@i=1QR9|dV4L)NJH)XfEp*(T=Dk{ z`0-90ss@0_I9W?#U|bx9S7?>$-kNO+ShCsk^7zc3Bk3XdY<0C)4=bxW8efA{ZvFC0 z*)O4m4RT`>aDqFXnrgN6G$C@lNq!hVuTj^U zILvHA*hXxd_-XNC%FUg;q}yIrBI3>q$IY_eSF?;+Ib|vw%Ys%7$9YB??UuoavLK_zmi)kLVKTq&;b=RCdN{H4S5M8p(Z>So7U7oc5Z5TCE zPs@9U&cw-7+*q}i&f3j=8j3;sgB22bcq(2sGy;n8ia)FCoQ)jvktf$jFA;0}sJ8Wv zR7noU>f1RvaUsu*pks3Sni&5#?l{ zHTejWln1Vi^TzLZu}_M~v(@y>h#5vCa}Pzn_Q_#EARq;!-4dVxgi&Pqf#he3!eK9# z*Zp1{0#JH)ujKc9>mA0mpjwaHkm>sxKa(;|3f+ZyEHBRKR`9-RgXvGqV|}rXq)7^6QJ7H)gb4JqkuIqy<%~_Wx14S!mFismwJl$VJR&A$ z7D)wVzglNWJh^`T#_cptgN+OEc)xUZ7t+!zB(ibHeb$BGM4e97bd>=|G>~1=qEjQ& zVCJK057{UU*B<=?N6gQOvr6Jh&s`Wf#GNlScD1(?z1{)69v+dau#-d)B9;jhJ~M~X zQ+#xeOSYJu87WXC4Nq+C5SQPPP9Z_@PW_2^&a+z?uiuc9$Du&M%mrg;DdJ_z3x1v9 z(pop_B>X(5nHoLQ9JK9`Bepb|;TULAwzFY3Ma*PN0|#_ibOOx3YJci;Rs-XpSE?Gd z!miN&7u+DyT^oXgU1K0)UGT|%F_zL9vGU|Ca5^caJm1}&Ocmugo9wLK1g6O2fdOWE zNoXwKwi-j_tSLyWHTLy)imI$S17v?Jpv5~juG#G+|M#MuH(jodz6|vUL4gPC>ptD+ z_D~B4D!JoI64tGq4Q2gZdAS5RiR!a+_k=J%wgfGrkS_TI>#K-#)O+Cvkm{ z6;4s-JGx#5X=s^$Z^2Q=0qSAU?Ok+qYE33(2TMk2)`O&;X1Q0QAwd`epuU}vg|%~u zJ)}ym#E@-9ueYsuR#qn?pBJx+Bz@z|S+g3(zuD*r%}WfTI}#bD?*};a=VQ!3p>r&HY{s0gAh`nk z$ru%+u=`1g@lRvHdEgS$2yF-A#cE=_l5*IY<6t^*i^C@Lw5oVi@vsndxiWds4vF`z zP65~6%Xtgh9kqAI?V#6XBFFF8Qm+{EElpC0^sua^9egNa^#KmGK8=Jc%W4OTwg)1g+{#{*Q z4l=0*wa8MPI9NGBY@<}TB{@J%TZVJ+&urW8~f7jnU4x z>v1=OXOY%VeXApBw8TvHgAiUcm^i7-_4Ifb@MRw`mt=u0Z}Xv037>pLN3HJ#7*??5 zvWbjGNpy2EyyV_NunLT?g|9tX)*0cZ?$hj)urnbreCYU*h2k9Yt*^}b zYh6{2EykKx58?<}9;uJ^HF4hADiOa0UB%Pp>H#oGtc&GL zf*kAMfRR_mES&h(uemqnJ6ZdTEz(TyF5HtOV|uQ5L&i2wR+p@*;`kyvv|L9dHzx4u zK1$dW6`9`~a7Q`^fI(vE+|AcJ7@9e>(epi!MZ^KG74W%OK`tI3e^!=6ZAW;j>=%vU zKI>)4*Ypf42mf6=3@_eN^Gqmf)}tUoL{uY3kY3p2J|attyvUxkND;BcS!TU(sM_)V z0d{ySgn7-=^4x0efb2&d__udk_O7Nop z0sGPCaYFgf03hWP9K>yQ=bmhy;NV}g+{cvQKJ4mMXBNi=;<*3)vt{}#bQJL@CP7ML zHUJmcU20r1VXvniCqY@C*U@=j7kCm0GsR7auB4uqjpt%-L#~6{S=&kuND5m54}8H<BB+~5=kw&wWORQ1B5FMXg?d`?-P%sPbNNtCWsBz=$qJirq#4$P1sPV^nuC}gO ztXzqZLD3hXMk3f?g~x1+JfOI!&=(R2j!K6l7;)RSB{83e_e{BY1b|fj6ZE(f(84i( zwN_LfUjbtmKFhK4uMe*9kKwW*FQc&~q4#OrRH%?hLRfDRsOy7}s$ZT>N$2?ono+v&(KzcTcIs!ieA+YcBI-qci)xO zpk`?|QtE=K$C1^34bi^Y5uY@8NESanS<3>h$^y}kfz$!R1o#b*~&~;?rE3 z>q;g*1z!+K>Zjocab>%6zNdwgxPP`C35bPf98K{O2349&>koiwYpE>Z%WQ&VR2MIMC#kv^ zBP?!TTLWXmzOXo~Nw$TqVM7YP1t*C2O(sx84HVK>75d^|=`R3s7&s1^e(SA6KNM3d zm%K&lIw&4hUz(1vs-=G8!2Hem8v4kw5KrW}zv40wfm<%Hdn8}T?zE+m9Lf~7%-+Pk zYu&@0cHCjvst=i1&(&0F6`1t-Y9{#y8)Humxie7m|Ho*;vp*E=zp^<&JdIW9g7L#k zXbQfCVBy|^WJ1nq(fJKSoPT;(x^L3G_Y0Sol2)BTB~a*L5gZc_JW-er1YOFapl}fv_bk zEJ^)f{RLJouAYFVVi`-V5L#}4IiF}PnZnqIqpw=_0pcxpJ*rAzPUCJW$vl^5cZ(VB$jj-3{-jC5!6@1pQ)MrDWe zYy(EXzJ7->EQBC7%@=rum9}Z4r_<>mlBP;Vz+dNa!WO1h#spFVbUqAmjJ{?>71aF| zQ%z3C6u=_$&V}bHTm*{Xej!cz;sAV6;QOO?>xl$R~hRMyB$-AMR%ZTru;7Q58NvBxi>#bxU;!0@Nn$ ztCeP~E&Ks2yL_Ut)Li-mal?zl7G%tiQM>3DJh0M})*haezZ16cy{Q!G=r+p>Wgg4z zJ&l_4vnBjlcL+N_A>pr?F;FwA4eSn~(8-mvB z;+EbIFU3*xcFy*evOfX?7v`{J$2LSn5?@6yU`fHqG`d37d;+fJQu|~-@|eWe1(=n= zB{cd14CN=~Fn)}>`$Bq|22netk$Sv+xNs@iChs5V(rGoD8D11rZev*T9p2GVB%Noa zg0@i{2|Qw6(_+3s-={VKQh#dS=t?U#2`WT14@sZUU|Ur5i1^t){>osX#3AyL zymv*(^mDiqn^T6Z!;_Dwz_Rqb({y~mez>mL(%*S-F=$g$H>^xbeQPSY&XQt`KDP{M zQISb2IR_pqjIw*dbObxHz>&D%^qHt5FqalOyp+R(&nBR{C-weyi{9dpgpNQR&YHza zW8S*zpbYC-@oj8J@w$t`;MZzL%0vk+qZSx7w$F*lD9P|jWAvuJkLp=G90z67 z1ra^VaBAMZe}MLo1&enOJ;_~w>yA4d)A@{A(Tgwv_!O~o>l}Mj5Ox;%GqjFxi$HlJ zAzhWd08kPz0sDXv;_h^*w8DxU`Uw$JWdIf9z612p(x}xeKloi_ zb+6`+zzz!#VN_x+gS=Q=d_s*2;qLaq=Vl1#qhTsxggKbZLEfj=AG?$$vp~#~y>A~n zylMgXl#lw4`3(`~U85q0Mhz!80_T;kkI`&~HN1?l19>D@N{c3qK9nU{n=x3Cj^Yto z$N}L6Ire07cfb|uRLM7E=F4blA8-R-d6;}C#P12=a*bc94IrIsOwfapEvztBx-x_Q zoAk5M3aSc16vF{#R7flM98SjxtxiUyrE-6xgw3Ks)ti@i{A?+S*=<2C{sb7Rv2{a| ze-v73bbC!Iyh8R?$G_d4iY-wzjbyJ44Dy)FFtfoessI&&{B8(t*Uc8JTH*j=DS;p= zIEeJXa3E|2o!xwHFEkLEZ>#Cl|xib0;nvQs!~>)IiXjmPtQad@12 zRA&NFb~AhZ7+mG@5F`Q}N|KcedvHN|iLS)X+~JJd9kZIjLx0P`MDh#hMlt+vU`3 zf0YY`=WHJ}!M3ouS9v)Qy3HS7A==s14)0Z6-l*l^kZNnyT{H?=)JwKM@cP!R4U#u` z25LY~#p!25P4w=0hGk;%AptKrt#zW{0&n9BBx8?Hz`Nb(grWrW$M^`>nRk#eomzd3 z$1m;afjGtK$!(6@xFjq6({Eqv@mAMJeD;Ctv3=QYr&t1!Ld{cH^+vB=VN0dQe|Odb zW>{=yaih#+45|8hmhqe&=nF=PFicLJ%SkA;PZ6pcq~krKX5~e^F9KY_t7PU44;n-I&?N)f58Nj3l`FJJw4@VIoEQ+jILf|~Ka}mL15G79gYwzH@ z-MOhd=VRn4l%(Xu$?qV&Y{dI_|+OZyEN)JA`)OMu}jn{ zcY60&W_Co=CF<*hj>>Fk8;5>S>M51FG?y{ig3AbSbNA-hwGbkllGE-`O3z;d6UzR& zwIjjJQyAaUu4Y(C-z7<+n6LZD@HhJwhJNj6I)g0Adi=!Bf@(t8$xs4ol?X4OJru7L zfrB5&ZEi}Y9$DrK)_Zf1Ri9DPF`!@gwLHEH)QL$j2ao@&$BX64?Afw;D@i%aU`McPPrAv34zx78hhV9Fa%bh%d~o|^GOWTJ$c73;;_ZDi+UMw|ukb9a}W1&Gi;#*oNG& zjYIKsZ&7Anq;Z>L|n#p1Y&LpuV{WMG6Z5py+%b04cchKWxi!$f6TtfEYm`lvEd$|6L((r|Uq z+D7rtzNGVo*=gZJ582^6#rC^Eh=QrCHlla&mPA%M_{Atzc7|zq&A~oFajxmbvH(pc z0&q{-2FT!I^cu;zmc~qo+$}A^YHwM@W|Q9Fw_q)NJzhb(z>vb}v=lE4rH$>&#vV?G z$WW3G9akvwN@^P5+URG^;<=TIaI+jB?e^#cny|AFvQuDvn7yB`DqARNF^!6hwYoyD zuNOH2HW89G(c^HTu+puTV6DiaOj1!5WT8*pGhq-{=y~Vp>_X0vb_>QbtX13m-jzNy z;pJ%BXj37;^Xlr{wus`9Ai2Yt$U+j~j-1bzJCICDN?P+DiAhE_Hm-7`O$(olGm;Hm z#9dzx%@wC>cO6(_w_mXe7}+xgU|rc-75BqrSRpRf`L0b z)stpYuePp?u@ag>+pNq2R9&@f<|H?MBqqx@TM|zi#{1g+0vY*0H*pxqAtSR1%Z5>k zFtUWR@d6?qVx7Z%Wn3M}4IL80mO~|rjkqL{b`z`lSAjCDi;HA+2MM14|Bg`h( zfVDRm&w>ex4gf5WngI#21wf+@;yuxTFRSNsElbEuVpUQF~ifj&_xE#HCKs1y@I)I7Dp^s$aILkixE*&Wx9R2@|o4!K(8Oe3!tLaDi; zC$S%Iw{C-B0)U4X`X@ZCBT7sy97wq{!hP^?iZf$uCw9Pm1A~kW28^E9Lmz?*y{j|c zcHZvqB^BC1%IuXyBfaNnQ7w+sFBm?e%eE7Jw*fG1p*u)ASGJL|Sl3!hw@vSJooi9J zPHHZg+CvUCF7ZlN`B}P`gE4>YtMxtk^i}$^+HNsyiK*f9w3PsdE|0_D#1+?tG)9~> zm35W1Z(CJHl;mU(xF$K>S~Q{-89d8?rs2L84kVq9nJJoIkbrG01I72xdpK}eLDpfcwo>vr&KExZ#|sVpBSp_q$9td+KY4Dt z2eKOIA>?hUBwsM=;IanJOudh9K4ICWpD20teh#rC_Ev#tipQUR+ZXY|wNUrA7 z(R9#Gzc*ea-$G1uU(N$1NB}`Uew*R0f#(!v zKMpKv+3ShSDal1N*RuY9GQDJK1@-g;dt2nMt&5Us=~a`=Q%ej9$}`1TD_WbxU^$;} z$Tw$7FvbHg->Qy6kF2KWT8f`qX8I}$<{0bDQjrd$8|wpHs<<>=hz9J`27=equMo5x zAY;3#*&@g+7zrM5y;~ONoRb7R(d^+GCWYC}NTXN92fhMiOlLFTuGbvhnPX>Y)5yZM zpf*j`gXC$XeeEKBS0uCjcuGKad}ef$=|Ab734&U#FY_nhXH#bSjwmFzWfx0=fai|= zI}@s0*TU`&uB?$k^$a?~dbJ4SA&Nc0U9NCzyesnRsU2){>g&RLU0(qF(1~EdWm0(Snqk{a5#45r}NHA8hNJOpzT?3#fG}!md zZjF9!x_j>s>*PCU5 zLVq8tOLFG-avuCtH7!moq8{JKVF_X<`aIS7j%*@_-{}XSGIyJL@5K*lZPbd_Tj` z5>6Zdu#0$Qcw5;ii=Kqgxt%yghqc*JOETWb%NXx*=L~;dDJ~(7CP2i~*U~$wMu$Lc zt2sT2@6 zF{nx&T*6t4aZL8B-pQLuFqBYw6LWjmp#o<{Q+kJy>_x~ zgwGLPey9nD2Fxmz1Hx@~8u4mqHwo0KT~@+d5aWr?><} zBtceqEHng7NyW#2hN)|rXyVY%=$$_g(>Ye+7xTR9h|Q!r_R|XLQu?tst~gr7(`vp{AB}Az%5xeU z5ca@V2<7y*EQFJC?8jjJp+0lG)VF|nT)(`5puSk&W21~lu)*NTV(g%!@=3e zvfbn+l!a9a_H{Q=7>g`C{_+=34@_P>q3<8tqF0Ps_CL?(%ie+p{7;KM#o`Y{~?wHr&gU{BU;s4c3NRTPjP;&a&Rqc@1q?C7@p`DQLI|81QDBFZ8m21+Yb(`(Ebt>0<&9KY zab*GToi;m&c>{Gq@Py0&6smAc&Mndi&vnufl*+KyYm}i&xHE!qvnbBOG)uoK2GfuC z4YoZ!oau~1QR`Or4lWK%tZoZKypp7*w_&J|!I1KJe74c>v2~i^Zh+1z#NI@guU+oq zk9{b8LHb1%F!scJmrtS;AoD|g@nY}CzB=cVi|?NckF(w#O$Bym#u@&c(t9$MDfVL= zQh)~~r)gbYeugWZ7rsN4)fgW*`(VB+zE{iJ_w~v8qb}`@KFGdW4**nGjZOSH@Cfjz&J943ZK!QIXlf}*=g1;P)5GOw2AK* zj87lsfgQ>Gp6!SwH`a4XeTS`--%|Ek_6-ZT_w{RZfQPFJYFpFalSoZ10vY|;S{yAZ zBBx09FNYwmAT zUGcMPeU9RTPEbnA-=~l^%K+l}ef(gYYmg;>sl|gOb2X4WEW;us(Z7@?ia5d1!OBp;@r^sq;`*)*mRT0y zhv?ArLdMj2Ep=~@-UjDf-Nhwx&O9*D48QB3{M1-nrady7pE23>sQ>ilLbRV2PO>QW zP0ADySUcIM9G3MJmdpi?4g8!P@Y3HP)qlm(^nps%;}jVY9}E9$uWQCpOyC$=C|izL z4SEhsmJXEA*+6}l3D+;GHDI^}NuPp`DhEC0w|r+Eyyh9YA)F6f~p)u#MEHoYpv=onb+KWI#G5o&%`3uv^#JYsd{pmUC&0kfpmRu-80sK{k*(Qv ze|`CwE+#v>WGn>A$uYI3#c{vyGqizS7XZ)~#eF9H`N14WAHI@DQCVtF4|u{JsJRiW z5!+ykDupvO-|}Z*Q^AO^?B2hI4z@Hpiq-eRdCu$%+0v9LyF|QqeZI%u(>glNFwdiE zk>F6h%}iH(#{_auujU}!&lj8(Fj{Mb{dJm|-lcu5!tGrhjc5vm!*SQEq^h5Ot6h(A zo!}aN_QRRb5Npxi5JQEsJ~i2<9UviKem56fOfb+BdN@ku$t)?qp#k$HiW}lg?(M`a zL+ZB;i!5nx2B0eNj|8=7JdCw7XOAwa2yV*M#?GjNs|3yeYtLinT|2=;Ht7HF-Ui)0 z<}kakkHM&nYJq@l)d&FwUtAVWwZO9<10n>dJ$_;8x8Hdh^x;Z%wy)Igc@VG@^0lto zGnrPubK)9#ceN_B>3DF~%?eN0Ak(m1ckpJ>(N?wivT+v<96i~k8Yais9p*{-IlUXo zEf{(reW$yJNbp@3=|F2uo)oFPRhByGSesz_a#x{e*d+jamFlGdZ*W?87I-xG$`exd z<1I0XYdURUQs$}Cc-h?Nz?xU=*IVd+_%@CQ8qS?d2EK_%6-O2e&eo4c4o_*kAhXj9 zT7UeTP7&L1WohGClQN<~7;K2|2#FxerA>D2CYIzkpcic+_J$S51)QjRHH?g33Bq>1 zMoy;ed83n@-)}Pg0X)reE14wKL=E$jUZcD@=4q@JC+zpZzKUt5(Te*E2Vg|oi1&|U)k7?nKiYUm+-a5?x|qK%f9ZC)U4pqzM2d^5J=6n+90zh;au zU&`9Dk@aY3b;{strQNmpvoOgY5LBPd&VDyL=bW#|I)Fk1rmk@<@^6z*D7+kvwf4CR zyD^E#9TG=1v2`Ay##BSqE%0+FGHsB;xbOUIl-Q>nenWB^4Msvc=oe6eogcbgCTPHxQL z2YnR~Xmn`A8{qx8ah61S;(}fhb#k$J?i}I8`JtE*-hlGk*i^ z%NK%2=4-}=6H8MwrHy`2>1{eIjF0LvSUVrh)8KAf`|(TjbhqnR)VqlmF=!Xn-*=<> z=cv)%t{n?+WrumgLqj_a?&_J&T^Vj1SjM7fycAF=HQYlNnDSj+vcN9%+&N0Kr`G~>$TFcj@7h7D>T3von?OO+ zYOeGQDceCby@tuSwmp-ox z8~91uW~HX|Yf;|~Bf2dFek4ige@2-3kI`U0nC5vHZto&9{B^gyhQEz%KTat->ji8L2?*N=4bq4ried|0Il55Bx($s4CFkp;IwSV^+zuN3Yl6A8 zj(Nzi4>ZfgD?7Lq3Of_o0j1GIig%#gi4XcQ-0jJ_eBtVMOu*QF1kj6g-oyk&@lrid z00nDeClR%%l8a!f*)qY)uY+GjUnGu#eV2cr^se1Ewx-4Kr8XQ0JTe{r@sj~D(p$=z zT1f2Gaym}rPE{uv^B`QO{wyD~AFx|gl_XyLz_3|g7n!$sp^`cBBnPy=5Qt`){QNO4j zhaFuN$_z!S`S76D!oV$>#v?v3Jr=rC)lq@_TA1SBU;+6BgFEXO=>6l4oc8g}D)P0< zyk$PT^m0PhBwPjUd8Dz@&J2@iqhXOmul4v=DYM8#<2`|~S0r3eP5$mdc@4xgAlE{w z{HiH~rUKuRV93g!*(zcjZ{HBFTp^V>44+KEZ5Ip1jK z4z$cRgtc+=eB|ZjQPRp*^Id1}SFX+NWsw0Hg`GI57NpR&&m5PvvS^iaL4GLCgAo(L zC8$<5y~#Vp6|i{Il01i)Y!#rl_fRna$eh(h!_krvWn26z)RN}gx?o!@1M6}is z6kq#`vRSuCE1u#`<;Nf`evvvxsSW#P<=9H$%N*CVPAJ+`i}kHjtHms7_mN^I z$IU`~CulHcApd|CQwkgta$pUNz_vv{v>OLeaHP~=v!v#6z7Y&&PWVAaT5V>v)Xdrd zgzvL-T6E zCb+-Vd{e6*MAe;JL3rthtK1r5H=gjXNLjH%keX!yqyo9HtH%EXZewF+%rX~?MNy?!IL81ysU74QrVhl-(rE?$#oo}J+N)j%WS$LWDeh)jKZ7!;#YJxqO7H5Fs&^MxPr=jo&$r~ zOYb>~Hx#<8gceAI9-F+CW>(0Zvts(Ax-vl?oKy9OSXa39!M$(X_(Vn8ZZd}r9|pD% z-5^AO!hmU-!SC0bX9*7NrEdDz$~gh#lDT?p)>%cfQ@T}8IEka?t|J;bb}U!Cdhe&8(g>5+NHO$LKlnZaiaaz~sP4*}Kq$2(D3*VL}xL-g>*ZN=Y!$>kA0nS?f>RA9j?Gf(%;7tGJ^%aERc~&1vMY{Y9S^3)Azdu-m~V7QmB)ka$BZXDj@NXBw&&?mo+<6RlXc zQ;bFmC||xI9HJ-25k?T8oKvN8wvRq@cRspq$zB6Z)pAchFJEnBO2moI2rp`Ftjlzy z-f8#smt%$%GAP++%wc6lll!|8YkYc-(Nd&^2CNHX>X(`BT<+Jl$n<@EGhpm-NaUP- zS{5OL&dc}bWU4Yz`b@v7Kw39;C%*28On(|V6UOKSJTL*vnk|3pL!SPXC9p(1P@&e3 z5ApO2-?N~sxKcG)R!&#oy6d9IEbcYoI=Vfx2{K(9Zn3>MiHVNPp;@mfPqX$;Bn6k z{^Ip%x%Hgs3j;8^;0xj`Kl8v;E}}aqrOLd@4kQ0y2&}t=Rr#0{1NZ8v0Kd=vM7-U# z4>a{@BK9DM7Qjl=$?d6^+PCXSQPZr5!*kl9LaKu?^0Ehe9K1oo06T4|@T{C)u!$I{ zaDB$ZzwOCLpLVM!PzDX*MG_FNJcrj@mM-mUPHP(L&UK|x;c-ARoq-x+A@puXv-f0{>hbMn{6Q=;Ej-k2eU9$csQ1^Gt*a- zkjN~|l7i*|N3-VLk{QT|@0h!O5~iDB6bU=f`nK7Q#X2IPD zsXs0`{&+cuaCI|1E3y;p&69s-xf@e! ziId}8$LncDCJHU@SCCIy7PFwtOfCa2Y3k(J%=$u&TnW_eY5K`6sg$8to%zZ*qv@R(Md3doE;fKDGcl87#^PGsavV-z}CItlE_9i)q2L2 z<_`2Ua~h(T6-z2rXY?m?zx?3z?@TmG!r&&Qo<;!=&#wRvEXYY z{v$?;&u~7Vm!R0JJm}k$=!D!pa|4vqcftqoec$<)8Z*llR2&BQ^O4qmq1z5D^Kf*Y z!vw?QZi~r07hxA05(-Qq`75p(^T-P&p}e-;nwSg2+WiAAE%AomemEo9bl=Q-k?M3m!9g$ z_Wt8TJM_jK#^)t-C*vcE;sYh6vC@^|N-wR?v~fiieUW!W9k z;1XYRc9%gmIMdcim4Y4=c(Dea7~jkk588B$S#VyH@}|OR>eYH$mA(+=>fGbaK4eEd z-eswL3<@)Mr$E!?)+xO{+U~DED2=96K`!4(O%9#c9U-gMHq>e%etH!=>JSA zk-w4T7n=WtW?}Hvg9Yvo$hH@$BU3xxqou2z4DA@4gQi-YrrQ@bx$0qszA}cpdO-^M z1^Pyhjg(G=uQ4cCT^p!{8BL7*@{;F&qBIuC@j1_UM$DL>AGP%ezr@V~lwX%>MoxO& zYvVcfFhLjzoXap-7)e1aaN3j$S>`^9X#mjI8iGI2JmY;U>PRF#@|0$T+VcO9=0O^@ z*x5OPG%(EGA{~=y{*CVh=qj7yDim;h$6av4P~Gtn5V|mD7UBB_VSvzU+fO35*L^v z;cafV)rK0e&3w}sP*{D{-WH$~8Ncvr7grI>IpqM9M~RCMMa2or{dwn7 zJ>k2Y7D%i^u;#_}e?52ljX1Cc0HKmZ>xV*^|!mgbzNMMWYz4XoGM0f_p&!7_f7-hK6QhR3gpbOD!Yj*c zigD$qLHYf))lOI*M*s&-iW?QOqq-PUo4#+9Iu}t)tPY8htAXKXz7MuKp3{cEkK#GJ5<<(`PAALj)c?T)Le6IHr_C@+ckMLgzl zyN#O&64YlnhEQ4ppVOfJX;%C)Ia_pP%J4eFi5llUL$J@k*eX?(!@WCt0IRWXt)5j0iL0%OtlNjj8r!RsL8hCpT95O%$!nk3EVjXO`u8m@pnz}MWnMCkjnHp9Be@>)zjNI1Uvx>y{>;> zoo*($GBM_)KQQ8_LEaBF0-W%>68?JZF(Db~K8=h{P8xLn^#W>o%2jYqy*{nlM~iHM zt8d@LYN5X!wU^f`8NKS=B&F2~$i4E7V6e<{&L=C0E&Xg{k_1504I=pZ7}&1|h_crBc>;W84~0tEO2!3@Xl_RlYf@LE~blxywNMuGa$OFJlu{{$)B0+FI#Y-^mV_Pg=R)%up6HwAzyrL; zY4xXN5+frSFKt`V_xM0#trt&EmXz#0L|?r)Z+|LTnCjNqp}tM!R=05ewLq~I>ltiF zEh4)EjT^u!U@aO!bfrZ;tVG{)WsKmrHnVNBHA9$K`D1b|=sDgN1@ek9Eba}S4wkpmJf z>F@mBMh@}j3!DbMUfFc0sqIcBGp#R6EXZ*{G(U!l`NTc=LX)VgI`mg|bt7VnlMOxF za{s1Cv}l(Sb2apph}^VlR6v08(8)_OY$NMhjl);B7wh2dh8KYv!7gb@c}aIjN9hyp z3C^ZfgMy_?u#c?MJqu2!v3MMSBs;^3BIz<$btbp5`Lh}EiVP4~a4-PGNoGRY?1>jZ z#K4ov^7GrtJa-Fs6?SGZcCD0YwTdWvaox`nn1uiCrtwEw*vr&~HKrI#+i~7zz z))2n>BW4z-C*f%cE^AhjJZ;1>#9wY!ri20J(UCj(1mNR zF1hPrwj*wWVmL-=zca9VI zOrODORg;qfzuUMz=?~gjti>FCj441)c4gW{0jN+$zioCXp4qx)`bktLmB%-B)_F`u z>|EaVjI`OR{+R07koW(kEdLf>N&kV~P}gTXDoj&|m@0goz&?cn`NIF^{+r$3v@3IO zzZ`n~U;kuUse*F^VS+DiYWwAxNkmtOr4p74kCi-e7(?iL9A_p37-*ps^7B;SL$Q+v z25PeHL$aKq$tr;1KJIZK%u@Z`p$cjBnA+wmWqBv`t%SENsEpbv_$68~V*PYK7GZ2O zhWqEkBD>qqfE_F?c&%po5Uf_Yb%P(lLk|}a3}oST0nUxKl#L)B6CO60!o+-Jk|7pS zgaxZ$df12aAGb8sK%QRd?MwIOx5@F|?Tt?vPm!l59Kdw{>f<{KyYAP~RIa_Ve)_ZR z2ta^3HkFk$#|3*TiLFu{SP<#Z478NlC)uOYw(WNp&8hwF!c-;!H#ZK#3m8n>emXjr zvz{Nz4iP_g)uwrf*}tZtaghZqhL-_Bw95<$ zUx;R8(wWECS76XYqt28iB9#x_3zXkp0*RDUVtV61^w3j*#jhhf`$CdL1!mDqJ!iS6)qeGaDgxwi}s)B zHjA9Flb1xY#8`BjVX&YJ0j!1KcU`W^JydLru%2Nb_{v~0%~%ij1WnwEk4k+<>uj6o zaojRH<0aTg_2-vpdEw=8iyx>g=j7#q8zyCQ8$?1Xe~sn25yhaoIFZKcXf21)*?qv& za%l2R+bVGDv0yiEL~0tY5HQLys#+?7(EdaKzjHC&JOQU4H843t6%^+H|JD%U1DGf9 z2XCJB(XQgJC12l5HfxG!jDjq>bJmUJ(#q18!cwy}qPgso0a0qX!G_@Y?rAtlw@PRd zH?zc+@P-4M=58H|-Uz8AjQx6;|t&t?2Mz8 zpM!14-v$RY$P|8C5QL=4cKr_TDp=D* zAhMq(ro9sy_@Cr@&PZzX)1PMmw4^PV@YO9bihdkvi_Mz4F;d*-%MiX#Hf(t*gWqR| zy<%vFV0OHH-~3T3*1Mu5bSA4Nh~nFLl@R72qvWk3{bEss{&8%~!%7$(VLN5DWBb0RcqBbT_Irl_)gv!|xlK>&sC*d)VLeMX zsQJC@Zk}-`{r!!L)38Er*{(EenpOC}XN?^Z6HKNpfyFd7FSc>na3YjWPepAZr%S;> zPky)7cZ5GGTvOE3KI(RVyKTqwM?XJ5X;)-AJQR@egss1peF?ngD_A<$#%<%u#uNa1U+w zq5QgLwM+Vkb}R5dRACnm1#xV$XJsknw`*);ZJC6qBSCJ~0VE{W{Ebbd8N`b@QbW?G zykz)DZ7yb_CpzkZD5cN`J6N@Xd94Ih-%bmw^Sdx_-qh+$f*60gbq=M@F~d{~vmshe zmNv<$!rnLG#5-)CrwU#03&8+kui%!oBTSl$yj6mx{#tQ$wOzp4{bGIlHrgH;m_B0r zK;w%vO=f_*a78tpjUul%aBKr581Sv^98=lA6L3Mo=~44rB~0Ov)ByFg%C$l>HidG4 zExTGIf4~=w7QDf7-u*dtpIiP{F=QeNZN+>F+x${Y#Uf9=E$!qsWB-{9)@KU)!I<>G z5%Z85@-QXsF4IoMOtU%Ez$hgrqbMA;P%8kIZMlMJ9B&}?&gL1t7*u?)d*3W_cAkwY z>m?x4lsWX)f5hFIREBtE{~W=}6ca3pgJ#tqQ6`_wR(UXvyl` z!dO%=P0!(G32-iNqMVw!m#7l9Bw18f4%h}-B~Qm9e~1={722d^N4;avfyl-NI_m43 zB-k>k0!t)o=CTRbgxOtD)N+^QPMP7&cg@&)gl>jA9#?l<(QhLLAi3yeoM>*_cN5sb zP%Rq>_7v6VHj)BLb$OP?F_9b!DjK6d8%X$Xe%cAe85~wIeJ9c}u|D9BRgyrU`1gbq z66UgdBYU`{VU{copxFzILl2aKIfJ~Sm_+qSydq2(X*hgpGY;DB@E zy9fPv;P4Q$k*yv?s{xUJY;Ny{cFVGpH*|_V!RXH!M&)Ob(MdVb(F{V7#cmTwAE1VM z;JWqpB-ed`N8$mceE=qD0(CoU4VraRuriciPyT=7BHsFh7~Q-;1vIsFVDp@u*2q++ zkzjB>U#K^{L-<>pOfX3lB8m~Yr2zzk9zm2S`b*OFrirUFt5R-mt}n^j0Rf@K-3oD+ ziC98TN?R2Wm0M4DuTSW&f5V%rWo)9OhCEHQAkhFADjhI`pG7cNQ(|4meT$GN;FItw zD(!5YOVuYEMBj4Q+7oRg4+cGD3~yp&hfWsl4qwzo4QSK{2RhvdW$EW!h4b~Wr72Be zE@%yM0>ClYA$>ZYx_AWrp%YSQu0E~=cyQZhjzZe)oYhDVoN%t;EN^R3yzbn<=TM*M z1Q~zdq8SPLR?UPtkQ21J_iUJm!p$_vpimt47`snv@oMs{OA(wiZX7u}l#!*e$0G9( zmF+aK*-H~~l`|zF$~hEm+D@p7{~^o{D<^Ub;Z^uqbYqFt7m3GJ6-bM6Ht$+7eJR*x zTdl|Pv?s(d+V+i?xwETot5T~~1tLDi(z?8ez#E&~ z53O?aL5{N3zFL)WH*GuB#=u#S^k zP2zfIYw^2wLrzl|o_>ov+cHejB@I_6=PjzT(azl#ZU82BXUuV%@06f=OEZ(;I~`-| zkCx{5Vur0WaJ*hv?F~xmm@XC#63c#OWRx^j)zX({ZW;o^mK@c~1>xAK_bRm8Xnhl8`-WsRy9tA5e{1hPO z@PrCCfXKk};so>Dtcq_FwR=WUCi&kT91{!DhmH65_gBMMx*zfy;yJ6|#T{pUZfeF8 zv*50k9T%U<$b!4LfpGqg5lL`h-o(jM>xnmRoaOaI8%&4$cJgHLsnW?NH=%{uJ*vdT zsNSAyXm$@Oe9`%%cc4oJZGKy#h37bC8-8UgEiWp4Zx5Lm;P!&m?IM`=BN=&!$$V>J zw}Y#m8lVU^v9(G6fQ&ehk-)C37jK)DFnFLesMNveTMb@EZWjLgyUZ!Af>~llNlw>+ z>7xf3jsq%%Zh9Y6cEE7(&0gOWI+1bqh}%4Do{zk2cW<-=OHbP=ET=o_$4_zHuw}5b zOO6r-;t@IN^UjY1GXQ8S1#M@kQ5D7G~{VqrGrswsX7RrKzg^7Vpn=oKk6&;qEKT5NIW?gRHduW6bsrO;4}WZGuO?d}8zdVrWNp}zf2)}u#~om#ScDr1!XtDS{I^kJT18WDqc zW65v!#G&+&k-nz>4zv?a%286onuPnbF8US6qxD&|jZ7g?P$~-QH1KJ-koWm~)#A}j z7_wA?!@z2O?@1&gCbKOi^O9UO3%p{Ef5wiVh%i;O&w$;(Wx&cj@P<1`>@RFan|SwJ zoR*G~FR6p3Ek$!j2dTJJY7VqCSlvo*wF%&gqvsZC89B(G)cf~*CIsiUd*J&)PZa$w z4_(CXRoawUEmOCz9utKOL*)#DE<0&)iV9KfDa^K#j(C>3bB5{GkE`UYf^?6j8N`am zKfVH8T$D$mJrUD#QdMqB_FGLV@0fS(kRs%J+{ZfZto7sf42{TFrG8?GnAWVCcR=T% z-_^>eASpd^vs+%+pb&C%E8p1$evBepRW8rN~vtCequwe`h=58t$;knp84$Jvr#ZzCj(el}C*BI?S! ziO)2wUi1C)pV17%9lwtCMQSPNn{fm%73lhm`xhh`0#S^)VgchF4Koo2S&M!MS0h0H z1gS*sA(mw3VtkhleZkkY^yyCQPW`g zxl-QH*vPoc4wwD9St&r_vg$|n!$!N9Mq=7fi)gl^CuIg&TtD7$ics!sU-FXe?0qnSN$-X`=-9q&jz4s=gfd0VmzeILWMBJd#LW91b|gP zB4V)%n1xJ)haE|BFO1ij!<#J!z0%X zTo@k?aT7RbMi^T{zTAMoYkM`OeX_HgKk)}0jQ^7>MT$!hdAtNS-~L1LS;r_mNR3=xsI6Sf9ECz`(v!W zXFEiP;{&vHemeKQFaALHql)ufDq$WaXd#QtA$ATX1%9ZXl&71}dQ}OT!!8b_Yvlmd zo-!`D$i8JZcaz>W}x;W-1&AmSH{Yl8%dZzr_;ZIam+vPv^` z9$V!4@Od_4z|RqGE_2eyR~w>}f?63W0c%s-xB8o%q!n4ldGAliN#)zhH;mv-sGiHu z!%%@ExxWlrZ$7D3r-wYpx~y5u76a4;b~YzfuJ|YmM;{78CXAuqjA|>jRriOe-6u|4 zOQ6Nyln}OSZb@dK4c7Xl?v89qW=j7?QKPTZDP{Ywl#qyeY%N>U`t^J$S-DHB!0t}N zZ7eazeW)=xMA;U!T;v@mA!6KJHBOh!K9WqL9_`$lxD}^wcH9hC`9D~d{{AS|Haj`0 z0nAXUlXXi(A@8)m7lGZb1|-L%%{KN}qh)f42LZ>%=#YW*Uaa|(@w(9ybEzN$RbCZ? zBgS8G0X4`5X(rZY@Y*+DdKv1;X+dZ{=0KPQ;Hx=E>HR^s5KBxCLMOfwlptXSSA`Oe z_UqS%mpdXcCJalLzF~{mt>L_|J{|N#S)5VjGr~(3X3oO_3yn2Tg}dV+KyKy3ZUqOw zfzGHVdj%^HqElcy;y`bS;hHkiiYjomujFp}&(M}ETjs#o0Ci%wX22cVbbfN{CO_fv z(X}JHG2jK%eCzl07^;!{m2$azbFe(td254B)U{L~B7guTRwH~HKe`Q_p{$p zV#{IQc)n0|u>0+VeQ2ix!^YU90aXpb`WOeZE+-?Ab(W~%YJZ_nw83qp742s&ZA_P= zlSo+n#S6a=cLYaG*o@@GlZ!N-D$K=R+-QB#qloF(rS|F43?W^6E`$Z6(>s~pG1)qJm6eU+tll3gmareccwPI9sBl7 zND!^`bZ{qcT={l+jb4mtz+l}i1QqwQ#nf%Hi%p&hFBrOB_(7)Y{IhiWc+(WN=^yMR z&}3g>9ELpUseQT<;T33%3L+h)#>=c^dJv@LDkw1uxF+l-G+nQ3TvLwT3*hTqYobUV zXQWD7U!_Snc|BM&&1MjDq!!arGGz=VeeVA(H)f#62VwA-K%#*L7)~S@BneQ5pO9?g zl2QTiswCK+wo3)&cIu7pZxqM;c-nxO4-4+qNFQks3(0kj$5w7ruSrn{{No>GntSZ4 zE`uOIjQIVYgCd#R~9I_VF74)Jvntr6X|y~AN<@E*4@ z{k`<>yO)usW$==NIR_G1$i+5+f-7nc!u%}Mrh2oquxb-f@+9O8Bw*M$mMN0v26>yy>!569g z70dj-29iSz71OrXriff1pzCbcEhr|)m_>M=s7dWm&5$B;t|6N^O+>FJ>H3!}MNzKG zu(P=@fC1NlyZN=_FT29+%8+V=MCdQ=dc$0nRO%)MY)vHTIf9MVe|72t&axwr7hW3Q zAh(w5Yl9ePf!DhsR@jS;AVKC*wNhX02CVJymxcXOF`}W%5o7XAn-b}{`1y9|sp~ZK zf`Ynh(p`J?*a|vi)XFbTcoXh9l(;fdU1@zRD<{fs%SQ-PG zXfrBpZ&v_;+<#!y+|F5QkpEB2p)CZrO4+kQRr}(;p&R}Sc7S}~!XW&ALKK9jj=1ps z{z;zEWS0+ZNjBE}$lgP}d7$9|YH2JfD`Hqzz{Syw@*Rr`huCz01>MdTU2i@6r_=gm z#%R=r!GGQpv7pA9L||UHjxhI$ZBXRBc1H^c=h9P26UPjHn_)*rhu2!1>6--jAevDI zPLAWlhxWg18!XKpAt#xx*G$F&kXUOcST(MywnjXJpj#AtEIN#Jonp_=DdRZ(0l9-E zqs+rdL=%)nW$Y6?rWHDYRsL4%ou+hIiC?h|%Sx}`b^s7{xOW*cV|Omlw~cU7H9VDQ zt^h$*n1C#a43_7%vF1qn0SG6M+C7v4qxA`h!b6vezgB#VMptvXON4Vc9T(@CuSsL%X(Lob)#t zvi0LUnlijT>YjItzf}puaxi%YN!dy7U-}Kzz&X{nh9w;_M8{Uvtbx&Do{5h!Pck}p zI1+HK3{B&i0T6OdWkERgmgg(Y@MPs8tN`|vmuC`;Xs{PB{_)o#RyJ0gUcBAjTJfvG z&C0AkVFE_{9-FY&?TD9RuE5`PN6&5Q_|F)H#4BM5#g($geSZJ96&PE_A8l+hbYB3# zKRSwX&lf8l+|$aDL0?Fg71z(dHms`^l#o+J7(X*__Zxu=q`T44r_6BCkLw3SS7Ork z!`%}#k*CnuwId1Hte*syB{A8XLiLHj_9}DBz(GAbu4s(YM9zMhxRZDc961DT3O({3 zb$?;(HTPo=b{urY|l_6D-0TjT>}4O?@I0EuTHH68fl|2xPx%gDJ2aDt5j_c1PHEQ$(L4YhQXCO-q*j7oWzwPmniAN=KvJI!_G<`V;YL_S^;-gd-YYu>AoKymXI= z*!$8YZmFt*UMdzZK~gH3$nFFZJ8z0{B2@Ftn(|250F{E<*V&f2N5K>8N9^{`E00?z z`kNjBObP5V)T4gWJ-F~z+MN{PjOtveOo^d3KACAs_^XHQT9M(Y0bzdTUzo40R?=|| zkDG2NNE?CmpDr22UUhVV&c>fus7bFNv2*ckM;T{Vz7zoWFL9qkKC2#^te=huwD|4y7r|YEGs?r?u-w!P7fQR( zoL?sotd28ip(D`yV0|sz2)bEaN8aFh2l#0F!o^qN(0mxnR7d;al2PT9W5}U}+xf_& z!J1IC+9UExUP;y@uq@S{ebJ}4lt^f<$kUmZcldH$FUN4w9EQ@~yi2#I1Tx@QCAlu6 zyPxsDcqj8acMHuLtKSjhLWueP_Dw%gPhmIGII=y@ocMT<#ZNmY;4(N3bdBn#kGDI| zib%Xfi%YBwX>aGXXL_onxrbDeAxeaQT8_CKhB5b_R5-!bQbG&j;5X^S`JpmWkP7LU zwhY}^0}NK!8*A@^K!O0}c=)u7n~OkOJp`aRWNXNQKT?UMb^I1`V$V|BE7p8(m1uIq zax1rP;wle~GZ!ZL*^IpW5!il3w&=l_=_(D%z8ojlCspNa(dhE^1ewsdjcI^EQwMYo zD6RBBAwJN-K12=`VNVN)jo4bvSfdkuF3jNIpW&+#V0xf6gK&Wo(xy>4stHPIj7V`o ziD|Mydx6OwkFY9}qKMy*6QKwh)>wkgWh$P3diXUj8_u=y3{a5;qK4RegELuwg<)E; z%)AU}r|FuojIv7?tJ`OPf~X(n0uwmd-BsC0h!2)xqDXM1Er55LZ8WdB&D^rMe6a))v4|d+N5P%_MseE^|YR%8w zheXgxr`94eEK8d&nqHJ9;Znb^Cd|0kuhGK{!M--I0Vi&Yt^Y&*ltofzZooq(_;+_5 zoixr+q!>1U81RN_1Sgeily_s`Ba(L9k^XMnuayj zcQV0th|@XU;vnf!c}>a5(~b60D2~S~?|0~(=Gwj{zeTliP_iCLLS%P(IQn(>r}5iV z+E^)~Q){>)&A9SV`7Y2Dk(?zMTmnfO+v)21yd43(Td?b2!%tw^%EjZHxAx*-9|>Am z+S2Zb%){9>d02lT>L_F!CP;7jbt9kBmCiO`JNK4u0mcyG2bu-w!jm>6jrlBcAqHR5whd<-}#tCnD^Ole@EX_ z4zgfcSiUCKcX+G6r(&TT96Y{6F7tJlRo-QwX(bg8W%xv9!vA;ZuX_az>g*KCZ@1&! zQXcYFLEvn)$2xn7itdfpx=a8{@83qD5Rpq1`#lCisi}gouk%TxZaM8+Oip8bdsrw9 zhkiL>Aov79zBX;cIUkMv3@FBS9_Mw zBqwDw z!>hxWgGYO;Q9>Y_Z(t4jc}{%nAXl6ohHk0OA-dc_7cSL`CqK)|@dn*1%2(QC$gOL3 zzVxlvqdDWMAQ+pn2rxpvF!ODXd!3w}Kz=jA9_p&`(Kjb6I}#mjR7C8DyoZ?vL}*DC zA~OB~V{B-nrt!=9{%EoX`1}*Qxni{&9tK~>t0*`p7T@{9< zAxRn%FN8g%WgZHAb_=M(S0E9`;Kd_`aJlag&xfWB@pQyy?O^?!{0WmpQQhr-*~Zq` zR9)AbI;Rry>aJly%dJYkW_&A}jyqE(wDuU^tR+nIqUo6P6*k!4f&KTFHKESg*ZQ#c z-+N<_bNk`gukPG}AxX_#X2ll%)`Y3MTAt2#zfGYMkG=pcPUN{vu`lHT+*=si0S`|- zMBQ0Rz7NK(x-rHR0GvU%H-_3aet}FBz&!0%g|^wR*Fo}A$D}lee{bxCJDrTdY8do& zBS|l#?%WltJFaj~2Jo^VH@W@t9+ngw)IcL3+#zz}dPIXGH< zPhRl@kC)Xi@6bJnQQ&n2M`>#mQ$C!>;xyI6M;lod{xF{C70jJ){(qB8pD)$p_^ zlwU0ujJB$nhz#wImgKkyRnv6}Q6rx$LhrKJ1Q}2FcZt10?VUY0u+ethI%r{J{o0SS z=QD1Fs0dBLpoR%*224>lSI2nP;uhYR}5 z{xVQBFnIl=Ld5YAl|Z5uPO058?4(187Hk}JPDir5=sW4tg>Qml19Mz|g`!D!h~6$B zIAxHG8WVb|&YdgkJ0&=>BcDxr{--2`hgcV8IMk;s@eZl^Arcs1og(1#%3Zz{Sd+_S z7yzl+*c>gb=(08?$z+oH*({JCG<qiGWK1-Onjrfetr8*Hy@K7QAbvC;e0#0FC ze*&#?7yjp(iX5$0N^7_oYdDULyq=UqTkH^>fnO~pQ&M`$#sX8nvL9ZsqkFEhEf$(i zyAOm>eg(q5&RQ%@M^FeCUz4gvCNbBewPUCMcqdO-3KNhjCS6JxfwG2YQWTn11w&c{ z_KJT<0wNy#-dBOe1WJXlj;7EmDk+KXZ+v;=sji5=V|uzFOVgbosjT4xa!j4*G4vzh zvNcei(~JkCrUaG)D$~s=KE?3u9S9q+rfrPihL-Jqo?Olj`tu(24vx(J{H(90NNmv~ zG=cR;3DqN^}Z!teGN{y~0OY9*#s6#?SHfm}%QFUOGX zOdLCWA#FlFY|*C#N%XIi3-s9HE}@V|LszGpEiC(ZDo8&i+Qs*I|E{ zy>PBtEFH1+-0u}T;N?FYBgM*|6mbzS1x6w&cp)CZ4zJg>Q>g}R!Uu>GU`C^LVqD14 z;e8rk=J4TCRB|X&aQ(qsre97wodXAqT>6K3;M-{|RV%6ut5A2RZ%&rDfGJ;OoU-Fh z>*=khSr{n-bn595Get{k?{ML2dykbL8rv7fDOd+gME++@{V$_hF_2<%95D#N7ub7B z;g6Y74E7HpTq9DrE5&mMEB!9UA+L|T?Yrd4Z_hdAuDY7J4DFc46Odke!C#UJ(#+w0oE5V#;QElMb zy?_AH%g}N0UXw?V5#gRJVHcqttzp#Wj+kG?#;^bj1FoV*`L*D^C4yhASTW!lyBjjp z%?c}s4*9aP;{u`u{ulD6i(&Vjs8jsiWIrsB*M&Y{s2a5X9V83SVlta`qFrn0C5M6ar4b`YR z{%J}-cg^lsfEW72_NOQW=OI2>buV<6HUN_9rVj89oy-uD4#;MjQ5>cy_zgcfk^(I0!g zY3mLyHzTQtc~s*rBszY!NGL+uVy$U|&%s<0IIQ*t+*+o$n03s0Q*s{{Tk-jp5FVnH z0%PW)9!vHi0GBIEWVT(4 zqsvkw^iE%=bq7Dw%NtT}N{$cof@2-E8Vi;{c?@U;?!@#m3yo|n?7zz&+m^|GGsqu}>kp8&K9=|E#D{8= znX^Fi2cFiigE30Tp|Qd2Q4qAZ(u)2E%qi(u`2O4nrj>#HgbjS%a~1HR1$xHH_5xFZ zLz~)ZKOrHB_AwCBx-<@HS{57Y8V`_nK+FUhkZ>5Yp0Lyt_^qW`T%s5`*xb9pjC9n; z%@W0$c(|6#ihKtuS|hIJV+CTQ7EbwfTfW3|A%d%fZyza`gd%Sii)%2qKz>=%w1`tg zWeZbp@yW-I=HWmJk@H+l=Io;UGL{+=xUSiB3Db#3V)7Ss( zjRmn=e>Q7%2`z(l8H+XBR()ZjaK+BlztXuTxii>9364J{5s*=e>f%Ksb0vuVqK0rd zNR9S|3kVXCB7G~7M1EbR!Ai05s_RH)k48ybFI&}rxxYcSSS*nq0|)r^ao{gU99yiD z4O+jQLzMvJH$O8lr1G3OT3I!iDO&c^>mOeGzTb>*gO6Ow{76D<%6h^cP$_+>p4b+2 z=+$BtFG?wtT%t!}ZR<~!0(!AkGI=b};i`5wX38%nQJrrwf~esS*hOHE#UZm4fZKv! zujEFLTtMy(fCcJC0?)8Re3KvO&|aIRddxK63FVfG?sBNiON-|T2~-sRPW!mx(*D@$ zbISnHO4ZGleDe!Vr2~1C+BT=j8ChhU zZR6ZQ@~D!XNRbFXH$#0O`znu{z$|5{1CV6|KlhS`xBvhE0Y5^W79Ee>2`t%W(+#15 zpU7|#7$)QYv;nLRO>#wd`Y3R5K8;ZNKE;EJSq4kRN!s}dH+GSC&NNrJg(h&*j?+fW z#fV!yO;MQln6XLR&=&=n-#F2rNliW}LMO>a%hQpQT~MMZ0Qf$x`F3U1jz0)bftFQL zPtYkRl(s;%1m>mt0EoG~zyl)}X*z9M-t<);L{N=U5Qjns_z2E>pCeP*S&m0YnC%HP z9TOyrBf&m%RMhK3jp|@55i=#P_)1juJFcTE*!+x+5$4eJif8{!mllXj`;XmXU`?@# z+3dBle>gDnhjgp17Ik0ZY0|8s*m$vxJc`r?tz#^&3kFBOHssOE<5j}6F@re>H% zE%a&-LMadZ8T5J)Bf|>TJcT+nky`|&Q7~+5U{TWYz2vDp>ho&@d}ldwXb6m}xUQ}) zZjX)yfWD^(rsuR+_X4>U7PNI5Iymxosi0K(cEl|yP%`^4wadWyX?zMV%j1uIKH#KZ z&Lw*DHIIo}#t)$aBn~)IgC7mBkB}0dTnAC{K;f{w1Za6=IsnAQ1_)*<{s!qJ>e3*! zp#q*u)!qAV>o0O{F#648rYG`b zIt3be=5za;zK#;r!FV-tFH_KqeXe>GgD$UNlAqbyMTihkA6l3kQieUU1Nfi{9 z(4r+#VC%NE`jX1SeNEa39%jIj3@hiFu>ez2NESdhBIB&qsaoli;`Mp0_k;qwek?r< z3^v0F+Vh$DGMX+nsm;oM;!}+NhE<^aGvOwij2~=oSwc1oZpJ7?7Yyfmy zSEiDZnH(5lw{mEnfA$LJcH-l(k-g%1g|q`527iDUqfS?Ll->>*jVLawqCPQQXHawE zH~v$nWrTz#O{qUixJ_<~@zoHuemciXEYFZGmpR-{ditl=@<#N|q7T^uW=fQC(UaH( z!h>M{P#{n)MWm!@g7!0Qg7wM{yjT_#b8F@s!wvQbWGv3BIVJq?T28l?3cF`Sd7+rf zeYQcP1)dR=W6X$Rq;Voh4vm<}xyK0&+{3iI!e>oaU(SB}p#TdG5=tAgkc%6$25i25rT856SzO)zG-{Yn9#R%g~As09B65-$7H^f-kEBVUpvU5 zpk0wgJVMTjc=1$o7yv*(zrU$7cd?^uBC)Z|GA0m!(sa9nUUe{?S>2GQcrm8RVIdrq z&I6u0a<8L0`BWgzGP-T{;HVokvU`6R6$6xMIl;DPkO8KF93~`*i)GL?qQQG}%YgB# zKSdEHYZ?m&bd^non~#*?6s@2<>~R1w$g!NUvE;1CM|4j&=0BLBfOhvUBpTX$({+?jc2H|V$sR2|L zzeQS3y(AmGlPr&8G=tS|V{Q>$Zw$~QzsXwonQDn8TQ^TUohaWGC8y|E9O`d-qS|muF)pulktoKb<^JH5 zI>&E+KNZ^C&zb-|o3CJn<+>taXvu7W9{D-)8pp|$nHO&(3!nefJ4hW`SJjudYK5|W zFk|U2e7T)AP1IM|^noST{TL!gfk1AMqNwg)r^mU3nRqQf4ki1mtKJgEcy^HIHL&qk zH5kj+{E@QjLK%J(wW&z}$f=jDn_-}7y_&!bvfaryqL!7=;;Z({8wqX+PtV86(D|lkvFZK|xbJ+kO~#uoLQDB5`}|At)@MP7R!NR!#Am2c-83NXK_eodqq7uWAJI)EYeR4+y@c?INySx_;Fwd134rfDCfb^60^ zRJ%@i;}o#Xp2H|xYL??jr&`DjC*Y|eqfRR~amxgd%c??J(PePv zQv3tUP1*FluR}y$8N5TL2%7@@8}}Gi5AD++Nbf>NDIul2r6rf{ig6=|`uMSIq#`mG z!YB|K$I5i5Q?Xi72db2;pKqYlmtvohuis9(YGCs@RoT1^e89kY6QgOx&H8R_bWf~0 z!BNI~g@ywonMn5*fU(Y}HkaPHgH+PJa_uBg@2)PJQhgdky_0Dp!7y#Xta!e6{~Yw3 zw`q1fn4XV4@(HetFfL}r)!mYKpT^^E$YC_iA1%oUY;bIalb;=!jfvQ{Sv;U}*t4Mc zA-7JSi{@sA)@H4<@PLI-oc5gWA)Te2rT775Z1Z&BJGG`r-?tfOTaCw)@utX9R!NeP zhgT-$h8s9eDx3Sk$T)rc*^H2aC;-UEC2t{IF!>cu)&1&g5D7oQ6r%IiUlYOL>#66B zY>IasdCusDp^frC?sNnpUEkyFJW-=B?Gd>87@l+X zK7-XKR_qvrj9w8wN&)MBc1l)L1c#h0s-xXJ2)6p?wG-}Q5(0(9bWUu$bp&ZKKvF}* z^!_{7;y2_608+e;87pd2xicPb@1pG~2J7YLTxbi-;0^he)C+3qm&Gb@*JYk|5*OqaF_@uwJEOhQ4+#E=h%k#Y5y>{1Y4J zuxNjp3jZR!M3gd=@5Ex@1fx<8T7pozOXN7ZzN1B>K=tVq{>f|Gsk@)abv30D!~*sR z08ahc?e4a&p-VjI@CPfik575ypFGi-5nrBn=iDF%&dKx%6jCS8UqeJixF7g)bpXj% z{6xWcLJwJU{$3+u=^>3KIIe=Pvd+-wF$zH?5~JTwwj#wUw1EFboBKYQQw+xeLXc z0^e=i?DNfHx>h&9EJQuEpZ8{9L0Ayu#$~cI2hSZ>a%m15=&jlaV3Mr=v64h;VA{Ja z$q!@24?J<>DeU%E!5rz^ovCI|A|icpvY!c~03HzWu8TNrjwEtqcNw`^xC*yDw272> z?a^$07wZ%Y?w~8wOrn(+Yl(xe;KI#IbV5TlU890<))QS@qLL$QLmp}2shPL8pDb|Z zC<}6E{pEakgF{sKaZ+|ZX;g;d!8?b%p?=^?x%(NxNR9c2k2q??z*gIZniP41VIQ{S z;h@9<C^a5Z(xocIODwgejem1I?&XC)OOfZ#t-=y`y7cCsyWeLs@Pw9llbjE{ zz&;AhMmGyY*%UbL&qRTxB-=T1>%~QLrAh33x2QDTMulDwIbfhyBzCF?|L zeEi)x`yu!ogBb#)^H4%*58x6erOwbdubBHxX4JK8Bnm_+FeZ2EKX9oEiXEz`*`TF*QgX%s$M{(mZQi5j{S}ehf^WEST3=N4`+rmrO z`XvCG4WI7S6|TQ<&Jxn^dSI3|qwmebiYx7X<#9&kc{}Wu9k1=)CzJ$;>sP~Op4faUC_vs6B0PEEdzQUYv=?piKRYJ}&5G8zWeJV0V z^moC}McmBwtmJ^@g_;+hR6>I_(lzs~4TrqSBTx}FyHkBsdgmfVKa`;SgGtNF@D*^3 z{1Mjcq?qRzS4w!@8lh)PFv6w7PBRP(MCDzbrwhdiIhT{ux%^Fc<2 z-wCKGN)nRd45`?+Xo0v`mQmG6M}Avm`@xt7kiQ#Qw>t@ml)rmF{NHlK-4u_gYMDwvt7giJ`$)_H6)Kq`ah``Le%F1T=s^245g*Ss*NRqpr_7N zOh_wi<>EF~stI6)|2@OPKw}1Z@oX(KAUk8}He-Q-L7Ur>{Vkj8cwV&_F6Nnk$^Ciy zTOrxA81>Lby8-X4X04uHG#Zgmvw*t2b6j;~6m9o|KJ!x&^0C>4uX=pgp25Ehh!(W; zjoCX!uEFRxRQLBaaCMGNBqM$skUpL}~DBbnV!A6zt+cKaTy!d50xst1}Xxr@J9U$0;h|}X1 z`k9m;@FOV^J!wSs$r7+jRK1x|orpl7ZW=#r{Pu2sKz)?E^I8ox#>WPq%63$cztT8= zr5fs*2t7*&qF5cUrvBYE=SH-1^pC0!5+O3m76&mYk4-&=ny`e+)mZ>NGuD`8-B^z* zT2QSq6PlpE0XC-<)K~Iq@aYdzwtT{SNIFZi4CkU+A7UVP#Yc zT5dW$vt~{n@`05k$oKIzc%+~$-hL*chd&cBkyDhAMaO7|zvB^%@7}dy#@AhiDixMB z@_PC%#NXfajwD`iT%AU)ZAvu2m3>Ubmkt7+L-dI>TZ%%6lSx=GgBzc;>8qgy799bihpY0o@st4v=XpiZ79LSh z#rGF;!@+@T376P8%mywbEdES848yg0t&HJ;w9+`wo?_7cY8DUvdpxjLNzS}R8V{-`~0ThjnX5b4R08&>V521y@jkE4x~3Y`qJ+mqOQIoMz*2@QKH zcE!X;(!?;K#Kp!gk?o?+$E*RRX`dSiF;y_FOO={!YK+4Hl)3}{RS9OLASPCf<++>8 zF1cDhm^xaAf=BCOfE)>{1FI0hb5(x#@G=b84;!}A2G~6M)<<-BOV~){0F!V<8h;@j zg~*4@zZl>MMNn48pUOFrO&#DJOp)pK$p^Y64I8`Fx&+I8SB#mr$Q!{bBR8ykeXHwF z_)+o|gT^ckm`4jhi*KX0T8RIXjt~%6+W{Zja*R>$Z@U}_`|bnx9Hh||!znP~MU3D5 zPXPzP;uGe-3G;QY{z#EOequX>4~Y>M5a?Z8rRL~<=$ z0Y`a%2s-|z0$?YhCUDibqQc3Mq-#0sEbrd0+_nUNGdp#rx{M6`oytD2CfyQ6M`-_c ziGD)hhboBc_f>>r_55;GPrgKZe)+)ur{ulQe#Eu(TpOs7I>6qZYQR4I`P)JUsrC0Y zuCD@o)ejmaJyp=a9R=!c4*bQvr!lCH5kG|8^#f5*J9CFLY$_VY&O&j@bEauE5xhGj zO{N&Ha{^Mr3_3&e?0r+0?o3DbF=KJ{?jx_#0ZI|Y4hm%@FqCIK34L`jhhgz)-|$Z3 zMpUVK{tV(ziz=x#xHX?Ftj<`L{R;dqoo!FkF8vounlG*XjK;8P2~>74ySqWf;8fi% z^fpG#ysXysOftr&e}>6W#YH}5I8(HnlqP967%sYa<#uX-4&Vu#_XWDRhZ&?i(ta@} zuH3mJy2vuQ?}qWYpclPvQya7D&}y@!vv!GwscHp5jJ#ff|2R3qwOGfFx{+h&DXv^i znBTzC`i*m#x=>n%eq1QS#&YLgYnTuU=L}8w7Ock6@0R01rMwcq!gM1M)gKS+A85>nnMo_7BYB{R7RUmI=Nk`sdUP(+t1O;~YzwzY&+XjO=wmYoFy1-NeLlckWOVjARfm?*G&oz zvyI5g4OVN?XD42E>$-t$NtKTgT4dQ&r+Qsye(7+V1lzOWVC=NcOpHpkig4vyG=r5E zOVU@s>N!Cn+(}S}lNHDm&`*I^n`a$bJD!NN4VQ}+&V0sMB$RT~R*<`|Fb_R>>r`O| zeOT1rw2RC();P8aB8wDw9C>Tp1Sb#QRkILuO)AEWgg%AWxM?^1Ttl*7P0@ufD~GKyCCIkljdIvNHOyfW>^&VCPAxG$-4`(ktp=lLaOXDyPJMr?*Gs z2H`r`_Y!^R98S}HUj@uRaA~xb^^$H@7gVY%2VD3HIV}3$sr*Xjb8#&~KJN1u#7PSN zmBsNqr+hrA6!s*I?H-lwT$q$+lJoW24DLLp@%HvA`bH2HTYyPSL4=5L0_n|4n$Lt# z7oba61sn1r*1b0WIU8@xiItTmz!@)t6}n*SH(%L?QM$!ev{^+88H4L4A>0o6o?z4Y zsiY)#{qI{Ex3k}{>D!a$PSJKYPtgVR$2@<8VwQLy;+b_yNB+AVd_ zJOQuK6uZWt6j;PS`)fy1TelHm-%xXp6adM)(7>r18Bt@a@j}X4NVDf94l=2*Y)ol0 z!1*A=u6(P`d_+1YPb0AZEztIY>z=twk?qHej< zuCLq?S-jVCjW(TYLKu@u@=oB3rps$FBBX<|LkE5^@77G$mJ}wF>t!@4QR&xgYULTR z6?qh&M3`z~dPTJ3UsriX*b)3Obf9e%o>5*GwTkF~2>IO6Le4O|kV zm^j2t$D=W?>m1M|c6=QeHTtadW<|$Q**2D$WODSuav-R7iSRn^hr5fqxv&N3hV}z@AL<^i)xa!xPJHb@g?! z!eP47qOxv0OP+(KJ7JAEHu_Q<1RNn2${fc}-7r3b4f!qJl1nhn==M5(tBNMJcO_I_ zSx&mc?sFTWO(MH6-a&rskZ>~t3kO>tKmY(VgoSHVao*c}WT0ATx+EhA27mwn00Tao zHC977E%ABm>p!(rhO^Pl>;j_F-s?H=IzqxRd;bZt3t=hRd6ia`^> z&;vRJ?5Ac-78cLoHpJa1u6`AE)jK_0y6w^B<1LhZgCZXY_& zUV-Ca&rjy3t^2K}105gK@xUs7mPFxSJ}tIH_O&0Te@h_Hjb77|KmzKjsxYDjs*Gy2 zBj4phE`V4K1H{LI)`ba3#n?|W?()SovNIg5ayS86LqnbAT+swxlwvXF!7`CEEkVJ} z=MC_H=cu-sYabhoI;qvA5LWZZBwHRUi&A2;$fuw1$u3`KGlZxg1C`)yA+Z)ocmt9~ z-lcw6g8rqw%Pg@=0a9=*4FMahdVtMa__;@#n@f6G{CVhHK1H1r8b!tYCIjTm+caLb~$=%)3mi=PxW0^-$ON;&3l0v}HN$sobo+x^k@*Li_hp2H*f84;8i z$&-$>^88PQ$X1DoP4U3pAd5CqR;`DD{SC~o(R3hx ze*qxrgr5v-WdU}>U9R^eP1FmpCFN)h!$dmfG1g!S_!wbdNNPE=7DCK`)iMCsR_T-X zm7IP#fyL1!u~LkDTEvW4)-pi+tM`=L!W63fxEc>kj>kVD2uv{AMw9$@)=H)*?0g;R z^`E>y^rs6`7C6f{AF|tgMWPZ^S0Ld@f@tg!9Vipv;b{*A$3Zsf9g~L zht+LvUZ72hxNT%a0CCe-(qGQ0o}3ld0`&o#T@sUlLIyg4z_Qo=UtJ}pzaEjPQvDbv zQ(0NJ2B9Bxim|SZjb*s%lkDs_M~1dNvYqUo1k3Ynq&XSsahIx}J137?Y z%-e>QIBGmh6Ar%f+X%P}No>$ddHcc+g=H94Xn!t9c}8_qu7)&)E3=LZUZ<1YhYE{Y4LMC4Q4;ND?<625Eb zcgOxkbk2%C1fH7^5xV^m6r;By{x7@sW~RHp7x_9X&Du)+E4p!Wo8{onEr+15sk zbc6ULv?xG}Qi$WMtvY@hS3FhCN~C#^4Lxg0bG~_X_)|wXPgxcTt4Qp61l4t%R=ID{Lvu@P}^7t}yQY@uuqzM3aXzzEdK%o-rH3q_K(4!hs@5gX9 z@oDVff&eH`Ir#90Fn&q)9`;0x=NK3JeLRSp&t=A@@*ub{1f%3io~0w7$1jN=N7FQW zBMPb1h+o|^fb{7KNYC@hFdZ!>)s@qUBTN$yAf8T-z+64CYr=bL}bm&yynsG^!DN+p9U*_tF3H z0AV$imvu(yO(cy|&=&R!%y!xiLfp zVounp!0F(u9(Gfv4)a4xFkzeGqej>SI6bp`caGSc6o4#!=J^^QAiN+Cp4RVx7BY;5 zdn-CRDE(ShG0S>dSWp@;oj= zgA4n$_yf;%mt(sFxoA`#%Ymm!ue!yVQGNNp;#vvu%z%jD&QcUJ~HPP zY2PyH1fp$OIZ`Yp5LF}>PQwuIgKb$2NOtons(a*Y66ug+Hu6e^eFn&5!$#A4`Yngz zh!X!lML5{A@ms+N>~|@V0d?AwT^|w@OQ)7XoNP=B zgNFBF#;RB&9Bz(rdLPpDwzs9&b|*iX$(xTDhii*zXQm0KPcLLGFi6_+drtkazd@gp zKF3n5EqaO`&-~K(OGM`X;WZsk1y{8K--8tO-(vR&{f+a2gLtK&PeM(>l#WfH9NYHz z;Hbz%KQ2Dq`z9y-c?mL07J?m@Kfbmz8XcG^6<26I2jJm>qF&(-PlxH+g1&SpY%d13 zfK`2>dqn}l0Pa<4hLWH<*qZgQ3F>0~F!6T_bw;UUU8vnb}S-G7SnEiN}@MdgKAEn>R z$h=@{$xUds-Oml({xo&0Jr2Lp2MuujwP5gCaQqmcB4}>NuQ~Nu0Nq9*u41BFBf65X zW{X~)EeN{yn-e208kunkAFX7 z$-Z;`_&+-{(+~4Dsjl0S^x)E%QmaNmf!OkMr)kPi)#o(ZOiKZK8u#g1X=E6M@a@9U z%~EMOGU_B9bO|Nl6p2rtN{E_*BB@cxc~Jr>-#i>iCShcvSG)xa!CCYD?u=hv5%#~R zWV?H>BkS0@F=Z7cAha)u>3I@EW0=jF@^h%)xsDB3A?I8}RaZqOp|~qCbQCy%KZd8s z(U|#u$hrKC$#WtpLHdAvdJ%-SxxlMb*7x=B7{5$5BUzv@}pHYyIVvj4ZyTjWw*CG9Px~k zsK&&ngy6T|%bp%%Im0wBJ>SI`Tgf34SLQ$GU+fOxTOc%=7RcMZ8-aDAEnJs!j+Z^( zgtK>s8+r>u(1)|vhzSAqnEi7SY#~PAiCJP?@9r4HgES%lm}XSjETh0zyPa(*{aKxA zO5jmVruBdD*If+P-XC%(s&P1IZdy3HEt-HF@Gyz@wYm!SHaJlObPYXY44EcfLHWI` zkyM8R-{8h&BVW`D<{+U&1&N)W4-CKLw>XiT4{g9@w&9@0c$1WIV45v&dG~2|P9!DTw9@J` zN2|g_veQj&T~ARv3s#y!`1(KcJJ`-9e+D%mrKn~0hStN9fZGAxnoER+U(cfCKLj>M zHRFifE`HEQ-WVaKDbTKJ_;MOKjxDzoFPf(7a3D*HnTSwCa<dy$~{47H)At5=-S57|Ovme4Lu~y;?HT3;j@<9O`DilUx{OYRr z$Ab^Sv+smwliOH))tv8>K>ilxO2C+_TD8sbmayS(C?5d3=mpHeenv$xdi@%#;#|Wh zy~UH;3|NRzCRm#ihyu7f8E*(j*9^ADIOcv zRy*5gFAt*rMkk6y&6L<+lw4skAw9}ma>b0sD+MbKe^3un?bggVU->FzbTAl2f8^?j zasDMtbs-YDA&a=6(t2r9n5KW+X?|q+aV_sd7Q)%|J}=^1BhZ{zi27=eMwGJ)p-rja z#Db%k?ay}Mg8r-TvpKh2>TMLhb$gx1WdlQAS_4_Z#CFtD|si1E~9=6Vem>fj6D6W!~$&?cq) zC78LRBKmF$-)+kplV##>g;|Te0UoHnn?jtp`QPb7FIr~6-B#kG+CqU7ELeX&s~q|u zbZX+VgPLCZmHd_ci=qZjhqZ3w8jkQB?dzZO{Y3=6@O_v~Rk!yg~>Nk97ya3(7iWgT+Y!On=uGDbbW{UP>=URy%`U-#`&1BN3LG zi1HckO6!ub4#r!tv5)$YaNo~QDV)zti+|=}_+v8~HZN(T}zJVn?b86ERJ1is1cOn++ICk zo<1-wAg!*Io(Tp3!Xo`j@~5{oEA;oC(Kia$;07J|Zq&Vdi*jOgn-Zya+yB|$l zJH)UlryOsk*H}8%j9}&1P!8z^KmnMRuPY6^5dMjd(hm8!P)e(km-m#t7~$(?T=OgU zs4VPdP533#!X!*Vg5HAd+@F};p;kdw2EGx~-wEi^@8?ChtlybqNAP&c3Kq|ls?QHT z??_$ImBV(Hx%!c*t$3nX#t^cOo2vOCs4weQWG;Yj5^`s%l6n<;JBSJj?;JaMPywE< zd@=(I4NFTbq~n$*xH9XH+tpTQTG-9aHWuM@xp&Y)=-I1hInv4lmwp@x}I zb22;zcS@mQZ4#c0;1Zd9zDq4RS!JGdDqoFeM9Dqz4v8bwi%K+%s8D&vKszEvn1w4c zPr4C@p*+)%{CQy{-0w=`IE_{-6E)t+$`BYNG-$-OLEQ?@J3jm9HP?s+#v>)$Bfw3> z(e!+=AzI7WTaZ*)QfJ&k+7OlK&|OkJdJI)_Bv3i7rj$)8ZkXm5TP*$y_OF#jF1BI_ z99lmm3rTB-JAsn84z(I*y)*3T*B+FkthnlMB-c4SlDG|h7o^{4A3%L)PwdnHu+FqA z(-$E{RYGEgLQ_haG>|g<_>kOnFgY2muD9hUsi;j_#ZyS{i(!^RTN1Uu z>2YRR1{P9F3BrV(vPFGxN79ENE!2L$1_`$;9&Wnw^QFeAvzxM0m$|?tM@kSRAiBy@ zj}S5npi3@$LaE|M?DUCh5J=r&;K`;8;pwi+63E=`3d9Qu7yi*ndh1lkyc`XRX-$v1 zb@Yady1(kP1!FOOxA80p>hhc~3x+ueS{y(z4J$pNnvs~!%GwRdS<4KN)HMKbjO~5r z#C8K!1I{bvGbR;d5GIVL21&;^wID`YUg&29in*V#SWL9WYqEZA94EB`y7PWzgCq6_ zn|%FkLF2z0Z-v4L(fN%H*lxHlY}tyg$M{yCo5^l>;4hN^wxGwv7waUJe9Y8MQ^t>u zy2-qo42tLFhSw!_$p+}fKyo1|pVxC0!DXpLxPDj8r-1Yy4~h0Cn%Jk)j{O$EOXM-2YmeBk)q*iM*9C>ACZzI@ZDMFT)L*{X6@LE3VgKbyniYlpc z&o@KjL>)npn(3)&Og175kZVFD5~d2;qd0!v zQB+)Ct8zyOqo%biPb5q1q;{W2h2pn7-%H%3tzkom9!GcRpi{A%B# z(X{7<^xteDcu1}e9Gq!&Ay@HcEr%4%1<+kn2@XJ`=PqoWgJ{CeMZQFOvsj*l`jDw(QjII`0W9gB_c`dNnIoyd$+`B(^+}y&rU<10x!7Oev8b-aAUd`w&(RglmqsT6GuWdQs_}a?KGepW zQLQ`El8wq zRi8eD)O0Qjqm9^cpr=|S0fl+9j{av$M6<`di_C5LW%^RBGHt{qWYCfuG#mcjIwdAX zh&2$Kad@CX(1hDcG;Y0l-puz2hN6Llby%ZliP;RfYm+o5>D@JjjC4Tkb${c9&5Q2N z+|aoNN$I>zsx3JZ8II|RgUaa>pw8pzK=ZoQ2{bAO-tdjQ20#J+79?@=f!a*A_f=Zr zR1GaEbithgCEoG-J8|4yrvf%8MnW>p`AJQ7`_lX=oz^Y`s_|W(&-DL}%xjKnMyG0q zZpKB*j_Z{t`FB3XY`7fi9VIUg4OPjr9}iDsyUF951Jj4t%Um$dN;jiwu8|H}G#%arrM>Vh%6_D+O6dTUWdhZ<8Q1^?i| zO(>H34opY(UBSre)%aAD$c2HKC68?aNG~_qagM+&U_(L@19d48M?}(yHYr{MXrk_N z-KYJf0?sUIj|FtkE0ulo28I29>Z6>6VVo>kCpx_en(B5qf>DtiMNO0Xb-*A*(8)g( zu#%h}_)vi>M`e%dnK;7;a($ z+0r~)!?9cs@FWw4i``J^E7t)P27Lqv6O_3vM{?m=gV=rW)B#VgNAhIDFLqdRtq*N= zc0g*R89O}v?kcW$%%8q~69-n+SI*qo^8fPvDJzt49GS^*Y`V2PQfQ!nL*&UOJoKmG zG!F)wFyC1i=${1+DNhrWeK6Y4>pLsIokYIE$bTCGa3i(soj;G>0UK{!LReR`qMH)~ z3YQ>v*I_R3!%n)#4j5l34+0^hXDUo~j$`E@KVM+)_q&}A3p?BuN;R#M5ry3?lgDV8 z<#P%m3~{)~mvbn@6jh*awXexu!1RAS7xm4-)tCc*x5LlLEnOSn=5SYe1^7G(`6jT4 zl`$I6W^@NFrq>!p*9;q3##1GYjBb6pm;G}V(k^O*OTKD@(2jK19NEyLNQKvFF1NG6>hw8GF9-j% zW|kpHgs&{%Y(4a63I~=Tc-U#VQ!p?2D5dM-IZiM`xRTz-#kZm`pjXrOn{=;y2ov^t zu$L;lW`hltU6C3@EI%-nO$c_=)9Je(*AR{kW+N`KD|sd5Y*lP$E^|~6@vz$M?f>vQ zD)*Gw%-Z!xq)YC4$S%~~h)n-Yhx0BbnuzvrZ=!%*&=pY_bb_FB6ia>egNaReDh~yA*EKUQk6elt*OBr4H#r1k! zTSQFRq``qVuz%TILqqrqeuDa_n6c92JEx>UdPZ)w5b6i@Ud)sbx28RcH3D}gx#n&> zcwF3e9L96ouwsdQzaUIYXuyf}B{#2odT+u-h^P_6uM9||rJ{Vzwk|}8as_`h31Ns> z30L6V4%O%8l5qgfG(*& zuW7KC^t8!Uhjis$kBTU$6jQi0SCf*sJFTq-AuFIRDYFh7btI5nL4S}Pm{I3sVga?v zKdaq8_ZmIK|0o|7{7_!-#2{$~f%;A1XdK=h*6vOP1vwhTSvEDBr@{`>?n2yblvCNI zx;E?4Cm`Wd|8K?LKokf4>K zI4@}23#(#{`QUjWY)1v{352hTZfO`G1n|@SOw=D#xnQzNl}p`iiwOUmmHZhv^&phc zieI7j$VEyh8$H|yH%f=8JM)zTX_J}4Eru(66(I^;00Eh0a`a*@FSGzgzyJt3_CG_91 zy?}k_lgTs|3{!Ylu^4^JJ==@B&QId-$A*g^VVe1WnO>QBjf221H}8P0^;}OPWvChy z0Ii`eM%uoaIC~yU;o}29i3F3eHSloH-XDOq%O1 z{B5opSiXN-%pVt52_$5juDZ>PNsc0RW4T0k>)X*(svWiP8a$;AmT28ES|XJX9E3)y z?3D|K{+B5mC(b2dqp;n4fO)eH2c&sl13Jc8!{vc1I=_-y$x<)gOUqpRP2XY5#Q%>v zViDe@Y!-5b*a%U5P0oMz@~yGE#C)BoMhIogL4AU-0L!!f8zs?H&YkHAG8b0PP6{;s z1nJC2WLWMk(1ZB3l-Nd{iMS35HSJ`}=}Z82c7ZQW4;XvA=w-NAM4sGl4Hhl((JF0Y zQFrp}=XQxAxL-`<<1cE3OKCu2el?GdxvvuIN+JJ) zEBL-_qV4M>X1(UR_l0cNs7N)^tU0H`eh-$S!sW!LNcu9&_9ta>=4vg`+9WatM_)AP$7LvotbiN6*WxVj7o2T@A)W3z9bqLpDh3R6a#|z2k=2 z=8>9!Kxj~s0NI{f<6Ui|r3bmsh=ST6EU!`G=c@~u-s1|xCb-e?5gduAZ^tDAhyUy~ zs@UnSFj)UZs*h`OzmNANO(Ap$HPmfy8wT9tbjxK4E6P@k_f#Si7ET!2kPAgAbnM_4 zgKMlzst5-}0#;I@NstPhKWeS$R^As4or_-cN0JZ`lEC;&?)dj*v|kbY?}Nns#ClSM z^~TWd0HfsHo#99yZbM`qGdq!hi2AH;EdA5t$wST2_^&KF)E5{2Vqu}bU_B!w2y9k2 zh^khc&^a!G#95Li{B-oStW000tKm2d}; z?<~ZRZ#!7sXyux?K*NARVA5-2zR-*x6lfEBANSWF}Z@y z9g)Vi-;G*ijRShJv`t<5MJZw;zc6O{DkZCG(wvfI2#6TO{7-6;Q9gO*xsw~fH)d($ zcQiDrOnEm>2GA%+a=k_buatpa?Uq@1e)w-x2m*vHPiKVV z^~7+_d~G43ofE>s?C$at+au@(Uk=Pm|J1SvHm%po7j__55Gf5=B z#$0LWIL&}TAXHm4fkl!@*Zu8Ritwqb+6d$@MtnC>R46<@kYWx=EIn(K(2P`NXlq$V z_$8GZv#A*0bc{Iqp+_H=%F+;_YC8Sd$^WG|QdtW2Q@n!y3^9{-9po*{AgfvB$Ca@R z>>tEg5ej)hEl$Oj9^G-kI6GaZV?jqFm50>^pQ26|sFB@z)QpF_UDq(^bk;qNj3IrA zf8+hIIPvG1<8^3bg#ti9J1&YA_%7+3`{W>{GIb7GSxNw!Kn8AEQIwf$A3mNdJnwf? zq8v%&S!f`&HSSfNOW+WPry1#wo@_Gsd7#6N8)%tSQUT4VEF^J%Rud_k4B=n@l`X=F ztUtVM-<}pzENdoyhIHvYqcCnl28D;xk2RQDJ0%9b_JLQVC^QQ=PE%I$BU)VX+uEt4 zBk+c4=Y*(4DBvCM?|pu1KR|+6yEbw=S8s*@3Gtl&bogxTWw^V=qy_i)srEcrKTR2}cK z16=ZR;L_Y%v*StE1m`}5Q8i_*E0~GA?AKU;jOW9D0y*$wW~*2>kSHQPHpgBTnGTv^ zBZlMA!l)z@K*83`S-ljwJxB&BJE>fO?GZdNIs^A|Rwd#$(#)DlvG)SIZRkX-bw?NP z+xC9S`(sw7v(<u_MN+Qc-^Y4b?UdJM^L_XGiup04m$XkT55M*qrUdo zJyX&+S6dGSAj$Wbg_6A`Y_4qld+n3)7J`Q}RTGB4uE}>(A!B~X9x{@x3mS9U$ms6! zw1Ir=YLufjjBo$66VC)vkZAM~NpE6krTw%zf*gR?sTJ9{7LQ8$`)>b6 z!V@@C+q!M3#mvx**$-VSd@b^^*Z*FO<-)JFYR;fuN8vrJ#I5bev`eZ#ID$@5DNdc9 z5BXu9bL;}Q=9)0J#6yHS@*00n;K*2DWZ#&k-V%PFpQTu(`;}4+EOsu^-*G0%SG<}? zm5j}2bc~@M3~EHksxYbBf^FhXE)xPwP%%IN00PHMo_~#TdUG}@`_knY7K-bc79BL> z_+rsa?D;!2-G0lJlBk@YYz)I`31QO6kQk9FpZ>-L!K9sBxleH$to(J$sAbKY7E!U! z=aYTos*leo%D#*ip>MvP8}OoOM2wXuU|#Pn-v1h!eOUYM1%Jf5$KjXVO1f(@rz2`q z-uv_O9I}L7S}7T62P)I=XDQmx&>-O6#?+~iLc8awQsm%v)`Jgfp3{JcQ?_WkR%>mO za$qJPjK$_Q{Ad++$~J5bEJ*Rl?}WuX5tHY6D@$OeuJngC#BZla-J(l&4Ph!}2D3muREMHULLUy6&md z_0P890vB2kFU6w95_cB1*34aUE@0~4uyr7D~|@K3jqcC&ZElVrUwU~Nl- z?wFM=Nb@nJU8&uvkss*zPcc4xKyawur`L1~ohV|f=%bv}jY^k$)gh$iv!q%Nd{^{KLlK)iwTa3rNz%wFm`56POA-AMOD_|X^Qw!7ZI_PGbr=hr!+z=Pg?>))}Qg<66+h2(?{T>m9x~jz>1EurQYL~wgloaEf=k6 z;(U9eR31$)MKtCy_%Us*6fW~0(%@|Zy(q{vMEW2BJ7{p6@vZ@ep8?u-8q>)Zm3O7G zMl+4&PZHpV;A_#xb)r_)7zUE zo(x@(IR7x6upq%mX(sOnTB1@hj}poS^$#<$4Y3HCQU!iK>Sm_3i|kVwPBRsG&RNht z-%RT7e!n(7qnlnN;cG-e)*qa@RnA)_bIX&ftnF3WSa(r{Z8&q~5O>pEbX++bdeo;D zEm}Q|Elcw(b%m;2Xb{3x>g)JoGUjPtZqA+0(4?{jAnd5AkH#-^dd2<3O{N*CYb_KgMn& z+~2{*S1qz)nB|3ABj7Ngk?ZbSztzjQ0$U%7pz|3l*DkgyxMpk#9!S@R5~;=ctc)*s zM4@qQ*aBjsA0+ky`E9b@T={T>!^C=rJNF-47Xj){_0H;)S1-{lybs-ds2hyU08B$j zP)6gE4^o#~CKt;xe@amz&8IH0DkJWR1NY(Xi@l)tt8g{sdb54T-)Nl-XHbkH)K`*nt?C=c-W@6EH+|a(OrDhC zETs$(6Zrhlv@3?jSlB23+&x06>5Jwp4wN`UrS_Z~Uylp1jA-S4J}MC3fGaSOWGT+~ zhek>4?G3VyawwO~gwgRz=FAp4c{ydAoUtp6ZznM-cbb6M4RJ=nLFjT%h%w~PQdu6FJdiMYncWU=zVQ#qhY zP9s>!{p$wh3ohoH&SkXElPCK@op9q**xau}HkSA|X8}=Evh@};5yC#pw`cwi6^plo z^)=5JG#Ln5s?1S>xGkoTsabxpC9^0{y5t;5#$Nw zRX%#k4(6Hzc{~D$R?!}48xLCLL68fgKELgZOXqSalfP3>$zh}OC3Lke-mW;_@M))A z;u*NEq#sew^C!Dx&RqjVZuah(4x{va3?}Mlq4?uJ;(@mnFHI0X(F9JbF6*AK(im4} z;#Es3Wi8c=x&}52B3S80rh%z3wk>rTySPuuirDaZru*)12xUWOp1PMaI%}_`A}B0$ zac5*ARh`xM2Mt~1Pzf_yyw=-XUbFj$KXl78Gnep z5HK{&(6h@#CIweO3JJ2^cPVi(;LF%Rhj6BwiU_r;klGgWaFQ^Yxj;gX3QJyUQKNaV zH}ov*0CmxBBy(tS4b0hdzCmM=D7#AdZAMy#XJ6a0QM!>KIFW28Ih?(J-O^@){#}<3 zQ2Hh((v7n>85(w3j*RvvnShN;zRn6O-EYETsBqu=m`~9_M zfiUz2>j8vqsKiB0ydAPTbc%CP_TI;(j##2AqQNcCjy`lrcynginLxgyD))68u;BYl z7KlMt7Kvawq&rHcwHv6Q6kJJy$08RgOk0MTpWk=PZ4i7mkxIyy5#$MCNjKop_v$^y zeGGrpMztN(k}3jue=$yeITO#|{$Z1sT7QNuo3mAAgYSs`n(Frny+q}!r94s+*Jbyw zvC)L91iG7;+P7}xdm;kuk$?oMZiT?ERFF*bFS_Y@zA+B%1kD zC5y^sSbMZ8&>_5#9cl!>xbnDzo2J2BB43oI8KzA3j-^;ncv#5#vWX(mj{O>rE!Duo zznOMDXr);KGsX0aLIi@L{?oyLnA%NI+hTtF2L})JJ4%e{W~<*ED&SpuiZ&Avzy<4PDH{S%n(iEE{c$}o3RUkqsDx( zXl(E5qAZn;(CfJFQMz{gw>YfdMJ5u;0Q zUSabl20Q2vCxd!2_Wx({LimyA#cTF^9p5YmqgWpU6s-FoG!)0z4|#hS1GV!(_0Inh1I;hfI+7?cpYg3IDY=5Pg27AHqodSrK| zEtmopB&M6rYeH?kF>PO{fv#`1yeSH?eD2Pbas9+R>k*8q`J~$;Q>Py-HSh2@&gk25 z_CiXVfu7{IK;AddrX-ZBV-)ganT#Xz>y!Py6vR-NXbU}cDcoX9J zYNDo;dC(V`$XX+WB&vG+%_I{qg^}CZ1 z94~(I0+J|5j3=%JlITR#xF|zS_91c5GhCcEv=@9QT*t6J-nDN<`X)6l5LYXM3(7-` z_ZarF(;asl7#Cv2)M2#}iTqb()@klUkk2rN1~po$sPySSR zT3vGy%1jRg_q`%WacZB=|F86R+`n#d-czf9fmJ?_I)A&DR*BcXA<-*}qbU+AkJ8-_ zVo@I|wpjS{ot0oj36iB9?nHyw`1McAFS55=cPGDqndZW>lUd|UH^Xp67~Se?wb_zn zC?4CyPWaJtw`{UZ1${nv&0EyoxW*12V^Jx)@T}5PH@pexRsbf&KShbJESPY+`U?tO z-|)RSU!ZH%B=z9%^%2tUN_ci|8^Ba&TlK!YzwgjD=|^m| zsnXxm#aivo`;&;&QMn%Ei-s)O`)*(}HSt4GMf`7PVCIjSP{sfN05z`DyzOFI+vk*sDrVcu z5}21B(6Y()RhbC)-G&8J!@DD10000*4Oc4tuPpxngQr}{`)C^2dM0Bddii<<{Su1; z>)Y?>Du67wq$_#%2b39M;uVP|#I_?`Cu6wNMC?+zXdq1$(Agg29txo)Wf1i{UG$jV zeJu?!s;@ZlJ=@qoIZYU8NIfyG=M0E=2`%k{Vb%Oap;4s>cRFA!M0P{@|o-P#p>Tfj^rb}>QN|DQ$?LN*j4 zcC9XOLQCCWTL-I11o3DWIS$QD+^tDS6`&9XB-j8OSo&>_T}}dMzk_WmVl>l#Qwfg< zn5-Dl38{?-0-|8)4ik1Q{pRh}ZTC7kd;kCd0CpMw8!1rx7;7qo0f&Ync1kCL#BfVQ zcTFp_P?RSD<$eMNJv^%OG#Z2grtpvq^s5Mmz`=HN4|~?bRv_$^UFBJ<1UGAz`hf$L z0nDS=9K#vo#Dc93_*W3a1-Z@@)|x{!l^Nfx2nXi>CZ;rbz6aoaAdsH{NiMi1!lN1K!GkI?(4Ha8BQ8Z+3OpR-b4-+NHAT?4g@RFYcg6+c8xXK zw7J53C`q-WNN3>5WbO9cgB6RZxB>8z_uy9=oNc6G@pIr5pSk&6&@NghAGw8xQzpsO zQSVsz0M^ReMJk+flwT?zT^Jc17;yMTELnHnv_gJ|I3zSsf)`jnd_=I>dyfSa<5ny_ zD@wXUijBTL4YyKRWQHdp-Yd0G-b?bvl>wpHm)T(`DkZogrPT`O7iihQ=^ZF>&@6vv zfs>WrWKAuoz|$wHW;YBmqDl^nS~pNCPEC_^UDbo70z_GOq*S|!xO7;$-a zrdyxNaX30-TTGWN9Qs(D>G-y!P-pc*5jV1D@0L9&YYh1*5o#Pr@hZmkvLK+~MABG8 zn1XNRWu;OuIHs5A97DA3aVs$C5DrU(fmyibjr}C*LnQd zOFsA{NLW88T^)&8)3qn;L>bF-mPWdNJFuIoeHcboCR|5Ee-Mdev>n>EUZK_K(7aLX z<(qxRIkzoFDwpYpM<*+eGDic;=A@;x85KaxY2ollxZ!uNesbJ&^40qn+a zZrPJi++6%Yua7u+?YkZHL4C7?MY#22@E=`h>g;O~c#k^18{9Um?h+j$d^Sr=_MuVN z&z&flhjq&m9%cbR{QL$PNw|C<9yOLPRo7{<5MoTk`9rfriLZD~MeE-7MM6~tu0 z0R#pj^tV^fbeP9oMr8EAa+r(p9C6?N`+Am9?3w0CK$e5fe^=_8-&i8ATtI^9ZZ*z( zK3qch{0lYO0ygq#*_yi=Xv~pP`G!7gy>geHr#ksFg^8b;9YGUZB_e zQZU%9>@W4X`-f>L2?99P6;{i*0j7ZbzwKci;vo97^|i(oVy0Vf%0xerYu z7VOK@8whI=c#k@}erP15Am@7`$0u(17&$vj+KIR`JVH#dI#S$F1CGC2V^k2_q9u)TX%U0=Ro zsz3w(k(E)jZ5xUBEw8OF*~VE;#R+q~G+rN0n=n|w>DJ{CI1?|fF%wZ=dJ0QVlWnAs$I~jqG1QX2rjj9YjI-n% zIstRd-ud1y_2Fd(db(rEJVJy|PwV}Ox%{9l+&lT^-Q{qb{Ad1d$osx$*!s)V@jDCq zy9RPkKwJ(~c5X|ndORcm(43}=?SJ>8-RIXd1*Xynd2u$s_v zeZzD)zV9w@DNid*1KMPBmWe7d8~b(uF>z7rczQXu2MGVcwszi)@|UhkB4%h5dh}xS{YpzTgdeq~Hk$zM#)?FJY7&lA%8)N@ z^-QEZ;I@coukzNoe&UBfj2|l~8-avGPVj}L>TpW)ar?C9YCM=nm}}-53G5`?`w$zq zFr|RtGk72|_jlN|(-ne4B;ymj2R;ZXvX}q}6*Nf{=%t78s7?VA70)CQ5 zG4deNRKlJ2EwX0ChgVjGfjPidw7ii{VhTi_dYM_Psm7m)9f-cTX9pZ6!K5*vkfVa* z5;hlqKjee#T|(14Cyo%ps}Qm!%G-p{E*Q;p1A-|af+VD6JFArCe-0_9)0wRT1S`(=D2hs|VD zmM9twRMMGRR+}6ihjZy$$N-LyZ_Fv}7G?9J#nO7)K*r{U-~hQ`vM`#GpPI!ZUSCrP?75 z4-~=jOc!4tZr^2mvr~+>!;0i-Juk9CG7>+z&=mv?WBW~fE;6nCf7M&+6Fczb;&(X;R0^NHOEKT#r zm$kg1tPXDg&s569C9j*o!#K>jzp|t77wPP(I#``EoL|v{n(^*-BbC#P9*Ykv;3z9Y z5+Hq-!|skzIfjcv+WkTn7|QdyS4UYwXgGMNK{fd)myTpjzGZzx2cG3XJjG%ag=RT* za^ANvJ@6}J@P1CfkoJ>3WqhU9m6FoCPN=Yr%=<^%bwiz>$o{=i zU9~d>a$RxYU**gS1IB8EW0cVa*3`LfvEWA_;CjiEB^5R~R}ZeNP1~ZclN{{P-%&k@ zCF4w4zFnU3HXg?$7#7!&3z7u2(p%o`wpy4AJgaCj?l)Mg`hPsRh@QF*JQ4yVr>UqK ztdD0LQr%-3vnyB#b##ai5Lv6kq#M6}(XKP}lKK%mXDgF-`1;`kJKCeyvMd6jns8P7M8h>8ddww6FVR$$}@t+_?Vrmhom;mb5fFw^Qo+V{8^C z)!#R zbMK6k*_w-lJ7`_C(}rDDk#A8soHlF1)cKo<=3A7yhaJ94D(5|F^bMoQSe;w+nGW+R zgee^XhgAl2rTWV8aBG%R*j8kLKUaNqdDlmY0ZivOJWqvht-o+QqMUzLi!U&J+SjC z9ZeP@sMCsX>XVP5pBr6Mh**lTexa^?mb}ZV=U{Y~RptoJJ$0&&z%}Ch5HD@AF~g|) zl5uq5b`CZm(dpJ5Uj{5bq|VNvEs>B=5+jpGX@7*rz1J+2VJr4|j9e+KL zK@#}0A=3&7=xcO!;8X13oRQW7j3z(&J}*#Xxd<+eZcbKYw-#UTMC(y&{rPO{SC^76 zS7&(&vBAXGAe}kj>26aXR3t*%a&r@2xiJZ>Z0y9WeA4RSP9@e$=*L6za@!GZ!57k& zK`HA%U{^DT0e${sfl)3PrkDBRDHqpjzPz+YH5@lNj|n!CDrl^H+FAc)R$~zq1~I1{ z2U%w+Dbr-R1_NlJ0^MHpd&{@qO~6beS2RQtdZ#|=9#2HWdZWDI5#;|nQ+wY(ZY%eT zSPE<7g6vEhRyrP36vddesbp6U8(+*}NOL6i^XV-?Z0z*YcCXR=06kgKrh*zCPivs? zmj@HjWJoxZWiTg91nDQ~W;|AIPzu@R7)*#Jdz(oM49(Ab=aFq>w%v2U-0!}Ytar8V zYViK~THevPCN?z30Jlq}Ge75Wf;Q*bGYr;y$C%b_@&`LxALnZ;A zq%wvHyn?U{xxtYhyBS4~)P;{ajyIG~0MN+>5j)e%#o&ZZ$1 zh%NjRShpd6>2Cop1ybQA)wM>biQ2EiI-H|MDCIKzA)8MRGJNC1Y z8Hbc&d6AP10^T00Xgb1meo=6?@`zALw>W=&_2Ac`I&B-+r_uM8mw3rX(hw;Ku5rxD zLR(Vwy3ZTVk<|nzgy_SVldsK;&(H>3+WeG791RX)aK+&*03XT3>81?aX1Vf4@HBmZ zFk~B9)o%W!2u8o%LS#!ntJSpUpf(KJr6N@yQ@)xHtwI0iAfLf-*1pH8`V7UCc>o~l zz1EUP2!Dl7*R$ZtB|_i*$}9P5eP4f`O#VzFe`~q_oC`f`G~{5YC0=Cc6!|B1O|X@@ zEiC3?on&T=V0?~RxsEnLB#_Xl;C-PQ%`#B{-7=&o)d9pf#WFqYxaA|Q4L6Z( zrN$_kMQoe0?x(i740VjZCgGl9AMUgBfc@(yQfX#oKVHZ2X!+4J*>62 z)os_dwZ(|ly0EI?T6}qt*o;}r%=%}yXL6{@H4U#QtqO3{%s+RJ7EMe==G%|`y(X2>v&LBrjdG!~g0xdaKo8LlXeZdV=?b9HDZmmrrg zwO(PBA8S)^g+i%-e@=J}J(1ojQMb`{xMrxJZYq?aTILb~DO`JxXE{ZSM6GbeRgZC) z3>jsXhrX`4qBok{$H*mC)_H-za!jOlT_>EIF<8XaX-^)?oGtE4(658>&3LFeKg2tJ-Zi>HdIibwe>F7dc*&YUXAXmGTS5G>zu z5AyE~ot2c$a3(dppGS;WH0bOEah$M5^9uSw_)B!TxN)PjCWyz4DzrJ}Pavvhy^1jc z1zEwFVNb0A9rBId9LUn*=eC!KVw|}3eLWChV=&>1Hajta1X&hmhvLfjU_h8VJ{a28 z5C4ed3+GhpEZ3B4w;k7-AeezwgRotZJw-8@HAw{iD|~X=H;X6Q-~6ag@7%XR8gTQg zE(zz{1%)d)8k}2ivDngQz$*vQO~is@ zjRDudbXp9iM!S|C&5@LM`$?Z7 zH1LY>`P27`Ey;fLrDPG>M-SkwL=X+evXaw&8cP%D(_ngRd+I%|5EP2pm%Grj;?n;5 zfOTHhJb_cE^tWI#{dim=0LN6SPeFkLR5LG}FZYp3%c|~TJqkj#JcKtUOEQet#CKOG z$?v*Vpz~E>f9`;1BSD%F^s2>&ov(;{)ox8mEMS11F?NcFqte`%cs;AxXDR}EXCKKW{V1NPp2KRW{yd>rx%q?RS89ZiwEs&V$FYXe{j zfQ*Fs2FFAH5bWIG5vV>j;u?)EtvLZE8)TJYcp>t2SFFj$2bz9atA!Y%z2z1OR6+Vb zlGb=9j=b#&WK2%zU-3RQeJGsx1rFC}3F^$OW!YG?=2^@%{ikM|OS~KPUeaDNIeIcDzfZ&pj1g<-nh78%9W0o9EYKRO^v)x5OeA6swL7~rJ#e|7iu$LpnJk- zq^0=TmW-Fu5R5wC1+ zS`!S>q#GW>y-h4#2y%$bwqxs1M@*Nw0@~f~nPbw%T1+P0t(!H#M*Z!;WpYyPy_0>9 z(+cIvxoOSYt_CactskleX)07gGKJAxSN~p%TRYXO$AuvjYCEuaH9#1KES@nas?POW z_)OK(L2$%}n(WgLHrC&d3NygnXxM4sRKK)P-`-SMiKRqp7szu)bZC}Wj9V6Kc_AA< zP7|a0n?aGI!_r$_j)NeuN2i$mCl`1BSCw-#ss~mph-{5jt136pTRice#Of+L5aGd0 zVi1;eI^~w#p&YuC0LNzJS>t?A^{yLbyyMxsj;%Jtn`P2PiA@9_Wg?jZst7}vb(^% z>1?X;Ahvy zmf_%Rjf)LL{&D`*rI<@xUXb@}&pFwj#Q3s*5>(B-fxM&Ce3H~YfzhxY7DFyIbWMVc z_u(Ztmaf1Cwax5tdrJ8n14p~1e4(*GfUyWw#6_UW9W zXEHsva$S$Tm^THS7MD*xaWonMY-Jkp81nUG%9rp30j(-|Wox~1-T>b{Q${*C*oFm4oW{csb9_Vg1{*>q=V+O|@+OjhYnv{1 zhjDz{4byOMbn7i7&QJ%eISY+Gy2;m$1KnJwiZHCyUZ_$5ZcF)bR4L8?$z{%OIX*A&gY+@MG{T(*>-i+Q6edkRX!) zv&PZLzs6d`Pe#1hqVeeGm3bGxIz-D&k2~KThK?)zWG>9dzLJ!-`#WmvxpOJvoMzmH z<---AFfaWshSoUz#j-i=VqEeSbfcGqYCQ&P&Vf}|F>_aB_{_-e;Xu+N-Ba|qB1k93 zTj;5H{#HxGMx&=|={Yc|{xNAt(UtizK%iZx(&@>laB^fGWFI1IQd_d$mn+ zm>=H~#tn>M#wCe1p609P&7y2b1UB^72N5x{Nc6H_n;ra@`b$2@knrji4*5?W9I8(6wW>Xbn~7 z*3@th^KDzFn2|j=?z1Hnl;Ok4y(qyN5AhqH90ax}L7artk%=CyoMK zFoa(6bF6X>+C2g*PN6GVtP%^fYt{hpUQgU>?#>eDP#$e3y7LcFUE#`ML)ePhiXJ`s zftqJV956TN;~DMOnYNsX5UmWa>~AZ9Vn0*&NvDNTBemg{?y=K0S)43{eMFShRGLT1 zG+M-^n_T$IgeWH5E>@@zy8K+krO0JpNrRpn?JcO2zehgz)2*$`1vSN8F)qNi(R1}z z2WrQP>e+t5`|p2aTE!j5y=u*-E4^dMWQsz2Pb#m??fU!Va>ZChe+s)IJ*eq-e62xn zf!g)j>QZPvFk*aw23&aT?G`??^iZIchf$$rM)vd3)4)k6y}=Y{I^f)%=!A8gsikXi zRaPR;&3#hVTvWU~<>&j+nD^4a7G^cwkfvk8=#hF987M0NmXraocCJyol!@3mR*snJ z&{ca1&*_#8l-_Glo4EvKmP@LI3B?^}L|{dIfXUHR4*{Kf-`-CIrYkavGwtmb`2OoS zcG_+9LstJ46Yr?>qXMmwq5AjZBjq``wym_sO-%)1|8`sda9Zt3a`x*>VGNX-CoPMLO|1zz- z1_HO{1B19T*Kc);;#M4Z3L@=Q43&4KvIfhJK{ZlemSB9(?unqEBW+_m9M7CM$X!EX oJa>?nPAOfxBX-%hJQ&OlrHJ1jo29?~r!L62T6u?O8~VTi05$Zu6aWAK diff --git a/images/smart-contracts/dev-environments/remix/get-started/remix-11.webp b/images/smart-contracts/dev-environments/remix/get-started/remix-11.webp deleted file mode 100644 index 885e62ce902a954f12bd489ec07ff6a87a63676c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 126058 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

  • ;`J+4tR@4D0dH05!3`Ja2akAFYn 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%0DQ^eqe3mq zKT)_11yE0lP4c9!3kj^6%g3xG7_j06vJSa*$gfg@WkW^Un9HhIK#D1SbzkOcBK&h~ zzky4?5EVP}Tyq=Yd;X(q6)6cG%?S+7^>dHaRg62BQ0*BfFFlpEl4p~Jp=Yz+iF!m0 z8)LGN9-K+Zl9+}3RTdQ`TgAs71*=16Rd~qw)Lt4>$@Cld;x$#&5Pcr1Ib(?5li`1d zrU0*)n-5o1Tn%cApThQoiTHSo33fnTYnvN64-mXRI=I|k*<+EPfvp9t7~3eMzW)Gr zlUT(=O<8d~X63FO@1A_XF@e%#5>OXQxc>Pf7ENYy>;1HZ(`ku{DOk9|)-v9XXxn<> zG*A@>;Pt>MtDp{o|40oWJQCy39)3g-R-8x#J|TFf99BIPe?8!3g6NyGz$uA%h=dS8 zpq+W#4I`{Bt__gS^(#cffxI3a6>T$Em@tD2O6Ls30$aIw*0Q9Iy= z@xuLYPg*PAHwN7hj+g3P7mioV^HVx?(2310+Yat-3^jJUJ@h>9&g`MEV7GM?}89>nK5znIgK|!nLUY|XKCf?oOdG@9-TG*>IN4Rz0 z>r;W>Z5DzP^6~jK?@5pNyr@?$WOm#Nm#`F*O8V34bVLnM^mQD?KvDKPYe*lwHxm|p zP@AF0MX~c(J0RU93L94gMvMu9eCy;pN7e3_KfjpOHMopF^?+<=aQor`^s~0{^nEHN zr=BfOb&Wib$PX4c1GFKT@p(XaBCKOqeAq*HY?1(69SY>>Pmh(x`T7P6FJ3wx ztPVB>UJe*S;YbjRu+;;BiUdj1@<)-;aYzr8qRdGY`Dm{{4{$P0L>>pWr0;ONTXC~~ zV-$}~lR0sYhNW9D{wQaHCA~}79|m~lnVSl##m%;Vz*7wzWs*G=2VeoZ5Gf-KfNxkOYWnGbs*Xk~c5>jD9>!d`w;U1`ejy4V zw5D#xJnQ>jML5;_?#D}K@_gkIT*JQ)sUM7u^BA4;m$}@zV5SHxhL}bQV%(KAIh@)M zDbXf*uLsi~=cIKWUAtw*mOm>3s+mv*(^$V0t>#l4Bg*-%Gq^;S55%hm_yb$^mBW4e zbv!U{x%SF&5dE&25K2R5a~;%76~cN1nD1;EcN$dDc-`hX4}uT4~=1(Gy} z!!G7oi*WHYbAD1LO&TAbhQ8K@28z>sK$c$2krWQ9C+*}e903@Q0`vwQ7jW~#em$Q2 zlJvOFGs^rRr;|*u#wS@gy$!9x8gU=d&DiV`*t$UCmJhPA@OwnLIQo*LFX9{t@eD#c zKfV~*C+yr2cA9^gWXh zl+!cSDj;Bdn1&8|m6A==1*nKdRCZcK*uY7FWMINT^+Zoa_+s;{W3#sib4QMMrZ6*y0 zwzF~@^VR$xHw4<~D0{V^+8Dp(>4shIj{1_nqshAc{C+Gas`Q_N?u~!9;`~$J`u}4q z4t+l_RGw4ciqzR!P53`o+|PrjbPvSrX6o&imgP%U$glG!Y_xAxrm2W&@g>WS{JV&b zaOk;JMl3E?J44s3X4g@A9TL5sY2mNUr>r?dEYn@{&_0pJjv!Ew@R(;e@y1E6H<6o> zgAX%KT~m@Q46RS$wBmewO;ra1WTs0lJb#mR=;G8HDqebyi9PI+5hY*YT6C^Xcax?Y zkRLpv^rkx3?c|%Avn@GQMz5C>WDLGpop_Y;dVbU)NBbh?O=@r%`i-{dEIZ^?p|4f1Q}nKFbFVPkQ#;W3V&+^e_H9 zFJ?LIvszKMs4nqW`1R z-S~Chf4+N#!T==l9{`_&b5~M{kDwn~n)}rB!=~@5)*T*uOf)WaW(tN5o9Mkfzwg4F zgeXT73hVZyK|~~|sE2Hi6^R+VQ|kjhOCGY$LWqLdMLYItsc?AMDYhA&;KJUpejJ=* zxHbwJUO8xTc~HSjy~IwI(C;iZ)P$r5Ki|g7lkRofea#>FuqAqI;Z>&josivfOw%=&XE&^w9%z!0yfHl_8WF)S zzgLMOu>5rXFv<9NDgHuI|L=7_2zprt&cTT>53EKsi?*pDc2#1}M*E7+pTTN`VEG)F znWpe6u@EZ@J`ywD6P2*vxwyOo177NhXEobDkj3NN=wpo z0UG2P!r6}41M;N)BXkl_JEJz&&dyxBp`UEW+Rp2?vfz!;;67>qf{{HeMPlf@7CWT< ziLp@i2wM74pY5W>Sg`1>fXT0EyuiC@sK_{xoqnJdk1pRGQX=6}O#>>#>Z8ncM7)H; zn-cbEV@I602CHS+O(t>c)u_r6XmQEVQ zz0YeV^)()UJo>aOwI*HD>4dL0c6=mTK>M6vRym1_Z4rj?Azl8(TY9o?_04k1W1&>!fL`gbt2-pNVtD z4)azW4}Yz;G|TAX06@O3GCn(U&#+_1d@r_ej#j3wN3^G{Q6sj#()91WTlW9&`qsnu zjN{7O9}RmCUi^+_2R?E`pFQ^Rvj`K=Ip+Vr>RXdoJ`GD!+`rCCGlUy`#)S($)tGf4 z#~2i2M3#g{MdLonTi-DgUZ1?WI%G1o75C4^>sAAY<=0Y@KOCW{s}URTtGvhXbUr56 zDaElVjO;vW!SavQIxjVAo+F+53y2@L0 zO&$F%_E;f>fP^8lF`KKB%c-m1I)|BOR~#|#0z!F*UJh1hc0!~6oRbWBJLq0s0S(9? zeUx3nTeroQN=JazN0(h|Yb>B1la1D3*Io&vl;{)A(pl346oiyQ6|QFEF3%)*x)9Kw z%n(8H49MT53U%ofhSwnrdUUi>j0O+ZZeN89@JXQuVw3oz0O_igYoe2Nrt-TQR0HY& zthsJPHG-9*UltF!7zNd&#EPi|#NRsq$EtN#;O2D~8BrPqcA(V>5)%-QDe5||ez{`$ zYL1koH6}{4;Tpg6@`+1&qa)G{fOJdN3HSo1*LgiFB^XY?JRcpBp{!A&kbe7{**J5Z zX(qpZY~|wfDDq*>tRpP9mz#qvD+V;Jb#;l?%&Ls_b`Qm0#Cy&%yxcGFeKbj@*Myo{2@qRYwZyE)fsSVE zhn7b{H3H&5Md+%13e!pZg9I{zb1Uu`xVLz4f*_hgXQs@jtdJwVHfL}^*t;%*<{SWg zfn#^6De2H40}?FD*Z9hkO|qPzeOYzTM`!8Lxpbx4&1PRK^ z$svb;3QWtxWY9%u=(=eFa7OFiAn-{Jh-PtcQuCnwp@VOMHXk>Pf9g&cf>!gJO#Sf^;lYo{_^j~D_KWR%^b|&bY zH(m@x1qdD;6^;S7IQzUzHkolhK7Y=CmtRTS#4rjtwwa{D&UG<9Z~ssTq>2I!=OnR- z2j6SD5b_Kc_jxLh3SD=lkiYt4wheMeJPIt1Mz*UFZkijl>nq?)Zs{Hw(+nxmb*b)3 z>m9WiG$*JsEsH`7{*zrMI-D7w(bXBWKYpm;P4Q|9%KHNmea?H)<-%_+FrQR8&SlZrb;w>F?$<>z-sh z-6d>FA5BO~qb8XwV=^2^Q*vHqrhHEcJ|CFT;p2W$P)jRRD>i8dBRAG+dXnz_3~h0n zvxFWyr;KqI@H+3N-wSarN?o+m2eA1Ir3uM3s>KtOkux0eZi#Ko&i1czP< zRccqG(0B{1kQpOZ+I76=4}+~~yccO;+%(U3E<{O9fiyJB6~S?o2&@b8&(DL%T%Zmi zenY02HPPTY7a_p{SwaHR?-agcAwf4U```{LK68{+Dq@%y#r*KR8k#EH4|FZ(z2JTc zx5`^m?x4#wUlN4lhUB_Lsf&1c9}QW~rt!{u@E(r^)fGT{+)GA&WFG%Ys}W5)5E*)W z2xuL_&BpQbbnwyV%(co(HJNy>2S5UfpG|XIV4CA-yl%0e;sV}xIG&P`vJajWVLMLw ziZ>)H%#V-pyqo5U9l^gNLcimX2Qct$7SG@+{GJ6;K?wdFWjX22>k(0E9Sh1R=dGs~ zh$x>JL)b)Y`h~fki3AHWx)8mbwPpmY-x_q0bMEFM(wN{<2BL@r3uGZmNig|XXdwQe z8wti<0GX`9O+7$`G!Xh{j-gi`UEAYYplf4Jg+2#kF{zkerC_kwraM9*qbWi=2%gLn;nLXw~wqH;1 zeXFOPY&e$K;C-{f%QZyD1vKw*P08b0YifLFkD6&n3J#~HUMKM9JWv4zlp+GVag zDTM_}(P-hjO=H}*W={g=Qk$MC-&(lbv{Xb}DQc2uQgE@{%!vOcmVB3r&_h{n9J(Qe z19M(teOUazyac^i{}xLE#G%kD3@{G^mc~FdLU>Lwc;7Mj#ak>j!1A#OIu~f^Xi6w1 zouPP;9t->Bd`5DOU`T7;8;AUUi~3R2Ok%a-#M{(uTeN;PL)ii?hnE<7#SHyo#t$)Y z9RoCWBFD_T-Qr5S1pzh69Vq>eOeus;9huf77kKzumyB$7PI@F3G9$ZLu zQlgc2XHZ)EaEGBfvt7Xi#Mu@r|AHLTzjNOE&c!Qt+?HC8qoDpO^`Yj3wzi}T!xo=+ z)t*?&-)#di@z)Nlbw;RkM2UB2>v!k;>hSvo{JLXEd`T`FbrWzhDA!L;?CAWu*mZ{I zjwimm;cidUyAHKRh(AxgK~G@GsdUtcXQWnu2EM1SNFXDv=azWyKx5C(hE`A1UA}z1 zc?!s%3#87a_Q+P9Vx{Y)g>t5Y_CE$0x3{=z=ktC#c~uJlAsKsK-3+B%7Z*H-H-9+r$+##dZZV0D%JlZ zp~q)bfLJo%y7$0sxs`?&H~5UM7t%bQv(U3O=LCOJ|PGVuzTh`>$hR z>eF|#fAXgm+v$l6kMNAvO!getAEp07P5lDien0NO8gE8|1CSFf1`onnKz%N7`}?uz z$##=h0@skewLX*CSB4+l9p~!@s^iq==f`{YfOrN-eR^C8J8_!|Qe*WxsMc$hckyVA z$AnF8hTY+#1{{BBW1a65eOZfoA$=Zx`0mdWU4!UT;#1Bdz~d~)hWFGT>OHlIJL7x8 zInb&8WdXGaU@+s6^WG!ATOICU5U(cPqk)f@lLB}G$~YJNV{w}Q_l&D}2Lanjb90qn z=@S|^w9yIR1y41$3Ct+F8V$|(vhh%zYf#5W#1{gjKI`%Zg&>-Lx z@K`LjYD5m?oB&$jv1gvDDwmcn4b;+Ie|6@I%C=|E& z$tRQ+HT(41%6#d{;x+2x%F1*0wH2>nIoz~f&zGtCYtLVmKHutl{`S`M3#G27y9|le zi&CUT0jZV9p%vrm7cW*`{0W~;yD$sjTaA`mt<_#^-JnVQI5GlXaZPx^Gnb_I^@Wh{ zn&L_*IAd+!Jy+;GSJ!;KD#Lo|Kcsw*WM1DFXg>hzpox&tsyJVO=+v49-$vEjb?pw) zA>R_SrJ9}a7knl*&j7_(gmq*78 ze|@m_IA|deo#hbof>`##!@=Y3y?Jbx8k_%iqF zt5aHmibl^)oPHf|v}N(f^Vsv(k?cRHa}Hb7=Uco%TS{stVm@x9N^WJuyrDb1?$v!W z6aJ>~&zo|i_2RNEzLu?un74I*w(gF;;V-j`DtpV2e3x}Ee%?z!igxs6wrlIXcMPMq zxu*rjhF*vmy&v*@KN9m^J?4!(7I^<73WIH$R|d|%ZJP7_@HFPbeA$P^dmol#Zax3= zVO8?uvf>Bz{`auB!(I%OjFh0h3|4JM5Uv4`S~a#K9#-8 zcL4q%5CCX*283lw*~fy}sIT_Kua+c~^KmKH`(M59>+%hJ^~ps2CljQ~;mc`rYTXh@*xadU%JVpHGnr!!!DmZ`uVs`o`UcIwVv_s zyaWe8#Ag}7G__3Hr3T|Ic{=C2U4kE%{{zryOA!;L!Dr`tE|gQ6NqT!5HaZm^tv=zE z!t^}S(@xio@ltVj)&6#o&u^ckcB+{0oOqU@2A}_UY!LLT=H>*awx%o^_O4VyREm^% z?UXMc6;rYPpq%jF=G^p``+d1eJm8WZ4nWgjK2i3YuElf5-|sI#qy6Cp^JUOLU(cOH z#HfM?jn;qR^XqXX8OQKLKkmQoZwtQRf&-s=COnYFzK{O{g{;~)>#%gmg5M>GQ8xOJi9~t(dWbD8K%l+1fCoHt11a4U-4s0>C z!E5|zp0eSFA&RUY0rnHu^OzqZO`#3%Cb8sO6EFHELy^JWGjnX_Zvy5=QO@g*f2Z z-4Qfmm`R^?1b-0{jF%5*&Duii=L-SqPpY%i!O=qrAY;+1GyF{=0Svxdy#c6xXihk> zpEB??EvL$)l;sGoRk|b=csAbIUgLWJi(>FO3JsRp>vaZdmE2B%@GYF@PJs(Iqu&{d zgfTJ@MazVV@|uC*6};hm<7XdaBFnhB}g(?0_M}$kA9da*e?;W>q$&Na9S_o z_$4T`7bW62OQ9GaVcq_})-~-XD#7-y&b7j|$Dw3~`-76Rd?znn{rM&^WHI_>K}n2H zUYO=tuV)WEf^))OHsiO)*vTQpm~>%L_u_@{E|=0$=u5Dqrjg0j^$Yu5SFi8C{h7zotmCEq?1sVzRY_e{bQ z)1!m>V5jX-e)TM~&clyPc~s5R4R;=*FDyAu+!fmUhIlAM_{;&KjuKW+1>F0wn#`X5 zEEMS|ZB;4CzP7ENwZm_}(wK|>_3`_4v@I8z!iLtBa&gmQ;ouAadK3>as*XcZ%fSj( z{oG!xc+6xu^zdju-(^+;7FhwewECYrvz!N;~=ACwl$ z!a~UhOtUH35XtQnBDGSe)@oSUYdh6r(%A}@1($eF97;DKPrrqr`{RoA(;veV&bX$SRud2}v~{)r{a4f6!Z z2rJ(IWayZkQ_Z^*!UQ^;+)OXrc_dBntZbxd>JxU?mE6b1_jzq9-P(JoazeDkbJjWk z4$^_ADc9ECt-7GC5RMD38u!zL=8xC~y{FaNJuskMoeZmC1>g)sBFdv?n`~qqBOa~= zo;#&Ud47-afp@z&vC zHq(QNSnR(r!+-WXQJjBC%70O~e^X^9@fw24)JWp0X(BJ%&<^u2a`NP|?ljpVQ`F?F zg!S1fN;cTM&c`!SZh~^qwel~8OW@Nz=Qde?NZPSPCt<3cWFj+DWiBHv=M@<`o8)kV zyYwk?<0qFgIVTLXL-oZp~tWgMJi}e!G@yOc%cLgO$X4-u+n#wy0}6&2dFgd+NNJ^IBG%$c4p=J?HLB9{`!h82*~OVW{?M zbqIg2_s5s5i7N*%UjnVrtc^5P#p8eOqj$e>tS|@Imy^+vvV*Z;J`8~e)>6J2&sP1r zgE8H`VGj`*C0eKjVAhfZ9WV=K`z|Z~Z5j+&=V01(>#6@y?)CKFJD7jFexOQ!n+8KS z|CW1gX4~n!*~}qYDE)Q)M9-+WovpV2iy6Kw_@5|T&{)J;c;L7asx)Bn2Y=a#aYhYN zb?=;D3HkDy+VVvChOJ6#|A^&6DTB*3)qzKBeDMFlmb!Cr*`I(5|Be#w9Zn(jTf;ex zqq=W$sB!=y4N~YokainwW)KO48QPq z@kVFarR01op{FIiSRbHq*wWskqsF%9LgbGrXT4jNWWTyqW%rjY4VAiGd44BiC`oPA zKX%j~^p?YxqVHAP4>w$|q@I3iJFnxgGMb~JU>hnNr{6g3V5T^~{`uW}o2~H84==b3 zfa;;_DP4pRpTy$h#^af#zl^yg&xYn09jjnE;v$BE9^Jps9<6M09+D~B`^JB&-UK{& zg00QD=mE!oQ^uovEJqwFsBSIkLSXiUx0OWJeS?sN%yx zCwMg9KXXEA{S`c+-i%gRXdn@si#`$(z`5uP8`%#3y6FEm^!jZ4ztQX5mt3#^OYro% z?CO6ty8X}SHD~cg|G%NvoMzmUN#wni!GXs1d&9#@K*P#e)sAmo`G@a8Ro*j(MBY_p zjL3@%@v>K$O|8>^v{En3xZRxvvvHptMWjflKHO1AWMzs>rt*C3-l}Q**z>;g-N(DE z5q;_0&reT%>f2rXHQM&$+dIzUZJ+ofmGe60;mqt|F9seavv;eX&(Y#cG0uW|J6z=Y z-Q&ka6DA@bV3SopkIEK=eI8S+ZTdX^uST~As$V9xo`rpRsQbF<%apx$?abO8{;>0yXsPyf&V>_zc;XR!>+4gWOKRD|KCu7TbGvgTa%{0@|GDG6 zIlamp*?vq$MtZYr0 zpdaF_n%Bw4xpV^{Kkjt@rKxQ<$df%^Ez#0u)n)cS%<}ZPp!09?5;{M`L6{NlyN7KKKU8q4%!UhF-c1TTab8`r@RtX_%E}`r}e(UH^&9 zzCE+wzrKChc+q^{_|hk?i&|r`8ltedfS;uWJ_v;!+7O~u*VFB|G-fS&dg-ajv(wI=KqWw5uKqfEQwkuHM&t5JF9R-@I!n$Bl zLgs}|;oBp+pHO}D{$!loj^4FAjQ{3Qidrj&}z9>_qmA!NV;klDNp`=S~{r&7^5wItEH|z9~ z$jT;Zo0PYW&pYqh&9;l2MFb@cs$894Q+=%AL)?Hq+KwaTqJbi#uk3K;abJTrrGJH} z80Pi&8)L``g~vuLD^!-wPF}kA6lo;{;$ADO&drLm8`3MPH4yjF`bC|$Q)?<_ zYJ6OJutrIa`$7eCzA+MHMpiYCEKgp=!K+$dPTPEmmr2s1WA#o`G>fzCvwL^xQhXX_ ztS?}1aJHIKWlM@fZb4I1fTX&fX2#d(P3bqfDu=s6Gp|z9mZS%cXgGrv;oaCDLILKI zuPn1`sItoYJ%?L8;W>p@(+(icXBXNHWfXLe`3Qa%q>pli3)kD3?V3)0z@Uk-((=cx z2JQCgwG~e8WNY5VOx)30FPfjM(Gdp-j!fS?7(!SoJvlv5jIk)J{>5#cVJ$G&gf4ur z%x6wfLM6DMHFZa8jjoilAH~?P4rJGl+QsNO-lLjJ`&Ceoz{^8@a}eo$apT67f_b^s zV1+|tbrA++`jyrsIc-Lrq2X-&b`)4${%f7hn(4!|_VYJ!kQv((Hb?V0kxJc%^$wTD zAD8{ysm1d)5R+}@D#gCmS=l!@|D!bfT2D-GaH+L<(%|*AL84p9t#mP7B22i^Z1=6J zyS!U%c1Kf){ofA5r=2}tZ$)ryv9E2O^(=n9{g2XY{Mo&qUz=ljn@BL*`2n$S42pe| z|GtU&kt5$)Xz5J>3LK@`pFv=L;DYLWwx?@pd|T;jor!e^o%7eCJZtkvh`(H#Bq%5y67PVGm- z+cDoKUi|s_{XQ2TBNk@23KZvbbvQ8M_f3*2hZ@J5^Rz1G^7ubd521N!i}dSiB7fcH|I~l`QUMy3{OO$cvq?C}ax6zi zW5mNc0jlA^4q;evP!IbQwX=dv{r?1`uH2^1#0NK9mUt-kjkPO1lt4koF*X-o8fQQo zy^bx!56}66bPeN8WGeBu{VF;Fzm2IJEMZ$6lN|IbcTdRqq;o3rT4U ziEB8cUNVG{QG66(|9T3uFq9%VWS18|phQk78E~|`aj@^m*LP1Ye0p^)YxX``%`Tb! z$U)*$%0|e+<+1Z`uLevJ9vn@6B&`3tVo_N0V|XM#QY67Vsn{%YC9fb-0Tb*M&(@8% zh}1L3WW_=ZlRe_PJnLLzej-V7ZD zl_E$}5(vG8UWEt}QNW5lAY#{`sE8#e{`NlS?DwAc-f_ph|3SuDD{DR9 zIiLBNxyaHz;d#imLY|Y-OjJfYk{KypsJVE!(*?o#Wnb7cfAj=fTa;irR|#_Tn^k1R zU!Rg}iET#`>GO#&iJ8Te2&I$;+NieC_VpQUf@Ty*(`d;HCh2DYbRp!#yS&|znl<8b z{%LDtbju=v-+Tg|zC$_hgoGmHWN;}6OtfMF9Hn9*sQd~-nlwUz*#OXy=wJ!NsQ1`# z)saxc$rsdD@>Njud{WW~mXsJia(;J}bNB@8P>XWa#j>;@Nz5rC%qDbZs?M={a)QqhWGU*iSWx{N$u#5p z0da?B_ix)^q$)v$R5@W8@0$JMY(b~I1-Esyo>UT|uUnMg-GoTXHwWq8-bj#MoiC)k zOnH#zw^uYzef2Z+Xz%hJ(dELywk?MXMz;ko+)G1Bl}|ejtoOKtByMT^b-dc<_Xkg# z6OTsGk;Ha@>uWvL;YwE5gjl)|XX&@ygqL*lUZvCQq%S=OBS8ah_$6ydB`qZSxW?JL z3HiYRYVOK8BM65myi{dzz=I5DKH^xvMX>FHbVoH`y`5ID+2sZ$!N0b5sZd+xl5{z@ zaP+qqNh4u5FxW7neo&QVwDV!H^1Y-@r|^WWdu!C?w(S`IwMtVv*wPVX)G=YbzEZ)! zbmHMIlXl9V*@e_jb;YSkM~lzm`tMFnqRW(P;ODA_=}v;_)YQKgqmF4ixm@4T^tt9Z z_1G4%bm4pHb1k>@m~M>Ajlf5r>n=plj=D*%w&%<<)3eqd}Wxg~_Qo9W6r>3JV zzBJC3b{TcM+}soR<)5$B`9`b~Oi@{)Er;2j3th*#HjS1%h#hrGMlLG?hT2h4Fw0}pmd!re8JoZPwLz$g_ z5~{Z0^y_QodeZHxTM}R0$~FvNb@k1IqPzS>Py2?Y;bqD+jdQrivpr%A*o?A~PRHJo zPzjdL!}&Y-hka=pw_{5l>>fR5NL^CqaQx&|!^I=VaJ%>3pw004fmuhgfR z^!fJL-NY9ynx{{`x^rA>f<9Nm$g$)%xH~?6n7sE)yHc~q&7bk;-YbT+%A-ZlvS*VT zuk@TPhz}JEqlvGc=D;uk2Nee^h zbWCL;B58i1i0G)9Oi;=Tzbx z8&)|PQAOLbc~|+pTC*3nL%(rR9+|<%Uha;#2lubp;9(N#0gGOZDwW&;nco+whuG+m z`JQnshM*q1)4lt{R7{KH;nX=zmckMeZS*iwh2wI|{J5=2&az_GnJ{C4YwZb5?MRE0 z$fbIVo|Mf={!Aa5x4XHVl80{5qsBUkg#t=$vLU}|N9hr96!E10DgL}e%=m%LT^FL? zZaj6(r1t&5w8^{ogR_o0AI{wMjr(wRKDzfWZ1~-W^MZVxj~A8<$EIvT>;CsyROi#s z>OW`E<=#(MfBkb7h3g7=5XE@mFoM`89Kn2QrWk)PZrLFvnpayHySAfr#o<3KgkV5D zPzhitel}A9n~|NX|2&(--@U^l_~9HWX;FO92&Rn^x*gW2gA^-r0LJF+5Z{2%t&-T=Vz<)Y#}gVa`xXiu>a?M zY%Aa^U>8vO|2ixDyTS3F9+ZE6qj-s0S`CKT@E@_z;N1xzn1XpMi~hf2p;PR91;fZf zp{lqCMH~xFjGk-Pa#J9<{KE-*OOaIFkr8%X?!-S@&R#QSZkd(dx8orklf8jw5*Dte zJof##5lbLZ&6Efjzy1tl4&=@4W8zq-^rmml*cH~5P0$=~vmehR@|hAuN7aA<0gnk4 z^=@DP5_Y8;uCwv?+zRghaarI*#ge zP_c!C=J|y&B73&b7GfcJ6q#>ty@o?KHrTPGlne)eFlLJk47MGWByRH9H^SP$VT`bl zyJ77S5YbThvCV828?4>KUXVHBi)fh8NhO69vvHACQ-nM!38G2e{(4fI!s1T#q-w_o z?^dTic#^^$7j22_s|hwNN~w!ISS9cO>%~!81=J7?&-g)yN{ZHaEGZd?IB|*hS)pP( z5{0fCEll#6iqnu03c`L?coIp4Fo6>G+P&-z-AltI279mreIofYQd_ES7@|*I3PUMWHZ_$>ng7i^b`&*>6i(zbh-dMYK;wZkiW)CI9-hsijs;q z$TX-T^wos%uJ~TU>KyW}`Kvw26;AMXCok3UZ85$zE1p>ES>H)rsj8J}{jNgtwC;48 zH0U|VJ+q-$o;S|dpB5%9ZsY$lV^caCfG1y>h!^A-4$o%}U=@rK4F;EPYpL!dOZ z(la5>(-@IGUpwO^tu=3uER(FzC0qnw?x4Gk>TkEcVDTkKW(cX#NPes_8n|ZZHt#=3 zZ~ft$Hm37L*4o)0C?lSjMpbRKV)vFS;wC}bh6ZR1Nkg`cc3Y~`Vc<|&^ynv-?P zMz(+b!6LCn3Ik$~VmV6=YIazJ9e2$aUiBza z!CMVII$uF36qZQbO;RA@{5K+OJ5`@(2Yg+zCG_D%Af<48wuLfL--C-ZH2P%2$}E+q z;c~E~Fa>rZWrHSNGZF>K7-KHl;7pI`ntUvtez>U6Bg+x62nMZbUN6L-UpGWa%xSX}fHRiE1|A>FznjoEHbI20_WPhLPolkB=vg=`JvH}u7ooP_;y z4$S^a8InlPh(e`3Dk7YHu9MwzZ!k&15N zRO=y!bsB_7!x|Gvz=e2h+6qoubfFWIpFtz2p7z9?*&Ak*hJ~3W6z6>{$8E{Q@6qI; zXLCS7n>O={-bR4J0V&SPdtFT9jFFQk!zAh&)RSv8imeh%J1c{3Y4O&SH$Y?b?Y-Z) z2CVNeCSVS>WR2@I0E>`vi%Olp;rgv!$B?hRj#KuApshzrB1vG04lE@5r`yoH?zCJ7 zVpx|;M$pzwWh)wax>utLJP%aUo6N?Df5P(I#VKfUj@F<7-?#pz5Ils>L8bwVW^VHe zde~&cmQJX0=kWvGxV++IGRBcKD(xzKFx47mDfS^|4>x8kw~&^WYHeU!b?Gc{r`Bq+qr+&lq@U;#FKhH)&^-9IU&k2;1na18jF zY|8TG9rcSb;4`~jPDv#-mUbO5`!U>^W3=<`mA)?0cvo4tb9K{=_-He?6Vs=qcQ8l$ z@{MjqyL%N>zt=i4Zc;IFGu9}gIYeXW(TG86VZl!39uMNY z@e6Y8=W~E56XAMdQ{QUWlQLT~2jSqGe9K=8n!9(q1r6?-O5k0QjWxC7`6m`;{(6D$ zF6L|Lsg5iKC2o+Dx_I61*5~HZp<`bNlQ%vc`P}rMgLX9_7w7}}pQcazN(JXHP;|?G zHz@pX30%`9hk!wqhW%HdX!0J-syCa;vJL#-{(Ddm1DUUTAFYjVJ`CIY4^Z?kKcdMi zA46y~OdPT8aHJg#7K;l107WIEu+&8)uY*d8<;TwDXg%sl_*dF0tjrKXSb)&UT~0>p zt4X0OMF~^wgWOP`$hld!jI)1%qR*F0G>S<0uG{lR zLjupQyqK)+-83XOG_f3`)%+JIn#rnt zexuD(3>5wOkJBeMeMJ8PiYmkk{$Bw_|9?4s|6%$>`4F=<6By>ljg}jK{AMgStu;<9 zH^0A#{QqG3v}MWrk9tyBTizb;tlRUp=XlrORu8f1a~xDAQhwKarpXmjyrc1~U-yC+ z|F$Rm_ZTfp2N)G^S3O1_ISp?tQm|csLif@(4}bTR02`op_3w0v+smCib=Pm#@VY#h ztMkL*VdzT>oyNx3gu6MRa5dtS;xetkItv-pKoj-{u0LProC#pX=oXf zbMWbhEW0U!QOw9KOVOQ>26%1X>TOqz=`&=i(-kATTjpEOj=5W&Ou6lMu*`VMAbab% z33HA3v-2^pvQq2=w%z?^=WcWI^n(KrPDUWoUY#_B;dDj(;pYsv-kN}=D0u;jTly^p z8yp(p!?M1Vr9BtDF8jVzP26YxtTKXaZr5~BZ~b-Wmn&&Y-Swx|-yRzDxJ2&C{d4Kv zsZl)(K~HmN#@ln}PyKucpR>-e=jnS7QEK4&zdoP&6g&K7)@hU1>RrG6zrWrs5SZJ^ zQW>`21)d3q))pc>|3F0kc=q~CX8G@*^W9RSUo%9C==beSESq1SKYbF3R)Pw@DjSmX z1^w9oDrfcXcNv)L>qB>T(tmU6uYL_+fYmshKaU<>4AO7D=f%r)didL#~u&v z>9$+1BxP?spoV^7I{edzn@@}k+nIzQZ(5mAlN<`eh=><#e^k!qV5E0F*JWJ&az*lx z2(U}esnFv0238ixe3L>mV(g2<=}hEGyTY*9xM7k(RzS@nu4B!?@KR+-{E)ip!`I^` zCr+29o_V2ib8XD1>0hG4jM=1JyH|NWwKM<3gUWR)ex(djeWQ|#GpR|lP;a;s^)tpH zFLnp9O;g~Azi7Yl5vj)9E^6nQd91H;bRMa%d`m_6^}wbo=fP=DJs(-V{G(5W`nv4^ z9p~xN`J}_Q9!C+G0n!qCD2)+sqrjUs+iHHEtlzq-`IG*diW=BoZMsUA7`^BofA~v5 zbJK0WhBs8Tj5~#B-EPypv9{@p*t*5iD2ui;qH7YjzO;(G1=ycTyhECme~~0ful-RufLekm?;05L#h(5fp6Z-DRq%LJx}m# z^b(la-V89MwA1EBz)a{l&-TZq3lx3SP958w&DhG$@9#}L628?OS!)UNQmh?XLUNA? zb?Igc=JzZDsWFl?nww$z#m-%@dJ0;%zR$|6~Bu`w?In{sK%_=@R;=%k_`uat?0_zpmMF=`mU(_Y*7FvRJHz*({<*#t|=)2jz-KkhCM`ixcprjqGhODyJxb zWecK;=k)x9kQ-h45O%|ucHPTI$R&niH=C?BRGM#C3X-uo`UFx)M_FbrjP6G9zz=lv#`0&t$&$?u3(59hqh1A#sgfqV?>@XTqz72Uz zN4FJwPd`L8(sRBWRYvWpP?uz_Jkz4sB9r>V$7-|>ULp>EOg(S;R9J30@s0F~l@s)I|*s^wXjXc48V8I~vGp;-pw;3kSGmf@p}&4ml# zO~M?Q^@V*{P$g8agf5qw0MVe5OR?Nbn4Yx)d5{51J9G&C_mMPQD9qM9f+XTW+B?Du zvZvKyx};$Z)uYg=FXmE3&5HW@bdco|6Dnf{RZgvY{VG;j?&dH2&Xhxj`$yNZF(GZ#4``H2njt)J$3{EAXhuBCl3vY;qXl9r){b2HiK%IJI zlX#sC59Dz6Q)#e40b+;~!XlwVY02euv^5>tlYmMyMYDMbUk*ZY0!?8j>#T*@lF&FB zw3LS!PCe93f>6kqA$EKRHYR`>fc-2Ek^=&cFiY&skV5Ca&q+e8kSt=L0>OzW-WtQ#>! z4Gl#rCdhVP0L}2wlPFXpFT|QHP849G%wnE?!C12$Bp!sqZ6PxW;W$o$;v}Y(xVxND z%oa+elH!m+WIs9AUJP(#qYRCK0plUM;+%~Mx~u`}%h=7QL)EYlQ0#6dm%(HsDI|#R z1Ssx!K2eB@VLF>`*9cw7HLLifz zSsDSQkiiu+gqjc)K*kh1V!Vtp)dYJ6*%);pCVmZhv>q%>L*?;6xXnN&o>lztD;*!Xh+HQGo&kEgv{MZaQy*CUAkiLX=cKu#{8S0bmWy zTBUQ5zoEehd*nxxeM{$xCSq!R#eCW5tRwz@7U~XHUlg6JiEvf|9U}nE+3*=2Btko# zL${dWL_PgdJa4>bhHO5V#_U6&`bntE&iOcTR;V6ZNLn86z0IY!&KOCg-J7_(8~H^gOw1iOAhCYFN6@8iU;AQFluyYH32wo2DwZG z;x3lgie8m}a-heuQJYMFM;npdju;s>bdUi~IScejL-h;MSMY5^{S3+d-Z&gT_OW1~cj60ZX&J{#lDMdnT+O244y zqYm@~kc$m*1`~)1c3|9^RG)c>P222ZjQ#|a>A8FYJ=^3UXri!Y ziici~jkhZVHsbe|&w?6EFy%bRARR^7oqdfA8#hChe3N355zl0spK9a{iO2{XC%*$< zo62cA2JiOqLxA2K?4C9I4eLHaD@iDZWo6JC#?gU*wr(L>OiEqXuH3(lN~gDXW8+`H zsLqm&&)?JbeFAii3(S;{4M?j>I+yIJv`==H!zY51>0lFK)|lVEb}V4EZr}BT$ae(P z{q;UyrMi7`+15g~~*0w(BXv{p@|9Q+@A=U5aOFwg=sz4cZXAJa60i=@PS7)?q zFg?5$Tz==J)uYj5!8R2sh1C8ZOf@n4lmtPJvTh?!fqQqI5#ic(v5-fDp+)v!B0U60 zQc=!7psJGkE0zA_s{?@taZt(_n=~b2i*W3kqH3_f+59Ke^1jc3qHVyd77nQK=r-&hbeKtH;FC7e|gXVk7|3CK7htXcp{)PVpwpiIum7VSFsNcfj}unHDP zz-LbssXx8LF3hiJBSU0`=(#BAIyp->XjsZiOBa4n(@Uq6ydcz^gON&*cNa%+-Lgk3 z=+u~1a)I+r!i zMWG%IjTiTQ90%QBhsSYYcJ%WP<3RCPjClewQzV47<00|fzIHC$4sc z>4dsjBT|=y;$wFc1>kBzQ6idf<;}$vtpSae3y*3qh={&SV_4@FhGsCAY4^LXw?tG&V?UqHPpR{9K5ra-l1fX^{ zct#N*(7C#F8J3xV+|PwK&lg2fqV~Nxd^~NKm;-DU9JHRTE@eaQC$HIZ_NGsX8LLRJ z;t0m;z$R0N9=GkS#=y-FFRC+eBnCMFhS}6m~ zTq6?8%`IQfR2nA$XZgb#6QU0~z+yzvlQtLenBsjpCdjSvNOL+elM86)qQ3f0)eEm= z&LZjopm+hCk$@~?Uzs8Xz{3vB&=6@)sB_zV`8)8)`*aP6?+C*2TJFU2>f}IrQo%io z{$Rwlb74zgLePo3Iv-e-+_!4;g~br)I6{CL8(CZ!eSXoZqQ~FuF~*pjKmZh2m<*tG zLtCLpP6Db45Y{wimdd!r3P$j`3D^ZIF`KGiQ27xD!C@g&0%j4S>I4;!X*ybs2WMS| z_tKGGjH^a1;OV9-`>}vxHuz~T#0~&@(|mpZJ*z0jK~%i1m74JRCT=7@H!@E z4KvMSzb$|^SOTX+SnvaR(2x*mj6i~4v3Bh_5hXaRaXh=5hmaTaC;3OUk$TJVAoD{9 zKI;|`8An7|AVql0H3May0BSVHd~*ZuF++15F~$mMPWP=+*qF&#j4d0*pT#tC5Hmu| z6b+uo!%PWSvI*A?@u%GzFll?@i(61{RMWg(F~<~Yq>t{uT?gsn0VDk~Bhz+e1b26n z$DrZo#{Kr!kx#yiMkd~PSjX7MIfQJ=Le|Y9^vGFZ7yV_kq-|9o*0lJ|Rc1RH%%<3I z2DkoeW@JDlXht}Q!?sivz#3^V-}68nViP+x0Y}D!t)S&O2sn`rpX+4`5ZQQ^+9a?< zL;&gnGS`fo`clPE;Cp5_@7<5R3HM4lbsYNL7}zhS3D088Y4Aom`c~S5=isq!9_INr zR4g9k$GVe8hXekw8`G27!u&iQGsZElEXzV-xFJA@G7_R$q(517ZOG!scw4X#N=VIjrx zpmRjfH3pDM!X*2SQ`i`z4Pf^MvxBead^lFRY`EF1mEx;jJ{g>K2^fJwmE+lb66WMN z#@fqLwTu^E6Bnn?FY4S{e6%O)&HcsA&lab?U)QLF1`4Ibaarwc>aRN@GOSV81ou<` zPo}R@imKs*G(^*dfWECp&WP~XM(*9auMoxbb$?th`kRqx2UsG`a>!fw*^%K9@dnG1#-Vmx2jX`?)RlH zMJ8ATlEDwgY!xR{cQ?#gpue-A8 zDi&u6OU|u#&b&>zw3uwsp7Kt)E)ZZaoRgO=?&ZxeE^$O4aS#s%4wMTmz^FMcF@W}k zSXoU;mKjaMxk!0KAU2FSO0HG6zp%Z?b|k-^u-W7Ne8LE&0OS+8nx5P}+G?l~%PL&h zw4>8Uh12b14;_xd1<`>v-%`W5R2C{UVxKLnoJ`}As_is@FETm2vR zk<9b-XJ^uWuV4A;C%k6v_HyICxUiD?twCIpt!lvM$m_LRca8VeMNKw0-;~simDili z#tx#~_W)nd&zz|LNIB%Qo7yfbg8Dw)vu&AnAMCfjyxHJjOr7%Jh#o3+iN+4I+>!Nk z`|A70ZVtp_O-Eu9UqqgkJRhLi_jx5CCEKbw;P?8O6G5}5<#zqaTL1dt!Se{a&9>j- zwvvWH=&f9QyA4>1LK^-W7{MOCz4o*33XJHzRr?IV?Bwtr!%nWflnq4s4AycffiLZ5 zBu$aCeL=HTe0fP5#0f7YJE{;b7&xgOY!T!fHM7^bg17G|1=g@U}HDtpq);q;Ro(+-=AQjTU}d5Y0EI`hS6($oLk0f+%)0hyqTe_8#F zvJ>tt7qUeoVJDc_qZpQf^8Z>3{5LP{zs5HHQSgH#HDk(KY!i#Zd9iE4UHk@e?tdXb zYr7}k`cqbYiMu${^;g0FHvziK=ry%zu*YmSmy_nxCthOz8{0VlaV`$TM4G_kZVsU#Eu~Ek0m^H z6*(a2%zrAuHlFmek88Y03{I6<@7$0t&g!UVnd81zvqVQ;FP4zT*Q85ium8>Jq&m9T z+pU_ayBOVXcp=W}xcCu&AHsE3inBVAJE|$>(ps5)FL$u*tb4?jV6Ae;YGl&YbCFU3 zJ-4eu{x;^R9D37LLqPbvsEEJ6JEnU7;UAv0@I4CNB?n$TDs#Uv^1ok|sf+txu?@@mlOM-}bUXhQ+xWj- zl`(xU9K|~6uJGmj;#bCSF?}oJst4b%{2#H6{SZfLm%rQ>8v~-9G*OgL33J*Nxmu_h zM!oyRVRwS)TevLzNRY`u0yxK2S*%<$R-Lq4#>vbk!_Q-jX}ST(v0~mAkGX z;_dY!c)qjRCr<2@RVp#1{&>zF@e4_J>^QiZx2#~k_s84MUwP~AxD$Fm$BYn;{0|qT zj{d}6`2O+dC!Sch7xESN4}H2!Y|HvI)!g~(7$o4BA0D^tDb|<4{eVBap<3GmjAK(KtJW1k#pHx+{?^OVWJIF&w3r}tl(nh_JcVG zC^Zj)YYCYjg6J&e1~LpKjKl;B-YbVQ|0WtY{emNGwe8R~2`n+A4&|O^D0xAcr~gD? zV>UZ1qaK;3+c}BSud>_Fg~=z?EMP=TXTG}fN})3)oKNEM2^Qi+V|=@GUTh_H09&Bp zt)>u%Fi`yS0wjZYA#vW>Q7TkWD$NO(cbFXB@OHLL@dW^OtAS||jW0^WsKW?YCUVWI zOyy0O10=w}d>H`23+?3Ol=A+y7PzD#kIYe>JY6Bn#le*ariu>8sI~PuYulz*dbRRv zTBusEKf{!wJ{h&%=}1{iL#CCVH}{3+$OtgqW)m*A5|i%8;2U0S(#Z$vM2<*uBf|-n zjRo#COfZoF(Tt^u+$sVsC2M_Mg%aNz@AUghXYQEz1 z#Ghe^WeWhTCS*!|i_P1vP_JY9caxA~+!_K!5Ad7l8{ zFWe%L!-g8p0>EKdooyS`fSZ=W5VBaH(t92V<4o?cCL?4GE1|OU!yU4dISOZZtnAo( z5VZy#b`lWKAFXzxIp7%L!scR^n&g%vTfEJPr%`V7&kfiw5%{!9@$M_WY@6J$&1W9k zQB(*3m($0wrA5$C$YTF>jIAVRxUk+)e4;MYg*g@lmVQ>3?M48dwS-bSq#S8J-fn}O z7%PrvDK#R1N@B-7fW^UH1B`9_`lAF7S(Go;=5PGK!)#&+6xj)UV`)R?PPrUKU+q!d zKRQgWNRV9V{C*>}8X~kN3{1r^ktXzlopJ{h%IPdc{7Ui8toB;O3Q$9JfgYzYa!p)p zr?0y5_?bcu1}D^K6p>0XKLK)VItA;`E)vNcE#eD!I?jE0crxgU5t+_s|qWL!7`=AW3Q~WEoM8|2z#)(P#ral zh(5zmplI6@u`;ZH$vW`L?}81u6*Q8(czy_HCz($|wd6CP{gZZh!$gqSwu21`9I&&b z;_cWluv!|_AbMdQIkZidNgCF-BcTatNAC~e#&xOW+yJbG?Ah(M1l7v-yM`7a>3B!O zSSB-oD}bn_orN5p18@D6gNqb)APx_|3}Y*Tr}1EA3TJV9?3wvI_Qze%1NJD8zsa(B zAXasA9N|}v;uO0}15)`!7TW=x%1?!^wG?2VG~uYCC%ny9--4azf#4a*fdlE4xf1c? z6}qv>O*2E$re$AlI-G3Sv#WC4vq2eseEbyNjD&JHP^A>{^u=b7*J~vipt3sq!#4hP zR*XMTp$7-mY#l~8Q#qp(x<5Ck*+S&M*qxK5^Ec&BmQ)@dksRXL;yt|bA^|ms4*z5F z`L-BYY`DUYmyEoK4TWK3_4|2~EC~Lm6#em6xq!6%%*K^cLlyv@-T+m@iOUVKU^s3K zx{bAE-ES!j#MEY~N=qSiR0BX43H=&5+ktkGIh|cnz-@Txl0yUEA>HJm9wL@?3C_f= zV{Db2`(p`MF-G#6_H`{D$Ys=8X^=-2ZA1Z)4x(H|H3s*Mr`HWtPF6)J*FGCuDHcsD zk^KzeO(HwFHM6dzRi06v6kS8tUOa$INOi+^F?{OvBrZtXpLZ43rlboojU-Gd3D_Zw zc|Hb_2E^|C?stU+wB=z`xn46|1@X~QosB$4LgfoF>t~#N#78O`SWJf{3eg>mU=bNJ zDK1zNqRx8nK5GnIib30AL1&_qGS7(V%!mqs-}k6oz4J)10Fus*kY@)UTxN3Xk;^F= z$CkmyCg|b>dL9k2l^y)YJ2dYv1R8jHg7R_PRW~14Rfov|Ao8%l3}?uzC=^4ia`P}a z9;5>h+|MZt6ydYfX0xbx;LRBC!#=QXJTS8p$>fO@cHk5qxRrzsV+4nop`-mn`|%)Y ze3Zjk;Hmsyd(Y@nIKoyy&0{>@ayxXpyQ?1 z@B^3S4qRAr!m;h&g4|^U4&x9e_dDwD7-A|RBt?kH;bG3zBA@4D`3b00p&!ea+Q^5@ zio1L0pcxuil@6LBp|0@|ZQ_2S*wlU@O3n*5L=F;L5SdOebsFq!bW#UCTdcYVrtC}S z20~sT&e7oUv`2Rt=R)WZn^LEi-KSRc068oDosFz<3M6TCx8J{r4?OyU7f#%5|;@z&U&Si zFhpTZEaUJHEuPA#Y-K zS(H5JZ{rb{1sIdY3B_&QNvT3428v+g5&l?^0bXoOc<3nt_3k^xA4P}~DvG%~ix7G0 zG`K$p5n>F?37}@yz#9c%BVo|MB+y6b)9Z~mEV}E1SU?bjh(@9BxmSohvKU|{#)<=} z9M4j0fY=QXS4#wl)sP=jp`5&xx(HwVJ~jg^VuRW2*2V5TUp(-S<}Su;L?#7>^-JD7 zPSJ{?-mitLkbndMLaZSb-Q(aGoID|1o)=NdE^Oi=sWhMnn{G}6u6t+dV%yGoBihI* zRvgdP`aCuOalt3Gv=-UOfZnb34`jO(V*_%(dR}u(DbG8?W<&2bBCW_dQ3541(^9YS z=sGsIos5j<0+Q*a=3E$>j_eiJ;E|B~GLTUg@OW%lR}mH(&2-2MnxR+nob}Ew1zC&h z#CV7xZVUs){Ia>dT%_fBPt(28+pW?S=CjV2GPnQb#Hqq5tPw7NAZ%a=|~xUdaxoo;^(Jif=9d&%{3aqkVefU4r1 zjc0%%h4J`fWlga~lXX2O-u7;I>nA(gQ+0_-Dn5ZW17epcw`&i3tojW#olu`tGJ6nR z%?+rb|E==F3t=BKkT@% za|CmN3LB&H=7S5E$>Wpmf=JL4BSahtz3Jpm_0R-Gi*-o*Tmf>O_F^ z?R0SbEFu$+I*f<(vd_;n_Yf1f=uDs6I(j%R&_x0G=HMxn6;~#1&seB4YLZ#&a#Z{(zk*6|OPpI7M%@fjlmy#Og zAOb|Ng9Bum?m}W6y!nXNc+*0w*@rH zDN+f8c92kIX{bd)Yq=0rr5F%|^FAEEE7hxQTIztUAr{I1&Ym6qR_X}0(eaT7FXhh^)tXdfC!5spe`FT-3;%V1ziJxy9HnZ zU|-((q=1H_B6i}_2GmI{w+>;>O-_i(=G|R9Ot^ean-D`a%F4|;EK^q4NJ71S1*Xn| z`6OVP6GrCybQ5;O#z9*DM<|7MW3LP37%?6H6%{2&q+r3@wp?(yeXRXhbpGe;skK|+ z%W$#R*YqPBCUMdKn0|$ubfPJmxQ5BhE8Lb@X1X*N#yTRyE7E(guZIYXGXuIn6O@(_ z>g-**y(cc?5K*S+MjpZkADK2*As1mQ z@J%*&l!UoPFJ$sC1xVC8(KyCL(R0KIeYPcWW&0*Bh8PSGLOjxvWGOgeG-Pm`_d z7h+7{q6ElT!+GZ*QnTiS%rIh<4gZ-sr{s=t+aplGMih5JeFe9x?ni7f0rC?<*BuUL zkD&wEg(Be|wOOY)r%6-aW0W+|-ZWGg7Nkl->-y|C*^=8qhRy$wq9BkqdP@(SlLuDO z1#g}_J$8dSi^&l?CwOo=55uBe=-_Z=c~4Xy*!Ic+#TIwNnp8JA+#G;PB|$byq=fO} zO*bCjR9Dy{+H1$=VF;^LHb3J0#~Wsi(FhBax*TYV4c6s(o?o@qYju$Hc%^sBZVR6R z4;36}wS(_l_*JlQ>QD9`xJUI?QvFGLDS$&fzED*`e9vr`6}UAU~< zT1o>dKzBM`XSE4Yi!QK$gq*vZcgZrKP54yjHB<)~EJKG11JdWpVa_izWU(;e*K#He z7>V_<J9DrITdb!w3y1N1n#xCNo6VxmSs&F1CLBs;T+?e&Izb&3^ya z#qrfe2RVns`vs0)Pc{Wz+b>#7*uRGQ_|59mn>>-NL*5!i%Fed!Z4hL&#KtbF;zvz| zL$R%Zj`n!6nk{iUIlxo8M(F+o0)OIf5XJuyXe51d*Xn)UYs3TJPFMU0=>2ph(6K)I z=T*^9jRO+V-p0 z!;WjSI=+A4D$9N>`)9SykMU2x-(R!;F!Se?=+CMCUrm<4tsID}5d7nsX#KeeaCE7F zoCB6n&}^U}VHj02f3DDTky0$bHI(1r^}?}ygVkY((vBtPDy^+{r42GsPBmLYuCmtj zmv0nr)f(aN4jZ|Kw2T@VGT#<+tIecfqeGMTn;l)`<}F+I7;W*Y_Bk2O@>c`pwc_v= zX9R5f(bJMst;Xm&dzfU%m}59wn*BccbRRIb&T~uoc)e{W6dn?ImvncG z(PomWs`QpN>ZSJLN%Iel>#ZTCSsQQAR%34;bI2Yi0Y{(QFfhKBzai*bJikD+&Cp~^ zO~T#@IRm%*?t=qSg5m65-NR>$_dTfbd(`#YBK`I)*=W6r){vj6AB`)^<2U+8eHc+h z-jV-gcdyD1IdtixBHzcPKHUa(0tly=|b!_Ra2=Z8n^`>%`yTVid0=VZ*-e0}y# zZ}83W+{sHnI3*-|2~%BU&%N!76<0)#5QAgCPW^PVg}vFfVt3z>f*k{X$(`$0dioR1 zQaS0pVn++8D4*^t>fjeDIKlr@O2{}b@}Pg<9_Go ztsQT!S6`5mIle`2LDcn6u#dRBv$Ah;e7pT{VC?|_23yOtjjPBC%*1c{}C7^olF9AA9Hd6}jwH-^8 zV=1oGTKfT-khaeC-Ie|Hy|=D`kNmCS{4)7_pRV6A3ZTbb@tHSG8Q?r93Qse69RF~- z=H8Qbt>md4!&<&Ufm37Hery&!2cfY27$PY7)rQ)~v3?Xk)2N@nBmy$?G=x4GTW>0E zyO}kq9;TCnyReYl=%(xOg11%5;Z@yMlf@U`e&44Sbm*qdUO6+XUXo4yWA@VO&dzFD z|4{omyCV7@`0|n9z?+Wk_<=9>NA?_ksPitC;NE`3_sbrK5^K4W(T!}6z=?b1rxXTW zHx@|>myai%S|_$uE*rl+o?qk zzE)bJelP2-@f*;@>f_6g2~Cfjoxo2jX`j_4Zn^M+B=$QF!lPsN&JQL0+_bfUefhv0 zPbaId({w$Y3HsdZ2zuVd?@H?9{S#Nd-H*`_3!jS5wjW$5AYM%~{n@n7L^3001QJqK zU@hiP)!!7jUF)>Y{BZu&)!PF55$n-^+Zg{e$mj$1iEWI7|7~J1ck9M~Yzzn1Rzt_3 z|77t@Rcr4&fw_2^GhR;!zh2rXy+~~|2#qdX`9yF(qP%GU_fKMxlDSSr7)4BH^Tl*rpV9K2yF7{m8e)QrX@+JWv!KGor`D)Z1+umHhp!M*;_M)%j9$BBG{^J3(f zp|7j*9!+l#&uzbG{dp&DSwJgZ40zo3qovV>3~2qZjW~O0fOrB z7k`ms9S#{=>s50plDi{w9k!Ti?vuYRtiTx8nTF~6Z%sImp}BmGz!tLxH+gS~rtju#RCh&Dfstf-yT zPBlQuz3BKI(71f;9~%QUyt$h_=~4JTX&Uq(-eSi3-TSInoT^-MPCBwxs??jP#pyPQ z9)_r%$1t4u>SQi2ABC$STj1saMJL!2s(cMaj?fWtVi@g_28O@G!jw6c827XY z#69P6?fY{j0pu5uXJ!uiCk$9AOW|_Qob3!nhYeT~v)AE#XGi%4uQF;M7ke*_zj+9V zj4f?1W*&ExVGWm1)9gX_u#SZLUeIvtC`u-+)TD}*leU^8`_})NzTwgGEtp)TU{Vw0 zzHO;fp9Z=gJFaoJ60*NVAbC$fF;rcU(3>1lDW~U?Xp^9nmK?>0Vg>xfFtg(x{O~GT zOgGqF3E8|mes5ekxv9ehI`(GMdj?#0MeRoNYkT|~0bJ*6rDSM(m07&~7*Y?np<^#e z#UpdtB7<8l<4s3sne9@^oI^YNf+bY^Ctx0&^6kfS6|eX^N!fFmY4K!*7B)lri+EdI z2r}$Wb3m-)m@<*!1ut$u;mY-*f)wG1q>6KnZiciJ&S(%~jTqJm4Ks?W!#9)I4ATZ~ zxl}M2*M(@4E=#+L6)wuT%r00|2{CqvTv?*FgZ{v2M8MJ_C@+$re18Rya;+fA^aK~F;;LD_188?W{Gm>o zrj!r(avwy*nds;oCkwWSdR#3;H&Ah{PO!<=6)eu`l$Fko@5e|A4+J5UWwn|-$H2fG zr&Jj*emIjtg*FHDRZ-v!f346qJ+`4@)D*WwHf4V=oup{k!u_#qX0Ox@5p3NG)-032 zGgNiv`WvX}yxnFWT-394-&;9rk(=tdTR*NA=EVsW#=q>+3Acwi(SDU7IY?QRaJSDF zLe6G8qJ%8$(B{l&o7oj!f3fgm8oV?yX8}Y|!&f;|(sAXXMR#%I@co$AjkvK*Zg*09 zbS=oju%+#_l|Nkkr+19ySOUCQeZ@)8F2o>`${*F>%Xh>AVvf^o{o2zm$G30z*)#?E zjt~a>;TLmUO6N`B`#D*6c4OZI5t@Nt-X~pGVC>-&uDlw2l$SK#`25e|jDYs1A7`_< zxQ>p059${E*jLBnytp6y@c{#p_*#;t=mWlK&6K@9kfC(X>sxZxwvipjUbJIYxfPZ4 zZC@V<1nT+oa+;1gul?xNsvl6$(N4@hxvnu3Dt3dx^WclIP@rDy&MJTz zG}~FL$+wp;{@Cn(zSe%=b-Jsj;`uA1La+R*nI13SpX5$zF25X+5xTz*WO%55;PNE% znaqUzxsOI?wuZCBTz>Wq>Nq%Lq{Z>>+wuXuBuvpJ-8uHxKP`kiX3qEhxGT zhProZor?44RUjakggv7^dnVaDbId)X4BFffO=yEA+OtQhhj!3EL^eGHzriEqzh{`u zGi*T<>&uSqGdTX|Ej>PNqYTT?;!3 zR^cUwTg&n;`au*yQ1u~*G9movij+or=rM7q5)Nt(0SpBZ(u@dC{|Lvi2+vYsU;!+u zOE|k#NQFhcHY#v;Ba(`b3Q>;=BS%HxqYg|(+B8MQp?Fc8qrpyOXtHcHhZwCwfZiuV z?|qTVBu8hc@0JoY#vo4QnBw%%O!esarkL`v7$LCAC^Gi0e?)|_0Et&c@Th=8|7c5K8A;o}{qq=w1yBmVJY>G2ay@eMlY$&Gjx zJ^?WmKTS@U>xrM;;7JA8%+(1C{t0Y+;?#V?qH!W}D&hME&ut&b51B+jWGOu#zedJw zkm)(BSWpHX(|Z9Thuc)g!50!zh9a@HNrEQYX(XKR!-N@p(#IyG0z*g$5LpUq3uh#X z^(I`hNmdw7z9)hCwvizBF!9hrvT8ueWlnMeG$Z*V3MvtuLK04e)qoz6=xaR*um!XR zOGI}()m%>SHUW2cD2X?k_e{V&vasMI652ox!*81i55V2FNU^oO@0!7PX_F_#;vN!= zF$=iwBb-K2x_{j^&Ci4nkZ9g|k`~mp(oPU?CqOc3wiz5o2BbPDIUTA}6~tQ|kz$*97##_{7EvaLD-FQCb|+84fK%4gSWO1 zMuZ7{0lOm0$?*ptHy^NsbEY{OIkUDoa{)PDGIAE5!#skHT?@$F z$jIG#lDj>gyR(@K5@A3z88ABrB9L+D8UoeK5Wj}u5YQQH+yy2>K$9<;4d0uYcaawX zOGa|oDIy~I(n*M70*+pVJ4wiwZ_ZcH6wMyb|6&3=Y6^oW6{rRlsA38<U~@^(M9JN)5~@h4wmc-n zt~4UBG%B++#*?@gM&bKU+{|AfcW@7g@SitEwAr0&qUm24?Yk(XUF;iE@UX)Fyx+CI zjY*sNl#rovb+|5i_0quZe%AxznM+s^B~OZe*>0Giw~KPQNr`(zb|Ur1{1P91ByO86 za2r=(TPuEy`<&>pF55V1jN_fymFf3QHKf%p?1Xz`}*TVor!O9-+3g9&m(qR7zE#W%HSKc)l6q<7EzLK-3YJ*D7(Ah&!-c1EIM6d<+d4l4iCQi3 zt-oI^_a64Ku)UG*Hz$|&GO|+Z_nmJm9_u;R@g$qGH|GDO*x&v!CB&dw>ezgs2`;z| z2jg|sEdns+qi20tC)9_6WgkcmQHE92rgWsXZaG8{HM^%_$|LGvBSJ$-Zru9A^~7k& zqM6*7Kh^%ZhO7Hir4p2m3VljAimA&E;WwsyzNhLcT$Chk_vJz&1ia~_>3HQ_vA*D2 zc65q?AS^c-az$g}x+V8`Au5ApOLzX^vfy?fF@Cm-Boim0lg5!fs*?;LoC`^b*99JC zaa*nQBhp<>hvFd)bPsq&gou3U-c)%Vcrl4jCxnshn4<^Gx9k=XMb@Ml*@7@5C$VuK zivk_I_m7y8!V!#TxhTHllp=J>ClSsVQKhM!_rc6jfZv+SaLP$}mH5fLFo&v>{gqC%+yvF`jjG9(=oj(>@J;(gsmKrU;% z(#5z{9@!4y=4L+wb?l|K_?N8SvS+9iLzsH1nPJ<+EN>f3i0B&we|FBh8v(FV)>>PS8c1^BX3Y1g}4IkIXvx z>}eIw+eL0(iJvKPax2>f1IG#`^}6Q$F0iz;U!`9^v-cU7HjmJcAanu!>L(lkPKB;{pQ_F(PJeC(y26=E`o@00nq3d}`xAO#kUvLh zRy_LZqz-g@gM|LF5_KEbj{iga1V1^H$cJhdfQ*C0{fxM<)B(X4bdrkdS!PVYj8G+^ z3vMdTrQ08hzlCb$57gnh%L37azUVyV_@AX&o~9n)M}0&e!6izu+tpsB!xfWx!SfeE zQT;szyk*@D-rF<6HO8%nVyd~#QD}*Ym^|Yvk|-;(5i0pz!RG1314|@P9o9+# zZMJFXuM?_fOmR)(a)-cZBjM<2$uu zZqc|gGXizVBpl`}>Ug#(<`NIy_1x|th`u8je%iQp+TC9de>&_U3~v__ zaE`hE75Ng+91V;n)e3!-h2HnJD#K+v?w5QU1|!MG-QLy}Y>{o1jak85{n@rZEGkl| zjK=hIE+~>7?B6SjZz!>ag*KbW|tA+4R+9*jV{-!K#pA=kMH zHa>LaQ)O3Uy;%Y+r1nnO(O6U%YcC&L=ZGsURFEm5Rm%kJ@t-nv%8<9MCBP(~v&L+G zhT#0FpyDU#5y61vg8xYm^l9J}%C_pOz_Y5hGFP2*=h0@61GneVW)oONV*;dvQMS4~ z6?Gw1=XOVGCt8+W%SWLI9?-*!Uw3#M+#>-w(PMBVsEX#?yu7cVFisD3In+t zXnr{*ZS-qJW`;M4l3`f@Q9@b{rZBZ}-ksR=K2zSNxez5QFysu$rug&ZoSBOON)3RN z?l9r@w&j?g%>8t;s(YH*ltYf++C`eEh_^}ce0a7hVmmU*;6g~zM`_eo_S>jpr_s>t zg?((;k2pRIOmjJuw%I=lQ_8HU zD@A(?a|W)Sv_cuSOe5ZtA-;!=Ll0Vn?CDq1su$K8}M>3`?YU^RSpE*p~l=oHXtBUO-X36 zKC+?c{cG_JcRJn_aH|%noj&Lw`g^SBab20Mve>3vw;qqu>jLg?vw-4GWH{=*A@#wM z6MxqG58RDSms7=}!+K0ajvlR8@WNg5X&1S(bU?>U3QBu>o^b2ixku{*-|zlDKg7M+ z$V8g6LpY+&ycr;@yG3Y(k-if2Nkj+d^;fU-f>C&qVW)~DE{-3DID0qBY2>f_$)e7) zLbgf)Iu=(1?(v6xCf?HMjX%b#=$;D>G~%uk8ZnSd z@|cd}{pl8408f-RXs&zsCfGbl@Rz^9{M$_F8gAv+5|2hJDW|uwry9J^6)Bn9pU(92 z;Hve~h{6B<-l46eqyNPUfB&&gP0-8aZFxGITn*I|c>9v<5cN##&4b@E89!$G(qEZ; z)Oy{f{p|7D6TUAQdOF;tmIcz{mC*FP(O~sF}JyHPjCJPKJK<_iWlFjpt9M zry>cv5&)?q?u6ieIc1&GV^-31S5BR}Z5&)j{eX_38AV6*1-Qh)pSiiQyG?Fec-dDt ziV%R2OLsIncD(@?hWrpUseLp|urNtj1Ta5nPx#qi!EYBx>WG#b;qG~fC`;-{M~O?N z-x$$wj`*z=;HX2_KL;_{Vjjbtggp~>I5|ggrK3(vEPN?AscDe~yPab!s||nRbS5l( zctavASa9S^L1D;()BbzKnnTAqO_Frw5OaO8`cC1d}vMKA*@QHD5#JFW;i z_O*n_H=E)Cvh%rg_u`uTWmwKx`6Yc1ztnu?b8TY8(Aw-5{^M#lI*J1<|3l+@YxQ(DUBF~b$ynfyFRw6o#$g{*<2X+n&8j1@gO2VzCI zF@(72L(`E7qT4gmilB){U)EK}sb4h}&g)fI&B}z^)s#7s$2a^+_VDpm5L}Qg@-w(G^i38uK2ilu%Xk;ayH5G$nW<)ml8DYWpw)ws6^z8 zPMKNkuT!Dbzq4o$K2rHy)6-<4ZkGqc2|^8@x%3C|)`n+Th2!)6kM{5lp1T{<*jX+e zMNlQZSNco%gdcrx*qGbTSHSGsWYFaW*U{O+Lxq+mJB$EQs{^ttfrQ8=e3wQjtThg;rh z2v^NNE-(Py{rbJ`Yfg-cui)5L{pGAM&O2F~!QAh6eqX^>E|g7v8>x?clYMw{U7N|5 z+NgYD^2v?N$oCgMJ^#_Z`t9wLSPs(md|TLxq(NAZ&j)Z|oDe3{zkl?4Xz;q6^%$oz zgv5b#-fE?;oW21L-u`7YbQkoOz9hJgVQ_ZtQNp|`U`JABMBGSE#(GK@RuQ+PjM_@^;#*ZafU%bq>{A)Gv-ylAk)xY6>pdRFejB3?5ZK z)T{RzZ+IIs ze)g5#corh`&VKDE=M()++J;G83%?eh&Tj&+P?q{v6Y(VxW0B`mz_I=%MYA+)&8B zKVbj)h)#8QbH5uN`2Af8T|>W>%gu5eSoq8+-nZ{4?asDP9r zaj~p!;Y`j{Sx1veec8Kzik%*v#&epIBt?`jjOSYnl&Js=`8SOw@ewnY?TogJq$X-_1U8eR>?SSLXTrM$Ibx-9>Wl#R5@j z^)U9w5H8g*3if%A+Bx?KVOL-Rw(ayvh3(!mK$_=DHILljf+ec2rTU+aSSu{ZQ=d~Q zoZSlLZ1KRt^u zrl3=LDrrVr(EC1A;@d^aTp^dV+9i)ESd7$hYgg2~$`RKwhaBsO^y!!b5gTU?EnGNu zz~X2Qhs|?SP1SUvqUm{;ZrIjCxy(n*zJLVf)o9-Vjq82A@sDQrom$eKHFg@*7T_Y{ zsxL}l1k>aEZfC&wXXTfh?%HaKdpygW;aA(f_GJ0dV$4B7jmh*BZuGu-%%iyDg^^&R z$1e9JpTLA#-aVeV7~^sF=S>sw_7k1IJ)a$TvW1s^zf-_+5mctIy9rLe-Ul}>7>+#m zdX`lYc0^vX_*kT11i`EP+HrbCz?9YyQ+$2t*eS{GrG0&~@u5pe#%&@Q4$cmL`TAs= zFjilkv-!hI{=j=$EMU9(pqpl&x`LG0nO7n{MsB_?v_W2$`>*#tJhP{$=ds_$f*zZD z7aik&!?|oNs%kE{&I&s}0>PDnX8Nb&)Rut@Fry<+W;hmu8`^SjmkQ<<_AYPElQTf= z+%?0X_67AN#@1r_3~RS6CU$&}a+S~4x6*>=dOVL_RJCIj>7b@hRMxusffqF_nbz_G7*||X^k(~b!SQl+MG?p_p`heWJ8%A zfc~z|Y>y%Sf7IWxBh&%s-L0N>u`PBai7OvB8u`z%m{~qwTF*bqV*jbX%NK0y={yp+ z^0)r3+qmm!=1QEqS%JuCPnT-*3ZTC$*f($7tvRuh;NM>$w%+sq6+`}|{nn3vFyu}8 z9Yy}Zkas&4>oQG*4AzNPa7gG%-`jcP_Qpx8zk0DHwCpuhun6 z1aYi+NjCqXCGV-f8QA|k>tgP8zVM~IiiRF>UDF= zG3~?jL;BoQD0J;##aR1(a-K~My)$CJsGx#fZ~C}(!@jknE`wP*p@-i#?b@9zAK4E~ zTx}mpm&PrnEceX~8l;(jnEbr(rq!?; zd&l?ZLMs0s&eumRyAr!MkJSE5czgGz){cIxIHCOK_uI>(h**q=4)@o8Zj?}T)q|`u zY?ogf9&p<@5%u2p$uGeP9grB{GXpkC@*KZ~cM-@7Z0S7r(Rb^F%Y)yHgyoNBvw6-P z_=m(!cG!#kOIFx!BdmyVac%Fyj0Pvw-PyOagHS+fTaewA*!4O@^}8UflQ&Rdv)UIi zsoc72bl?!=`0&qZZ^Jyq-Cgq>bo}d%n_MiwodB5r^Sy4W z-&lvc9R6_z4YeIw*e%AE8wG7`&S-2k#Uv_IFomx)*sNODJixlj4J?J2hNPVc6cm() zxTr5R&E7w*a6j*;EVtUcvEH;wX?_voDW&yg{G&_Nzji|CUiE- zym!S$9{l87brW$02_2u9X)9$C=}phYc8jstsO2arMfa?$xf$NLr<|CgM_uB(KC`}q z?$@1d?Sn+`U?SxOwKxirLn?BiF{aqFS0E> z^$jKRaD(;PnMt4A6PEF-A>)WWi&4=X#I?yAqtEy{)D*Sy2i+Pu3ggHpsdvMuY8n8<(>{jHc?jGs4=1{BxE1?}Nw_V$gm2)ru z%}q4p;s45t)b`_2R^NQeB@L_G*;;D+e)6|UhjtKKDTwoj)CO0i2T!kmf6@QTiH5$5 zd}NfC%-F5E68%g1Zigf8*p-ZzW=OGZ&$zUjF-!Ua)2Ffz7_|R=!Mjn5CCXGb%ACkPD!hn1o5voLW zek^Ztbbg(X^8Y&dNt-JTR|%_2QU3BlJBX6BZ-~VR0FXU@Ifn3G=*SneiZPP+ zOp3dndPTWZhuhHfFMM38zqGms_g(t%bW&=O{6R4jlfa}9t=T-D0WkN+023|>6GLY) zW$psqQ8EEpP{o8vO+P9++yOBk=wtpRfp7JZDnr?dSZfcTD>Y|5I<^13&3T`86N?bO z6gv3e5rtRL|Rn`k3w}Myj)ixjq&xMep2YEr99qz5Lk4Z5O%6*Z-wiL zui9M4KLiJ<;9mKc({!GkLmLxdcz?E!OdHCM@`b=>(IMAIM}}}ANR}=z$(^aUdR)-7Mv12UX2DXRe;RszE%zi_l z3}<9a5IG(zpFVwnPSrTq;*owIJQKcwsID?7nC38tdG(5FCSkG(0O7tb&M zIA!5DbRTE%;BYl!y)A$*pQ?(i!dUTr{qe})m&eg7FXJ%jECK8E#Zs_k#F=d;0Y3o3 zexrqUDV>C)vZzt;qj6?LN4z7C{PfNWmY1r9tEF@(Xzju7%>oG%xb>xXTCviFA$gfh zrlKx8ddW4PduYd~X-_Q8GR&a?Z`>)nh?~_Uwh6i`!j2KR-dbw4msD2i(QaNq!6FIR z7d;(qtBfTaP_}-7`vX(fLHX)!68Kqg?s9g_zK$HBIFeqb)d9!>wj)ZM5P=f>_$6I< z1a>vyZoZ8T4jFF z(XUtYA#E(?0gMvZ5CtK2P~p}TxC9fmDGfaLaAz6Fxh~X0Cd`@+<)=IH6Ciz!=Mb{s zD%LF>3up%E%BlNsJ`g%zjnX%7IXee+PyyFg?UI#%s_a96tV9IU=v@04PPHI(mJq~j z2-2fM!Lu=yRB#8I$C|_y2Q+xtXe%ZcAJMaG-tvVH6oWJW=rFysQ- zUzHYMJvy?OfT{$Lng9fn1Z|;T6en`=S$M>N?|xaaQo!B$&>i{K=FXVfB@G$OXSkcS z6^`;Qs9yg**U}I0PP$gC9<7-$^94dqezRAYC zSVOO_BgH9Hs1gR?F;>#i$MLZ0ZWKTn$|Yi)aS&k1qtgZ6!baL7f$~(0Ub-il3J&+d zOsQa);b4U-CtUHlH~`NHz@_M1RctH(m$GGZRZ`&I>ewN=6Xrho)aN(=|464m>;Rac zg^N}b7~q3Givqj*V4%fLKw(&)%>^{JGMHRY1SZ1=U_}Da8LEW>IcX5AK#qNpo*2%8 zLalMh295?LRtHDUpnlB*~Mev|IBPtZ;W2ZK7mi&ZRs&ZGEQ&;SZjkN^fs zxfndenU2&W0IMQUejf-82Ll?#9}Hmf8$3r`$!1k(zXwM z31GMa81O(1upj6G#f3629mqHc)}h1ClM&9uXc{O&kOTwTLcA7;af5ijAsj#57S|B& zOo8*^5CL>357JJYinvKZmTQ33O`y_MV42aZi+is<7tWSZqqL#3O@C$Khq68=k#9#O zUu{SZgY!ZRaqb5(O2TG+8aF27u1KlgFg38{qi630P;IAvJxFzdNPw*PnBYq;V466D zpLOU|C-`O?s;xLA`eyucZ_cI(CF0jTUN#Re>)MX6!-|P5@0$Bo^mWR;?9nLaUJr8j zXUkN$L$Ak;J%~(-6&M!bENFK_Km-g^1*bzC?yaSqFwEQM37(Ax>dtwT@atH+Y-N#b zvCSlv%mM=&u}gAbpDGMzNbjQlgEuyXhNifDB2w2Vx!D=q9?t0Q%@J74!O7$a+C}JjAvf&cvkIAhGz_eY?@aaejVpl zOz87pGCqDyvzR_w%oBOR*R;e^q|`q%pNCUY(6>-ZFDuY8b=IyztiUg=+_TSUewaP+ zFvk-ePk{0gz{1SJCxs>0NU+4>p_2wV{G?n{7fRhRO5{7GQ}uS5Ce9kBj!4b?xy?dZ z<2*Ob(za%w?srP9i&;11i}mJ;Il_4j>koE>bK!P*<`|bY+frItv2zTgVZGwE@Wbh? zteM3utwpPoR#x_Qk8wym-@`ItI`~;l!K!Ixj&miyQg*B7mB?R(bm0o|fIMr1f)zR3 z++0$?Vs6sC?5XIGQB27d&GS-zRiO7-w{7!oXXM129`E+Z=N+lI7x9=CSs7@6D8(M$G!s!X6!;`wJ}l0(-1dCAG&VrWuJof_)!T`4sYSq6P-)+0UheOj$4~1o zAJ48iRdCzu@jUq2ib&|j8taPDz#QVnHAtd+Xt~)_u=MK{{a*`p zo08}mwwJ8v-^diVvc`Zu2Evaq>X~ic95iZNr)rm7FWU0LgW_aYgl%aIJk(%3$Gl|s zv=M9dPR4GLU+D8sDErKCGkg9XZPa3e z+V+{$z$LOPpZ3YUtfPV(#O1Q@dO^a8E_@Uu(*~Xhx;247x8NX|AanvL&9e*QN5>?P zU=Q#pb>ew(3NqW@axGBh^Uwku0^mT0lOi%$aAo4HohEdN1xnhJ z;!KR?r*nm{v3zv2ungn@8RbmG*7w7z8XXFlsP4wl78Z0U8(E`rzK5I;K*T)naxNiU zEg*VdL83XtYXvOen$nw2KcD%&wda=)>T56G_Bo7JYnFH40sg1TnU71CdQ~S(_L89c zIgwd3LVgAX^8yFHj6~ZsxT?y=nt?DE@!;78u#hOYmYq^eftaySFllf?)y-ODL;=Z8 zofRvdb{POC-q^(Q$AgEX>P3-O03o8b2S5qi29Qvx@R1=Dro`uNKk;<{5vvSBmp^fG z6@>uS7iV@{2?Z0F2KQs4DoJVK1h6#Y8jarn5ErD!c9wOkO6RL-?QB7LKb0PM%>Q0l z;c`v(;npjnCMOJ`SrmwBI#SeUP@Rnpk?{k1xIXDY;%tl=9qmGac%8t0xJ{Po!*(9W z#Pp)NHNY-IZ8exKu-|{)wboDq{~P<2Ikq2>bz5l!RLH z2J!kjZz8aWl9cY2u>glL(KJTzJ}O*> z(U!mj14v~$+X5&RD-*zN-LM7WX8d|Y*4`2gYj6M^^TK~d&j*ra5p3BH$;g2Ik^uww zYZ~ePz$%X|bCAPAWqpRySRgAgST37}8*{P)CF+q75x`$ypmhMG0}e48kBB3>)@fq0 zaEZzTpR8GJb|hFX6GbM$*7{L6W2hg80*S-*OJH0)bDSIqfqMyF;)K#qhgxJJ8uoph z^1R(AUtvN%4;J+SLz^ici#JTi+vow8jPpe5rrdaoRvCW~`n5Pxj%NE~jI&35~ zm)jMkef{bHukg?;(Runbek=Xb`$wV)!$~o%%1+A1SY;)p>Y!H1wy;x6`sp6S;%u)SDYfu_8{2 zs`lCwluLXUUhw5znDDAw^Zv9Z_1Y@m`DxmPl}lIGnfmKDzpr1`&JMY>QJ}CMk-HJ| zVnZ@%EsnE6=Q;gGbaS%KXK%el>Wk9~lzX;SE*X`l%@}ZqLr2WU=4)rWe8sKe#MAby zcaJJhpJ&0(Q=%(_Pg^snDDv-j0#Iv8v<@SwS^G3%`FN1<_FH8Pltl`|B0M)B{j=YD9vOrE#@s3i<6VdNYS6;t2LEoe*F z4L+Oezm6&!xb2u_J$yTyb!fD{BBRdgeVv-`PQSpr7qL|-hb|4aJXvihax;2y`h@cQ z>ycWX60glC>)%=JfYav_ZuQ2%)A~oBxJ70p1G<%{jY3v;B>>po9BH0xn z0zR~DI8VPJtbE30X(`g#nZtY|rArc2-+$$xkKC@)MRCd4AE+i^*! zmiJEQr3t&u=f|lo${INsHXWcLFY4iZPKgN5k@T-@y~27dtK|D6?mB%E7u7^>N|}%B z^-02T=56ma-6Z0)ru(gJ-AZ?ffaER_Ld@^WeQ7ai%YJfKIsR-OP+(sKBUYUSS_0&m zhjPktPpHeq^z0P5r51{fBPh@RAot3vxPM)K%9eJ^%diN~kg>U7p!t>5mo1u5b64r0 zMGFvovd>S7_sCaH8r*x(K4ztYQ*&*Xu^CZt6!TgLaZqvm~}uWs{x zoJ*BFc@qdem18?Z>HN*xuGKXo(g$nj$##|YQjUDS1I98Hb-IpRH{y!~vSy}L{<1mz zOM8x-sWNhZN3VKRG4S%j7>B<9jrMTrxBfRS+Lt{rr@9ZX58K$;>So)l39Oo{XK+YK zXeG8lDA$h+W}Eq8Ja;>qSjgPa7H+F**On`+YUd94exq&1_ttX2uu7O%Aa{P+m92$R zA?L06^2Q@-=0d}S-%E9)SAKu1fBN|M@`D0^2*^o4a{N0$1l(Tfk*VDN(XR%)PD4hD zfBxb08FQ=rvo?9_`=51Iq~gwo=8>vCso9dslfGWtdc9lh?pG7Pe~ez$cAWcE$=SJF z(FRzhxELU$F>`l^17)@wd;&urHtpK616u^+R#-#g-M#$;@MU)5DKm>u!uF*uUE{xp zJY!x${~3I`8Mli}{9lGV|0VeRe>volgl*EJE__)@)K%(~6$AI^?#yDNl>aRXF6ZHw z?hT_^0HWaXS*b{7ule=lSbp@uJ+sgxzt@b5d6LFhV_Q0Y@(V#gJPLyx4zUqLX!Ja> z2%0{2$~q_cKGfke$({aEbn|*zGncD_Bcm<0Co-em>$7~K-syLHj-^8v4yt-+oc6Sr zN_%v}6`T2_&##kuukDoX|-yRyz62=XjH*O@%! z9{Ehp(TbXt_Q+PFMJkx zP3zd3f9->bt}_8T#tV~Kq+j^rrFLA4(1p&(tu2oMQ;6dWZ1 zc6IiH1W?0Jsty1IQ5;r_0;mtXC>=8@Zwv~Ij1or~aA4E*AuQ?@FB0s-4_#QEi@pLR z4|QnU3E9c`! zI-5%Z7b@6b9D#x)an1b*5h|!EhxNzUhg`TNC}Z3O3t`4-0rbF1S=cdYW*k44gW&vU z1MJ}Ou!IOE%q%K{M}CvXF^r0?rBeYoAjYU4KoO=J*j~~>99og6;g|L9mR&h%YBt@a zK3JU~Go>R|JJp3c>mAI=8EM{aEllIg3%J!w8+6q2=0dEU1@nT$geV z>^ZP8dgtr=E)Bl}x)GDJ12IC;2*sw9{eO*-h`NPz{|#+@CQ4#E^vUfm(35%s_^7+? zQ;DIl{Sa}m(RL`>no|Wr?i&R2%eK|=Gj;paydt%>+aVgvI!S3pxEX1>Mg^oVra=5; zMy5e;lCQGG9)zP=8dyD6i6q7Woa3ci9pIy%gmi=$t7{?bdtj1vcb8-M#rbI)0VVa+ zkCgKSSRADz^0m)(S@0~+|C~n&2 z=rZ;st?c*C+$qHKhZwesji0s_kg7j{>-B>#w9l`s^X#Rd z(}=k5p-#|hCrlG{V~r=DiRibwiRAUx6EqxFyYsfuXKg)Dn0&jfJFr+42i#fqmITLq z4wOyz+27-=D;=B^PFrdW*-yqDC5Ki<;#8YLU8Dl5?FGy`5f1!hs-G)o+G_fYyh4fI25l-CLd35g1j?tY$>MJCGLKHn2zXc$p#<9yoBc?TI3`!4EL_ub4d!7@=HzUeX9 z_)rDe=IQq$c^A85u`5nSPg-9OLDGS)4_)vPsz7h%vX0 ze}_y&lz8eQf-c~LxlH2q4I?sD?z9QrhOPuWEKOc)Og>;7@x6y8tR4*sIBd#sOadd7?4c0PTGehf=26*N{_%gklILI4;|GKPt^j zHuBf4P-Da$S1X@Yf9FgUFc3q8zq@fY?H<}DdAKBLzX{DCI$Fsjh1Ek7#YeJ}Q*5Hb zN8CNb0usV)(<2^|cl_=3Oj0%IXkH??zcUE&+7DXd`8)jL8I5bT#2AdNGd~eVjX+4S z1M29X0%gKoe1JS1_5PRFOa_G@?fy(A;Bu+=ynwMAVdN6PaU=wg zfM*cEGDHA-1s!!o0%*+Hy%{Y8@Km!ko{kLj@m-XMfNo>l*~l7^+%ku>(IsOq{!byvf z39r_liT2Wo>B(D74~bC;b5Em1ZDSOp!J-6krvK#v3(pGmlGeuCgSQfZ#E}w#*pI%` z6+p|9PZQ~hnp|hTwX2s|xM%a0R%;Wv`ZD3|=!220kaM>yG~A#6C{46>ynL%E_#~*& zxVY5;RfH*wA)kvLIUc#+JM^4gySem>?DWLz0qp_fOmu2Rg<52qdaU+Rpt5)SG4BrB zvJTIvR_j=j?qr~POPYInhgEjxf%48{r6Eb@PTYvzT+l9BdT9f^sx$e7fi%!0Q@4QkR6nZdE$$Oqi5-B-4Il%?pF<=v%|eUG>Ms`kCC z(Rx{T;blY6%cks?%`Gn*y)#?3UoyFjiud)0--ysP=#LSAh#JD~hWAtJfNOWS4zYW1 z(h#tmIEo9t<1%*e8F=q)Y(F&caeE-J4nEWGFdJk9j1=v0S9R!v{vF`2*$z0aS2qi3 z|5-mFg1&;NkdOa;XY23iB1~|{AP6YCb^=Slp31-lMtpF$L@Twry6|rb(Er{~)k5jQ zBD475hS}=1C9iVf+B=eHU{SolcvnaKvotnX+K0OXM{|4gh>V@ym@g}c!`rsU>_62| z-fCt&AaZBx6&%HdmqvB4Wo?1Cl#3YFar#ns3w2jVOlF7dgPn3Nvu;}H<&)Uy0)1_& z+1*b)#^sktp<;#AQ#aOOM(}}Be#|%W%+afY%}Vf+a`Vmgw9H3lqe(iJc@0~6Cd!J(A&%Q_^L~;5~3HpK_vq=XxHwYJe z(eACM1+yb&ft@W6mqfu?wNX0Hb)V6DKx?%)>XKu|n{;Yb5mfzw+2_xda>xdU00Wt&m zujO?kp8rRgf#IQV|3{g@ZgkOg=zGi05wGvhHvUJML0YEK^*u)Y0?H4J{~u)rjY~gX z5_fmDlt;Z+2h``wR|mD$msVeqkcWQ`=?h){`5K5WehvdWTR-1e7#;rg_MFY-U+>7f z6rdygoj0GSZ?_MOZYG@O9^c4`Uz_l5{I>Sq2Z%0!ovq939{?Tk`p2Mk&bRfyb;OLB zZT>-07}xT*sTg2C)$};buzlu%ZX6#sQGbVLE@_6jIhT7Tf&L}+`$U^|>H{&oJ%{T^ z?TZyJt^_R9jdF`(L+UAQ%Po!WPirM$iY=%Y$8Wz`=@zQoe!Z~$W_xwMkpIumVVg65 zevP;#o>+Ss8JMv8iC^FuX@+CDvpJBJdva^GGWYq`)U6jDzYrc*Icw|lubypZ-RIf) z&3=;$T4{W-5`NWh+xOhb=V?5?#+9`1=UEzpJ$$H;R{;=U2+Zs9jD4pv;8X1XV(mSn zn)IcL0Mykng6Eg$yCT5IoQ%{BL&zw0V9fC-qUl{`NL&@IEg zw5GvLMnoqhQ-1_`_7T>fCyRbVn7yP~eAJ6d(zqmqWtkUb2|F>R1TQi8KA1gAo|Kb5 zVrc_CF-H~1bha|H%+uu59w0hop+1GmS}nO!)=oT33>=lM3iKT0{^F9P4n#|GEbHmX zZl+s7&{7<-w|<=K2U}I&MW%aN92MD26wC9I6y~N11qK29jt4=DtrHC;v|X?;e}OAv z?2hdIT<)tf@Te=pX23I)lKyhL)CSf*J8S;^L zzlMs}fBK_&Cta6e)lZ-ZRrcxiLuU5B+_C!cdFmz*7HmGkg)=A_*L;^zTi&jf8NL2p z0{VVX&#K*tu-=NA74tE#exE_`t-8y3m7p&!JO>uvpDqKOGQV@D279Z) zA;fOFXkn*Tf2_gj%EsWtr3;Bu?+c%9v=M(-bu zo@0$3Pe)$ezxLyvKm4BOklpLnq90A6j`zH0M_xba{LvhBN?cS7l&sVL<9^)OJ-@w? z*(=ER4=fQ-e=hqu>fgr?1dB=n!^-Cpu=x+w^iOTcs=D<{a2Nf1v;T(*dJUEY0Rcev zW)A_dIR2w^_y3e;_|NNn3dC$C`%T%sTxksI|AV9W&+Gm-bj1I5LjNydfvH;9&Pk`(XZwyGhXh0kq_vU}+Dl$O$sy zPCGWOtJb&pI7~+Atu^*!#bfk?Bil8O6qNna;_!B5Qi2$f2d=^laVCo7s5q)T3Y)HS zxuQ|pc?sl7wmRqLDDim9UL5*Vu@p<|b72c_e(JWvHqSmi5+>#Q%UOB8^@@_iqKfN! zZyP?WPkMA)=>(q$A{WlX=0b+Dl4@@c6I!89Njml!S|=kjT?J(wD7eE~tAn+!bpw>A zkqiBKufp#-Vh72IsdX{_-_S0oX58Nq z0$GY#8K7WJ$sPATYy;p34UtseFmIiA&Sloax7#AI^kOT;QE#|kuud;RMy33>GGFdjb$Y8P1v^+PlAb)~`WF(fx zA&RwQa!3X-R%sBqwctS7LrEs*h^-5abNltZZ#_{Dl_}m2PI-uP4LD*opF>4Qqd3Ha zM8$@C|0puM#ZLN1bAaBDMmv|Fg~S~7Qq@3J+vC?oUmOdO%Jvqg989!;g>SeHh)hY| z9yeHt{5B{OfTf(3awyrEvvuFuHgo$b^~&}JVNt9~@LzG)qV)Bg%f*T2SbJLn<%cuO zIN@{g1t&6g|9z@bX59M>$;^GrqBZr7RfyyHpC4jQ_wQOM_WOf)Q3Q6}<;r%Vm~qpD zkZ&LlO(+E?!M*GS*JMR9=M5xW+V%|RO@@N0lfP%^#H?;?QotwbPyUb7myQ#heK?+f#5E*)JpD=Ye>;8M z{|DY03zhBf<+=Vmrllx$a|VVN^zifzut=sltJ~xo1rRy<#G$G|83ErtpG4?se)`nW z7B&GFSK^HCd>lcN6w&xwJa_TKNFvKNcy#jnMoMl?=YIhWwY)y<((xUnkCRouYva2* ze{9V?iujk)*Of1Dy_8GL-!5U#zpYPK)vcfG`MtL(*jMH(V`5&!Q+#Nqu!X~dbqH8b z!TZ|SEOhr z)w_{($K{df>gVYJDOyFT?zeE9{}G?!*t;bTAi{nS=l|DkDaeN8UC`+%2rr>Xn}@O% zf?_&>ZS;q7$B^s-D}%w#QWB)x8Xd0w2Sqnltbfs?&EHIE?5@fGSgzT7*m&oKOu!t} zzgu$ag%7|y?|7dRtK52>_@9ZA2YU*E0Ez!wqQvQi@vTSvLrebK^$qM3x>%1qGk`!@ zBr|Q;9y_@h$GnWxiW>Vns%O#)Y%c~oq)71vw+}xGF_SP!v@_b%d}~^1m3>J4n(kYJ zDlQ+JHdLO{6xsQaVNb!M#@WQ5`64$ATLxzzL8cpwLv`PsXg>Kuq@RH(O1&Ry?5CHa zso`GFS`;8@<)FB_!HM0(>^s%(2wqvi#wmG`+=;0iPNBXzr_F9yRV16-nJAgAW@%is zy8eaTjn2Xiy|v4W^dvN%Oz3I+diius4RH4GHS;4Mr}NN9&Pm*P_-&9rEXyxl5DJr; zxRE1_DQ$Isvj!c!tXF*Mci4xer=p9S(Dh!i4>E4IJbjv0HxOt0dw+T|*0*Wu)|8vS zy=qDlHr4Mia1fEyDLqKE9OB4q)R~GTRspyo(R>(T0n;Oi$-=eTqTHet>8R)AhTBnv z*QIzAmNU?Up0|%nbI*X_M!PoPtA}@m5dW*%euZ6aHv{mnpM)ELRj9Ak!XPKGF{A&g zw(~gJl!PvqrKXE%nzPyFGkqCiNN+LQ7$Qd&#$9%m+NxlmqIBYa*k+B4hJU53SOU+7 zxijly`2YCx|LZpg1%TMYzyUr`DGalWI}z&mZ{F#j!$KT;BDjBOQ9XdyKUe(2JFzE% z?h`?3u~FQAH4rGfB>$6z=OIb-UX-{KLXFpHx?~5;3l)H+hB8qDTw-S9t4jDBE%aj~dJ&?M#oq( zJ!mvtzddHiTDl&B@dT@z^lq$N3kJ zJtN6D)209`|IWhgF2B|>1fhd7CynaH#Yf;uu)HgX>2#$lHf+x40d$(ztYn`_mjm5k zP4S}N1zDsT)|8Nikb8OW%M1wzRYRuR2Vh&h{9QyXuA~|b(;aTQcDg7FPP5kz+i1kXAR|#FfH zvN-ZNR4MrIX6VovZ=G=2(IXb^+s?{+1>gDcUvN2NIE%%^M8jA6s0qREP)nGoys2!K zw9Vz5TQU0Gd!x$b?a!?hztVGFsO_yX9it|VWJe9tgK{%si$Cu|jSr+&gP&I3_??B_ zB!@~geKlLTrS^S?;;41QPJ2TA%kipn$SX}$z{L`=OjQeS?0E19<+=ahqrjdMaj+vX` zy#)Zf#Q<-iP<-%j^~7bhy)-{)6;~a-1Vdr$Z2OE;qlzx* z%Zh_+=j1H8Y7^oU5l89CQ-|V?*1F!)`AUEZdb*VAdwoV8Ft{>VI~EiNhcnmq1g4EY zQ8=CS%`dT-{ie&`vLdT#NK%U=8Mg+WA}QYVhgFFU?N{c`lye%`R7p(74JIIH3N%~u zqaI0l*XdO}L0&_;IoU7`x}5ktq7=LOP@mH<3R;I5#0fmKbYg%_%!SE*bEo_2>5DPy|Y?{EG5S-}7O zq$aVz{ET;mz~8%*;0s1X{wpmOJuj(T%{}UtRnR_!6@iuK&IHDrMD>f>$aDLNr6EG0 z>ln@=vG$(NY*##x%-?7pr;H6P0peM+SbclmF+3|fk&<^jGb5cP#h(HJTJ7WcxY7CS<`GKt$V)wvWdDe7mMTGD!YJ5 zighMyMVMEk7d;kA&Bi{~n51nIZ4%3$>NeNAy-|5(BH@whuhZ-;*>?o~-Kw?ma+3wU ziGLxyqN8ZHt^QW6;8iE6HqGlX94)O(BnW8O_AC{@;!d(@sW;HU0rVz&^R>jQnn; zI_KFX!>8Wy(hzk-z^n@-P84p$LRR6>lEb^-B=0o6o;3V&YiboUt_P>n}zH=FbhZ2bNKAZ{5t%kPjsA_wt98qbs|&J=Qy*M`}|e92kSP@zsy4c5ei+^oUG6@_W3YIGBpW$F7r}oc8_9ob`PceSWM7_1*89{P;6pIb)wUfg@Iyb#TuV{fUg0jeEn5i zz9$uDvy&uqBPsQ??20u)5Q`V2#K$3TuH3-`_iw`H@B>yiSSV0~BBAF>7$GqMsf7n= z0eQ^u5DfCrK7q>>PrD*~$Pf8ctDycH!gJRTdnWFQf_`#I%42|v z7$Tq@FQRo*3X^CRNBWWov}-3V4gt|jk~1B6l%7c6OO((@s>LBKQ%SyaN!e~Buq(-5 zA7KX-5Oj%$zP}Obd4p4nT_{iX$0R`l@E+fYFjqVa1w4i!@o6Q2A13*+wRq=b7_FUk9l=vr6yjuXcs0(}(#XE)ISHj`=nD99lUX`D~j!E9{ zEEjl(KMxYcyXV65^A7J`6qiW>>?sN{8O0AXK>QXZSI=eg1VC6!fMk6d>j*D50ay$` zjk<829e_Te0v*ZmyP=fetNFgJ@q1CAITUXl2FQ1nKZ%iO?gi6z$>y6^Qr1Dt;rJ~m zsWJ@)uUhg=F#HYc`FmKlP`&{Rhcia#F)`{wczA~_;w>INk4osk@_)vIg(YFC1?&LWOclZ&A<770w|VscrNs*l&vH{nxFCvq3zFD= zlAdHDYm&PZ1)>84hxYip{ec|qKm|aOAsv{mUn1{adFbJxJqlD14_{)!CR$YH8QikD z-0vv7v0m9GbEa5I+FlDd2f?2wRdiB)Ms*Ds|~d)AApwdG5K#$Qp@%euI}^q`d^gP2MVcx z+HDbC%0NlRd811SiiY*1BIJ-4NB|G-s;}W=ZEz2?s8msS7X%cmaN4gJi9PtrJv^5{ z6o0dU+2+GT!R09;RA71(zW@T%fZ?yj@=gMPqETr$D*uOl{sk8vaRl&7%ORG_(et^$ z;Hung8~%ZU+QDm08W=p=1X#7aT-yH@xgDRxW*kj`IU0Dmhb!xJN$z$OFnd8;SCYZK zjmwUY0-i$gXGXE-!(k`@45RYEDc0l2+4C4Z(H7OR??iQpT zH$Wh$gsFvimJ4TJi?j%(?mEj5(X~;r6pm&T8H~By$4R!muxWL`!?$Ss6+*|zp0HmA z*{?R>eNjMBiX8>PFY0pBASYFck@!I@UTXjTB%%>s$c<4!@Yw@R8sxfL?t^Hs1<;*- z987vEQNM-n{5Jm;EdLwB6s0#$Il>VFI3TYfg52J8!WQvqHkpNoJ*UE=C7-gG+&S&Q z>H$!wd|N?!2b)7xs87>S1->7OpHe}H+uaZcv@7f^sRK$1i+ff( zf!`XsAX=3$7JEx`EqYf+_)(7t)lWXFlCX6IUlEEB^UoSO+KW9(B;9Ljm`B8jCC|Kx z@H-CHVyhW6_CS0q8TP`<#R#|d-a}@+e4p|H<_KUil7p=Z%IGzMP^*2YQVx|Wo@ujzBM2Uvi?XIqJ9N>aRw zQp5o_L)Acb^a^=j(pdWQQ>p!zV7CR-C_mHtVj72j97P6t4qcLZ9zN6`{;~hbl}n1K zVqw-)Du_mBG3c31h#pZwp4yNBjBeB2r(91qw#mQRjWp>VvMA|8r4C!G(RF<3;~$Ij z7e{dSjRFnt9(fZB z`u3uaw}NzX{n=MlL|gYw=k*&e;z1pY9j`|bGe*gU81g%*@t}e+F$8E9mO>xxqdJ6_ zKMm767#@tDc(6DAGNT>s50V%RQ)CcUe8)7P$x|i7ud0&^Y7(Ei$I-a!^}=iGkolM&EZ{k0ehB*`_V0G}=w8&w&5sUbc4aOm~Xrj%R{ykL18x;%gd z8$$!a74g6~$&u=eStSHmZ8G9hJV+!5Y;Js2jY%?~vN;b>TK?RUFOWQTNh~&%qkWcq zKoT(rE20wqN{v2CiA1*mD+7RkMlZd5of?1Yyc!;uE;<+CIQwPmb+yNY)ZBQC^dh|O zje6v)0piA0$Aw$%=Th2FY;~UqdV5TeI{8Oxerxf%79MPfk=Vh^=&&5YLDC@O@)>f^ z!b&VivOKi=Ug+J@#*tgVzfG@nnbYN3Hza~V;#3fpS)uC!7RSFB><4f3!S%X4&{jJT51ZV)h#{PpS^{d>wWyv<{XHPdbb*YKtPa7$_#yX;;J$I z%q?JMGvmuBqx%m-2D&JC_d~45dy!|+f1ZX-mAqyhkaG6uxzh2uO<-2}TDS%R!{oQ4 zfS(Obqbcvy5b7QSRcw-75&k>I={r?CLM z1?*7-Ivi}}_#tw}*I1M5ez?!ZsQLAtSqIU1;qv|~d`w-JqM$L*#q)0r5F8g;ARtYI zJ7NQD%0bcil)oFTkNDF1B}}QM*{0_uxZ%qQ)}b$JzrP$V3;cGUIMbB!rsP#c&)8PU zO((IXuO3XRgq@t59EOuyEG*cRIw<3KT@sKaiTHL;{l~o?LWp{rqW@~dvo$+YCgs_h zHLKWde;W67(!QPmH%`{pocQFoeZ+Kc;`TOrZt8CLFj|diC9}&Rv)l7*$DXxT5!Z=i z#doLgFLJ${&)l*5x+nW}FWj&3jS8`%o!Eb{t1P|O>$rD!!Z-HxB3=z|%G@Wg_K8`) zYFYbH>l zkKphCoAm2=_)LTIEj!$`nKL9JsMzqwLYvBo2QtW;@A?adzexKrIKKge4+fvZ) z*^NJcA9r~$8L3u+ZkHuaM4xB~;I%67CpohUzSN6SvPE(k&Ntm zs{j3q5r=3{iy4;;iJ}QoiidWsEei5Jdw6%+3@)U2aopg~uWjcPVa4AmV4!W4i#qtE zJ=R=2r23(iq65&<=x$)^?{jX!$w1?y6RRt)d&4< z3epj|yrhJ*Q3p%eGM&~Tq^RJyYKvt7UbRC$k3K9?eq7t0P4uuW1qa@IKMc!|)0xyw zkh(vK(vlZq@xc}k?hW5+FMd>ExL4igX0JIgQ)?1-4`-{x^_JU+b>wbrML`)&5JmeLiIsP7 znRDYT$m11&^_N|<4)hpA5WhH;F$fYV0Dy@W++5~W#CxwMPfsG3!nv&Hcfq+LIZ#fG#M6*7VizsjvUIGTGt7XodI14&|NoEpr|*`8*+3aiai z(KQaYIovGwq^o#=^4d!HiFRIsMYLFqC&bF&g%vw+3!G z`Ii)ss>4Xr{XwR5%4?8!eFC%5P>izi%SNG0Va6ZCmlW!9_Rf>JDM)zH8Kj|w zom~=UsM~|bu->&hYq@~gO&FP4;E!HRd4TQ=Q!v6uG4cc7<=FM7mf7<_jED= zvEwKnwP7mdLOFmmY5n?Ty@si(oU4B2UP$+FeKSxJ12-% zEw*ypT6^H0sEy$7rdJ}f?R*jHk*j?aXgl5^{3T7`Z#HMJ^M{Lzu#gMPH`n1cjGrv8KtnUX$h)YW`*0k zhI&b<9BM)V9G~%-=T()6T;gyAxe^+&>GKNGyKx&O{*+hU!Q%7j>X$yP&-o4Ji#o+L z+xu)Bt2nl581`itO+j-WXU@6`d!xr^&IH)LF<3VdRblPZIR3g4V3Gd8p239l{DpN$L*4$p6&ckSPn)-3Ab>6eIm6vWE~ zXnw-qW*u|@oV_%xB2mZZc9UB#Z9(7b*gLXwaD*Vic%|dq^=BTC`Pz@iIPQ2Hf3UFl z@tNb!+9lohKkp|ksQN3uUvHOck(|~1jrt*#(jyqP`nLBA-T109h=o4nQ+~vk=F0QJ z;Vh3bWmq?jLyfzG+;c5vY4Po9{-8d{uWLN#QLL(?*Jg@-!{WNt)e)bnFQ1}IV)Za} zLO(=~NOX7II?+ZSt3UGa@^m>$9}9#R(Z3mb^G(8fBOJ2xs)dAi3zCBNH>B=Xb5rrL z`uLUQOCi+AZMQo=IhRcJ{W^diA?NH=f6ssOTuwuMT~$fBzW9}>uRk)HG=HxIT(fTe z>1^li+g)dB)erYb)sKCZLjHQYGqypF2GnxCljtDjt#9pM3n!i&2*mjRfCm-hrH_=~ zy*HNMoF0Ep5U}?JIzAj3Qk?$xY~$it)8AKe=FVNX9>5m$H4`Xe`M>Qp^$+*n82qwv zF~(%}De$5T;m(aWTes!fXUheD*6=E8gUl5-wI4Y=oISsFGl5;THaQldbF-Lt$IwS= zsC`z>gXma$eLw~7t6oDSD9MAYxy~b`uUds^t+1tq4%Zt#YR)Juxv2g4y}7y|sSgv>g{+1n zfQsgX?ix?f6r0z26VBq$3OE=wtQ$|OQ zkETz~-S=q1LP!HW-XNilRt~RKJ~XoB_eYoA>iV3P1uIt5+Ui$ z*6yjQ*Q)r_N`}e#Ar*&;_)t#c&p+C-bqA4!pNzBd&>;v=3H7LGDfykn2d+aZ!6I?neeA4R$K!g1Q?J8OEIWHY*) z-iepLi`PN6*(}dYWM3P#k9nHOEPcOmNO;+CvFkAAd#Qs@@8vU6PYRxvuarqp2<9;_ zG9ltJVPza8_;2#!*X2j1riwQn7IF$3;N{D^ujYjkNSBS{AzfZ4hBo#x#ds&L{y$4NGM}(`;?#lMO^unoOxqgh%<0F2p z1&cKN_(hGIKgW|c)s+ix0{|oOG#7s1VzTa0lM@2*FKzJW#lrI%WB&-__)4GF#ZDju!(L7hi?0TOmlQoa{j@&~z<%?fdxkWj(3L&*V)gpqFSgAJ{2{P=BLMPK+ztc71i;tY0c-`Y!cVY0xb3 zkNB0(+_t~R1BIX~`>%@y$ zsl@eO(wpbQ3ptWBlrE3OS?zEI@}c)Yp(voRe}CQWHu0LlY!`h>`5aQ;2Z>(5D_G|X zjkn+S4Kp*V7njLxd*k}pmUto+>TkL5D@7w$tb?NKG2HTy`%Rv|&u=hUsz8{x#iuOF zXQ*^>;jQ427aar0?zptVh@)Msx=*J{EMCm@ytyw>JtS5@AU`Y-H*YlHCI$$R9|IOP zbh`i4n;cy->N$?iTgY#F`&9vZSFfn3YrOAzak$_i@Ivi$m)?V8!;g7ua!>__&F=VE z@)lE{{}$#RGDGiJ*hfuwE_5rtGnV^(eDo>DJIJ8G<%_8HmeQt`(^0>iV=toij@c(0 z(bD=)5(9)irg#LaPA%?BzaMVD-zEEn)`fm6J^4mfjKk^RI74h)_#2$i-XNWD?>%2& zu6?WYgHl1z_XWzzTQ~K^@n+?aMm(?BQ^YfJReSruL+K0dY@Nj}d(d4GZ`W^O@0H^N z5-t73Iaeeqj`EGPeU7Y1|E` zRP8$~bxP{guTsWUIdHzKBHzlfSj6=XS;Mi8A1|aLUzC*Syy(q)Y2Sft9zVkE z71`&w$m>!sr**o}{tv2V^u}gt7LHpbpOqriWm~*8h2t_d>p!2E&ktQ<6uI&>sqn(+ zd17;(hl925`Y>+LeyU(XH$K=aFDfP$X=<#Uc@hjod*wE+MXaqw40{(i%<6wxi(bpQ zVDjLc;>SyzS&o)lbjHDIykQ*lJB$2RE&(LpFo}2nf z)(psn@)VLyaTc~_iaMNtC-72vyzeVtnG7X2C;LIO=A}2vgL6dCn-%)Y35*mK&uUpl ziZx{}gq}o<<8VSGhv+9Ast+&A1O)7Jd9AM#8Jk1~S3p#X05$EdVqc}l7FaQ~A~xce z`&Ro>4zwP0(}qa20pG-=UQbQ-om@{?=e+5e9MaBp)rK>$J;l8Rf1OU!#iSl8;3~@p z1kgFFol?X1xfJrZDucJ4?nWjpeVW{bhM0#3(35-%xGq!ik<`fh?OfbU&e0{n1v)2v zpVN;57+l)Cx}U;|+{Yj8NbybuM6xy5*Tcp{K67t;ng~9hpawWs(|lfw76R&JjE;1rZZC92WC z{(1fN@7h<^?pFX86DZ0ADKWuEm=J3whck06+5GBjUhX(hS0>(_!KK@dkG0`6!lWME z=Q_teJ7( zYcIO$GJnGkeOVnj?>DoXwY(VatgakThEMS5}Peku? zDI!9A^A=8?-#MuisB;CO99CS#7;<8p7Cp-1(NA~oOT!qX(N5f<1wJeDyX0vdt8qUk zX*)=A{#%fBEcDL3R_{|1S7SpHE{EN@6Q(q&4MyM3mCrGH5f#dQb1@-ldSe z57OS~_Ke_reiNOr%u%fIuYO{)8a{OWh~3DIZHnwcU)oIhjui6X7KPDM3>bRbB8 zYI~^e0k4aE#(jS8M`@NR<5I8(BdHUX5|ay7OoZTd;H4K8t;4e*nE&uL^u_D=R&5aQr(#J4!0hpL2u?@@WAK1rT)~fW7RtjS#?hW%mu49a2z` zER?wC3Q^rp65CHPgp%k}8d)L)o?l$=W;MREpsM8>vWyi|7pS^Fi1-Nf8w)%NNKKIa z>&5;3E1PgrP$9lY<5}@+B$@^){=gl9g zb1i{GIqDI+Y71@Qv#sa0cGVZ#V?MrYj<^${g6tKe8Ky=GH3ek+HT$)f27SOvXb~eg z)L=GDc@-UCe|OS0TfDLeYd=p~uhk|#M~!*!U+}2)k_|m4ar-i3cmVf;L>+mNUlma4 ze8C|+f~m+$b_XhCehO|%=nd3|RNL@Y4H4Ry5(oUePJaECQCxQE^QM7%ig|x8QN&LB z34|7!?tc=J3)E5r$;P%^(^l1FeIw>==5qIAV#MA0Ner;Af&BEaa`y~=($sHJ51l0J z9fwX94{t}ONMG9zNP6zi^}@3A*x)<+`?NrF@$UXW5LewnK$5zmw0xgqEj$;jV^F~4 z6=bWZm*75g?|AX;e$avm_8#O~KwV!ynZydBE@of7A6DanD#tE+qggeNcXH4xmqq3^ z&6om~nf%IoSr(Z_gJvkDU^gq3s`$WCoCZ93#e6LOl8e&iOCY+l`X7sancf54NspxP z+e4aC^4sDbvHjoD~nd(E8-9@0;2m_w$C#`$8TDr__l zmtOha1Y~sXDaIpBD43?{)}yQD(mOXrhFW?1Ban*P<|O`%yu)UB!tlcx5KRtkJ86MA z&QGRwK`%v}Eak1$G|Mo{lV%Q#Yah)h`WqD4Oy9FFZdPIYY{ZKpAOWr4X9b|HjLViw zrWN8pU*IU~FMyA{29An}d!AbkYVJJsBTJ;A!0jVOcar(SlJ%hTKzmf{g^|vf-kosZ zRjcN(B#X?z8kf$ij0Hbbg>u@orb*tnbV#QclYF&KYKKfNkKg6ty6?yc;wvXr-&R+a zhRDkmr&2XsihNIeRMn*fOsUGvBHSOFd1_@q$&Qo5mLAxE(HaJ8f2~4e7?`o^1# zZ*Cs_(y{fdE5*a}PMvxDp}Z6ul4JRR8Qq6r5s-1PlO^lMx+v5m8yPddz2o$bl98<} z|HIkRNdcJDm%wLEbaXyp?Z9qIs(0Un7Te7%pz87Rv2uS@L0_JN_M?Web1{$1V_VQ-gbxmF4k*OjjvY#c z^5RsHKll`FUdSM9EFkvL-Q8{_ld(Vwu3!t5Em`MLOV((%0R(xO@z~VTVR*ZT8C=Ft zPAL^9+4INBF9(Dk(~1I}c1nW97VyCR#2v1!J*rkTR@P=K**`9&^6BC&(egM>D^Ikz zNGXpN&s3igmIxCl!2RhY-fM!8q`u<4@~ z4JqQ4SK{ffp{ZX96Qkm##R$oN04xxE`h_`K3JHF0^S~o~_#HycCAB8z7|0{aQmRQH z70%RCRj;Bc+g(I(m!kzK{xo}VHd)0+s3yNhEm&qaqYNg;d4~Y;NXSk(DW6d|++ty# z!ZudUsB}uYU1{bVhp^5do@8Mx0~9H+end-Z_hi4LRK)}IoTeZW>li^M5J0vfnD!3? zkksfj!?(LK+AzxywH*E1c;-!7mBvZ=4QB%B1ApyY=K1qP)J-$Uw{x6c7VRUL!`u8m z5LpDTg83n#?3N(09R(KWWoULV!3fzMC}z?Q)8f3HgA?13xo_r?Qys&jHrmG{;!orD z)8es|TIH|!ITS2xb`Kq`(0_X&lfxnC?GAE81o@l&PBMo~z<-oIqHOW=FX|Z%k?A1? zAfd#f%|wi^dBMvRY*HCl>-f$V z>Op~xbPP75ZZ1WN(_gEdc83WnX`u1}EpX{H z2YJL>$L}(~=HE5}mM5jCZ=CC;B=}k)L@JP^eZJN*gnrg{Z^p_g;<8e#E;tKlz&vbjoCDN@We(e&DUfWO7s$mbKv`B{<$fB zSrjPoCemT-IN5nZr%}g7WWtU*nToT2z7Qw{aKg7Xw zVa65_W*}X!GHzY9DGhD3;Oh$VWdK_6$;SY}dSSCehS^+(uT%tOX{hb?7^QnU8Q6>$ zv>X<{?5<<{?SPPh5p1nObosf!Z&LI`3q=%&CP)IujaVZ5iog=OJ-bhOZwTI&?k{Vb zyrZdHY5(N=vCP1;cNFs!JJnE24;`jJg+c-%N%fx+cHH-U8=6k)`*`u;SJMzlO(Wh2 z`^DVegEi9xA1rnE5eaZ0$A0~>qRIL>ouKylsUqCQoAqbAm-VBUWkf4u!BIdF|5701 zw|F^70|ibV_}BrnI%{JY0NC#+`>TiI3`VIC`n?O2ggwnRq;7kK0;6vYcp+t63Iuta zY{YGFKL}7cwpPVUymUEG?NmAE-2q?nv0r(KDg}VgAIcHz<35Ap;V-kJPo%(D7AH_L z$Zv3g^T$p_4`@c>wUq^HO9vqSWy+T2B6dizm?T*T>X}I@CX&eAkL2S+pK|dkZb3^0 z($A*ig-iN=SX#k@%+(-7j(8!ncq{Exez}>sm^SJUmsy$aKBYFQr6nE}Kd3m_N4wP5 zIhl?^l-z>Q{2eN|9C6bAMI3Q7RRp(YBuFiFq!*nA#hR<>zxi8Dq&beMLi$2x%oJ~# zt6&LGHHR2a{EwNmd2m(K8Cw?uTf@`u#mwg%%}C9E4G4EHO{n z8eVN~%*pW(GH|!r{2bLU263kIfFKeHay%eN7g*QVPlfH{g<-;+jwBfDtq7JEX*2f= zz@c`qaJk*H8DbXZX(j?ny6O*HlINTZGFO2B)iTVHuWTd#SinActSOWDL&e@RV49Qt zSR)&8f5MH$^utaAnxSNZ33#>V*F)b3ytvSQrHQD!; zj)(e-bH!UB%Qq6pU9D6e;FcTPRHkI0o74S5dc2- zzm|Om<|pFK#dqfBx(kH+LF3g#>A9iP!JyVQoEm^Nb{uQ5Bxb47=8(q7fUHvQ=-Ml- zbE(?|W*$$P!KDeB@yo{x@fD^dQf;O2q$n6S1!2A3V96KXr#J&>_4;sf@ECj*4{sQa zv8ofX!=cyh6fu3rmQq%smh+3LvX}aX-=}hC6hV#XiSol9<`ZR7meT#8+OUP0IWx#v zVuWvqrMKDXHozmXwVMba5=)b58ZRbsap7S>&xl>O2LswjkR1-q{(dEW5^7b%MgFtvKeAN z8`KwHO^mS%@o^D98LL1MY0$OBg)muFax+4h&`AxClvJtyV2V7_VUSC@KM`UU9@*DY zZvE3T2+l|g25_7{WEoa&Egk0=qlN7uR)-+84|!IKO!Le+kfssB z{o&HpYI~h1s*Beh4=PdFKZzMSpyo*mmW8M>LDli*O8PvigDJ={&Nv5r19zWV^@ifk zdX_|kceOLDS|z(k<(^X#hYf(UU04tXga-k|S7}y`R7(sAI%nph&Qs_(Xbb4GL*3=J z!HF|%5tAbj&(+GETDyWN(*xlDMb%x0H5I=PAK%7C4aVpm8!gfzjFJroQc}_)EhQx> zAut$?N{e(W-3>BIQo*8C8boPSr1sJ>oav_O8}yaaa7w z$K8OMz4sF2Ag_woRGPTq>!J?-X8TQWFezcH$D$c5l(ePZ5h*x;FxwYV0uc=6Gaz7y z2mMCZvYs4&!XbyK+8Ooe@ia@?h;zZ6KF@pYUb}DizJ9EuW-Yu38!?#xF;4WuBUm)x zWb_jt2TN+x_P0V2g1MRzyaq4CW-0vd5P@2xAEyz6g59`Tn#AK$kS20W-`LBZOF~sC zhHsvt!YYnxU~g+|k2*^-6Qtf2Iz;uy=*Kxu8my{uJ~kVn`j1V|bOMBQwDw*iOu=c@^}Y*FMDCYH zLZ%LwRtD8XHUH(4ixxh;gx?miO~R~go96m(Q6qiF|4*c{Mz_@gz zGYh_>8$Q+Z2@%w?YpQL_Uh-KKt0*v)F&bR~4?hM)a>X>+awDbCW zuQw^3KvY$`>vEgQy+qm|E#O+yO`Nl={MTJ7z7}WJz)w>CcNYRAUSiTq#YDz;O{V_1 zSNYp7z?{^KeRW1PZDgHPj=8XY?iA_XAq`fXZ9%b|KEt)Y0#cym;%rnc>}iq{0P!sa zzk@qO{SG-lGr6Oufr7q&f+*18Wo?hWJk87-@q1Hu1lmJ{PVljT`0!ot7i|${ClL$& zFi%;wd+68&Mm%R>jDv6N^T)DJ(9pBCn|IOib?vbZ?c_1&#No$@;k)qu_N4FavM8Yu^R^P1O&&)=`&XBcJKqk?AG> zBCz8{xO`S@2O;D@NLenUK%PIoBfCyMr>!HWHzqdz@f_c5aLGoo#dNQWvmml#3zcV-1W!+{cj4PqnNUuxMgmiVzd}C=jV|hoa?rKx)9#*^qrSD1m)w6om)2mTwz1vAroH&`JfGM#sDOtK7 zyv`k)rBxb`>mE>18ob>-sIN3+c0Tw5j~a^b^-&}Sc2`hFBK@*PNLb`Ka5P70>{a(z z&iP1P_js?;#Ble-c=yOm_q*>(?>D>O?Zcsq108q&^4Xeq`4+?<4&QM3I}z)hF-e|UEPD%`i~V=YJ}O3 z^;M3ulz5S?57C8zo^w5%F9v;prx4Bd4nzt>VIjd&6{J6E&8 zhazk&?7~n+lm2#U65D$6%cz(u+>U1Bb4Qx9et`;}oLM2=#jxadil9kny6fFn`b8QU z3K?!DRb~yRx%K{}Do7kPDf)EA=)-ISWL(>*G&h*D=wuNHQkr4xfGzKgEOmERMh18TBGkB8q7H+>CK(qbuoU`OU3@cNG7fP zPOgRBaHeujfX71Hqs{4_oWJh1_j@DnK;+Wq-U-YJN}RQ>_ZY^CM=4p%JScPqNnJw0 z9=7{kQOA+%(NiJnUZi}i+Gi<)R>#@2nsMeWo@QOD0Y04Z&iQaIN=S99y>UtbhcL*m zAWwa~@{)oh-Znu?kjt&Jq75oFVK6`||7&W14qLk2M%C>joE!qCj_1MK(vPGVyZqZ^ zya%EmY>d4m;nx*5sh4p`&C7;^mu8eA{OtAsElql-V6FXRRYK4P{c-s}zGR!MAjh6N z*?35%;pGp)OPei431%F>RyixSI(NOmjGBr+%`xWM8lC^+4)G%WtfHZwJ3dnCIY)6F zv01mdu0G(ZgXGsU94*gRGlF0`>*TYy3Jy$btW39Us5nRRR-0; z@9yHg)4n)W?zg}ny)&7)AGGsj#wLifVK8o2Ydu-gVSOF3d%3L6t$c|+;PI+HFM07` z=8<0JgD?MH!5q_B|%x{pay-{s|}(FdyVB?PFXiGChxQkJA08pE{3)G~(CAgBu^+ z{cdz=D3l%INFS5$b;jxSdP)zt?HDRfc)}cu z>XJL-;)Rk`>*d`Ms-TLEm(Jw}9k5gLnz#JgJfj5o-8EEcHj-2!2*177vze|z3UXw` zB07ZNkwUGhT`?~9yhA?Ro z6~Ss>k87Q75V6b;S2Z@va5=r4!xfhaOaNn9^50rs{GRjre(@LorL$XQ>jUg>2>Eg> z{pt4bjr^Y*2UKw*C0-v+W0eS4xYAcO#G!Yr5*$SnwCKP=K*sG*rXnB6dm~0QCnedo zFfJ~u%5;hl<*g6ILC6m!y4+#W6Fcm6?tR3ZW!@kH2lr4K(3``&{ROk@QcZuS@Yj2o zEX}TKAKcIF*#AuOb3?vky93*HJ%bA2Hof|O2{N!KU9poQ!O_+srX;ICJ4=v}qaF#~ z_g&>&X1gu_{?WBVzRYV*Y*k?%D~OkmV-ySfs3Zk(+@naG;7aCG*T+{E_(+2)2@Ubq z=O{+uPUznJ5nX{)G14tZLuA*G)f`>U9lLy6dc!o<%3z!4gRth!)X#}7WvWIDRd11@ zP9;iMGTt#xGigG@Go;TecSzA^9>)~wg$sxsMCr>! z4Ch}(46qF;zgdR)gL%E@U)waZa9md^qCgd7O)DszB>I2e<%vVuqe%11Fs~^G#&KQB zkJN`WIOK{F*PW|oZNR&fW`~?`gCtqun>3GF_}mMo?%ql>q(5wEdV1vd^WHLtS%>ul zoL}OI@cdz{A)6{Z=VVw|gO~Egn3fpT53q!^6g3uXFJ4E~d?XB_vYd!i2>cg&?UG)3 z_36;-6*aIu5_n6MO`i?VHYAFWnl;2|AS)hIK6(6sD)JF{ zUQ}EkZ?XE>b(pzjF%{C{8guJXX%eM9CG zZ(4oGvHo3a*5j`(WIJ+{(j{4{U@Mh`12x1`^rtI1H+!j)eto-L7bohD^#}wd6Tk%0kO0J`T!+MWOz+qYu*SavpCQ5P? ze8(ku{S|xA=>0#3FZvc4U42Rijacf^Kjb>x{5N7Md;@zJu}N6_ zM;B^JSpclryu~*-36^gvf^ctPN%9{et^JC)dz>{SIzK$Ojw_bB|3fM9?-XIWxdi&o zTqC{jokaj`o?)Jw$*aFa(@2>hYi>&QKyYvUv%O*+(VvxO_FCN+q2hVoB z@vY;Oet6nC&l|PC6YUN6K-Xo@e`%GqdPyXNyWB%AZp63se)WiQytgP14D9IG+40@O zeVsRL)1OxM4EnqFRYgm#bKGM$v`O*%+P7A0ob4Nz)d)eO^g~zKDLUQ?h#x+WU0g$MYLA;(`=mY3UA_6D zWBi`yRWN1|#5_wRmU!HH#htsXE_eDN=q7KOMBa}(fv2B}5dIbVdD|v!r(eQXeOUlK z6im|S{uD$&!}AMSbGfrmX^Y3L{@+dx0vV~E_#OB? z?aiL!zQVOoJ=kPmKEE|Gi4?nv>U})Qm@lNmI`aK%{)2a{bGvze&o|Q=As?QHLCujD zTX(`wKURhPuGGKyVe=d^H<|yZrR`$pQ9;Ppz5KsDe=qhNCQse(VUMz3NN%MRgm#(z zsp6Thwfd|q(A{#}YU(=>J`kmr0SkW>jg z+BUmu`SFF`qjIsl@bf*=r_((Z(uD*72q*Ct-(bR$>k`4{OJJ_O3$A@&R}$Zb{w1$H z=(_jJgap~R*QG-Ab>u!7)?oCtKABcM_}z0dQQIAoAQEg*50TJ4*OerHun*>(f_Utc zfBzv@??Ar%a6&eT0x!vD1gD6vr~Il#(c&g7 zyrG=$$#&dOYry);LibbNJ`q*M7(1d5&6`VJcyLkFB?{5$HUuwDg%`t&Pza^B)DCdo zm}DqW3SL1@747i`oRDg~Nmq_*mBxnlm!berdKxU-3bs?D&zymm5$#GO4*t7(qQE2B z#1q)T_%5SWMwfUba+%5VCjtRvLA%CY&13k)(cO`xYczoSKVnrRzy*rKW=m5+D4TgZ zM7|x{`&D-Eumxo?BXK0*^aoxVD?wt>7HA)_60d|iEh9$USm5^PMm#$Rg>WijUje>; zvrOlNwc5qAo@~W!6fq)!^r^!vH})salUaX1;!z%C-T8?y(nM@wU(vWStvDerk>!}8 zTgVlrdEm<}JN|lLE;v%R^|j~LDt&f^?LHqD6wfuejbO9m{zxqazs9(Y;bvRa`wV2T zij*hk7kuC&=-MdgaVYqxkzZVl^4~pOwgp(bkY@hR`tvYoiLa&e8sVJ;m zm|38VyPA(13gSer@Q5-b7WTzu6~Rw{$Sw_3|0Axij=to}2nCcUjUB%T75^e1zx|N- z60hp7L-7M?iQhgF{~9Go7d{fp_NdE!A*v=xyC^uy1G$A_zCH?nypd8`=Bt4(seULz zg^fgjIFyFP;_z@iU?Nvv7R&`n*+(Dg;5lKW55|hE+NClrvx~U$_aCIZcN`drrFRmL zW5&t_`N}T9{ud$RkOvX<#&QOccs`U;Fh87(AcnfYXeF26`1 z7|0QWh4Zh9b6sZ~G~|N;1(%8$0mkx*c4!JFbQ6b#-4XIPrDY`Fk$RVuW~^u;ca6#L=olN+g8gl59`)NyuI28LwyCSXMM$HOSH^I_ z7jsfmv$lW6UB(uJ@EZnDuy~iDCZ9ZvSuu(-xL08!$5+J2 zanlN7EYIAhbMVD_=Zndm7Ttpk8=>R7zgMiN0@QYBRESZ-@IE9ZcnI_8oHE0@tQr0L zn15OoV-j_D86-gcMP<*=jN1fF_T^qsix~AEM_ONyY6LZ_tkCvKi*?nU{j|32A5^+A z+?&N2h&Oa+5$EW4CfPc(s|$#v{S%M;m;A>iW7;KZ6Lt7YkMX7|k=eliu6)h3A>W{$ zUB8~(s@tfuSf+-cVu?QA8oH@P?#3T|Xg}DX)g$C1G&+*;v5tn+ zSVQCJwa`tZZY5GXPEv#9yqm+J~*JFImB&ba% zkCn`PqsKyFuwhL)wW}xJ4G+?vi;s~l%BD5P2pgu``&H@d1;iueo>`3?6 zxy~=j%+KSwe>}$GYe3L_Z%8<3zfdl?j5S!j5P~Cu_%UEX3|JRQ!7v3DMFMNgz_=wI z`=yX~ZK1CMpUkyADGG#G@P(}hhON&~II4o(Yy~X~LndcJdS<|G7;q>O*drG%R!DA% z#H&YyvA5$b$U7>Ctk%+?Z$YZV;`}_J|R-LV1O;|z?rKtxpoTkh&VMOgjG&H*@8xi%jHi@;KU=ab~FC@s>KGh>8 z>D!Xczh8QL^6UWp{5o+Z%yS968x!^ZIpnG(QcKb4`RoRId<7jfGyBuqmMplCz#~5& zCY}(21V`*XzZsMa>_~ff0&Yd8|7`$?7pC9&mu@JZArbNHM|-*e5~OWQW*S5$>6xjs zl=;9S!$0Un5PQaTagaD*mk^W{&rU%zm;7i6Yzx@31&}|JpC>)*_(_n@PU*<1>B#a0 zr01EXcd)~wmU8;!bBE+9`OSm`XL85q7GsECr-O38{>xhq$`z2yBNaVrLDDoMp~pc5 zzb&BW{|YW%7C?dv&pHZ@XREvL0l zOBGLtFO3+TPhY2;zV<()t6nPiJ*`Ngdv}Y&iC(B|+}$ajL;jsHE|v?+8{=^Q6Z0x>{`T8|Vz?@(2JBM|H zUG;y>+D?yxGfaRo)>X{s+;RoW9PB zKl?Lm4iXG*Vq_~a?nrlgdZbq~QTz9_^(a_?p*U2nt1V@><}OY9^?p7MRid;#|B6f= ziz1pC%bb3fd1YSz{!P`SVEZ;d^XDyQE%(g#m`&*;+ny+Pv%>DKLuJb;3@_uxR8J5s?;FrS4zTBwBHap}4UDR}T*@LvMzOA75rac4aYc_8mj}Ptu~=Vc zHOR$&b3m{W>~@islv_M9&IlR-IHr$t1I4L&x1WTx>*KR~9y?IWg24wST$wsaqTRuSjr62je1?^M%O7R&g7FO=bTbTA4bY?aIJ!q}R^*bU@V zD7xqPdMWHOn>9g?Ziy$HJ2($=7V^iFz((-Lwm@T&Z^$4+i%6Wx= zjIrZByunV0Wwq_&gyOH+;0-r6=-%sgM+B2EFI1@ad~g?AUR^x#?D?JSu3+)qM1|F|MEi#Y0wW}k=J6%{cW2!55r zSDE^TaN&HFF6l5MoK|lbQ?Z;|v6>9*v90Teu~`aOUgRh=++l_oUpq?2y2GOkT=UbZ%~{Fus&=V@yl_a z3eVaNZ@Wmc94XD50;@SfgB^&h27tR5fn_qQ4@{^KXgvfO6hSLN}}o`3s@*mt@LjF%xX;#!QdkP3}|33%g?)hGM(AH-d>-mGdgrHsSJj zeoy>-?KVfa`1j(MKDT+(Wv<)CZ{(oiLq$rx{~{6sj$`AcjE(^deL#h?F=!$g zIS%Qb(myp{<%!~A$aCZjdtHK)G2JprN<$eQ$2VRx9Dt}VQL-!Ak)%w z^uY`3OEb!7_xmT4(Lx&2rU~?w?8``5ko`zPIFfBKn(;A(JV*u&6^k9Wk%TBA!GKl9CF>cRV!kh-)3w^aD-{ORg~u^xK&ox28$r8 z-%vlSZhWu(u%`7}!o%9m-LZ#tZ!W3b>-%9k?hS7diSCVK;^Xd3?{7gpnm_94c(hDg zCwjEbdyeai)d_||ciSK_P|voF{KVa+lcGw~F4vx)wOt;{F{0#;<0HJ@oUpw1dh_EF z>P_tRDHNd~=SlMJryxDV4#0$j3;W5Tx{rofY?7pG{&)P~F+dPtNv8W>V^^ybuIXLa z7fE7Z;Xm-Q8;GJ~mdh2it-#;E!#>z7OX=&oNydauO&WImmIUHNMn1dn-xj?j+A&B;Qw zM8uuW<{zJ4|KCV&u-th5osgr^*BpD((PLe0d*6wS1OEr}9x=4hJA6)c#IKhiO8T3t z@Q#9SP(o4D^{iaxo z0I{$w;lT(^a2OP3NbsAb?IRG>CFvPx*qq{)wbapQf;u8*wkS?5*@c&x=Q1i!9bG@w zpC~aew3;L{?cxxstTd}eNBT9g`b+?}tOlPLBKD_fBDB;JgdodnX(Xi|j_F25RAuQ{ z+|`bNWI)jBi>uO&prcf}>&8o$a(PFXd+Yxz-MBjEq1PhR=tBOCZWf@I49IA2O(jRs z3Fg}N7bj&WlNCgLM7kEHYipC0WmzX&D-RCH-h7omZSa~7ePWS@%e@O{WNlm`_JTab=2tIZ0zd~#;okqwcrC3D#|7;D-XID#&taCVyqX%TL%vR zO%C#H0>q16P(Q34{BfCh{axz3d*jH#>D;T={R|fmM|gAQ>s}L9;QgPVH{ABGN;k^a z`(an5n`avuodbN0OsT)#a{B6uGzW8Ri;X-X&vtL&8h+Pb{$|5MxCob)JvGANMH0QS zIPgtWivH>Dyx(N36Sd!>6XPAfmQh&F-#4Y%fR_Fwa`)dGxq;$5)0VMsBnLD9VB!>Z zo12~~#QQChwO?64wWTB`hPZ|Hd+sUuYFS3IutNU6N6guUcru!2iz%`&tbxK{Nx@|r z1&{LS$g7DsFX+Feq{FeT*Bch?!G*o>Uz1>fZVAVXIXe(0 z`OwPuh2)}L%qn*s_uDLEs(;N@rX8$tql!CFUv!3TKy5XSVK( zb;GRk%o&kx-ZA`}bs{|<12#nHs z5Cz3cM=7wRB)T0Ja+WRO6w!|o4RiZB2@x@(!m}_A+ku#E;YhjE!5)5KwtMXuqo^)&prp9xLW;CLGxiy=K|rpSFwE)qgdt@{zq*+^Nd zXuouq10DtM8^Url;y)|V0+Wt(z%top*SMH&xV09$!GaqmR53rTWY$Drm9tTEots1SXT zHg=>hZDdGsNkpGz*JbCKre@MH%Q9zA;U3JV2nGq}Wi5Oh?W)i9T9NRNe&=<6Vu;~W zMaKaehc5#+g=no@j2$SHYE>0GUnU{PWjOjD-{$o!dS>ZJ*2;aBQ@&PKfg;Dhr`1_u zuIbeENAred&ASyQ9K;>&Vpvjl)MXTN;t+Aa`{um|)r~Wf(Q*>`w{Z^nGw*g4Ioru` z^^x7{@4(jwL%x}x#MWzmA-kcw%8ZV?&LPSoeA_#carb7_HJN2K3nn1t7fmondop=| zDJu6Y7zYpDk5k4*lH*3e9F=zl_^atg8%ayJSM-$>di;3!Snyyn`XEk`A4MBTMAE+$ z)#!w5&suiboQY?|T6Fh6-mEe{tL=EjPbuN4j8=O-a`7CU7NU95mCMe`92F39@iWYS z_0u25XyJ(*$_E8)bK~F2k6g#h9$6ok%^J5Fy+SHn*%2qU$>OrTHKDvmk|z`-j^I)$nNT3PqI4VgSbdn_tlfooX4CZM-0A5; zuUp;B#e9kP+2xB1`J6(485h~F(Dnd32L7siVvl4uHv{p-8f4{+sTL!jO0?J{gR`ut;wl0-IWHT z#d7VRBsJM=ZQxB$bf;Dxr>BA$aM%zdh@i2^h7-gV4#pb!U-)>^H2I@l=&$0X6-3Hc zjZp;ixC0>1)%Ro+lI-wLIF!^M{v1tczYRW%ks+v(2YAc*21-RX-n!MO9@MWMyF#W5 zm&RhqQ+;INnmEQ0n~=@u`jdbezLco>-CyQ82kr@ntEcP|5*%kB|GwtOwPn-2^fKiCsZ_q6Rh+zMr$ z8*;kI5DTP|;Q)wgS;S?HOl-=(wjcB*UOwSt?)!hKpI#PmoU-1W0%`g1V{IW1DB{ly z34Et?bDHSHk0!T$K*d4)YWt8|_0P13Al(S^2a;e>?<6uIy?{c9xOs^d5iA3EE}B55 z`L9U3vsAaT)OoHn^J8&w6hEw~)LFhrXbM#1$Pm>JVlOVe-c)3-P##f~3-!%wG9w6B z66Q|m&NuU}CuBlD6^kN4BxG5;3rNyd!#bFsiZPR^Qj#Yaq?b?-Q+e}_NEw;Ti&#?d zYwEEw(bF>HO8$G=<(a`1K6XF`I53w3$bh^u5DD|>%2wy%^bsISVMRe_Wwi*9ajK%e zv!dp-qJF-jQK72cvZ}MQsw<)D&1qHlc2&1R^`K>S{&pn`hJi&A*gRHI9bCz9m z8bwD%MLJTY3q9Aj0SeHDCWR)=oM!FB+Jb~8y|ZS{1|Tz_i5^+Q<=tYQ)AGd)NNWqk zRW&xB*1vaa*16XTtFL!hs8_$&ypY{saMr4KR^5_a4@<887~EE2S$lt>g$i1=p$0T0bzkt!Mr=I9s(-?WI5WJc^uR{fGQZ0%GJAF9SOZp-cf|4fw2NzlChGu)WkD7 zru~kwGfH}IU^xbut3bX&-V-cIPAcp!xCefEy~*GT!n6e|k__7EiS0iXz>P%cR?eGl zTZ+L-o)>3tF0!E=g|y>^z)$rwjRw?jZWvs7CZ~hXXXbF~2 ztSDcCIb8A9NSd-jitYti-#U1Kvmqyen{FR)1(K?}*XC%y*|3C^!$AY5lqJdFUifo8 z2Fh2q4b4QF{jQ;z&I-jP7z$3CJJm)4(C!i`po#-sl6_Qm#yN@}^Vo%Mn1S0`}FmGy%ZMO}Hh76wE4<~kfSfXN0hJTWzovN=d+o$~s z?~@7uGEG6Y0l<~B0XM}rYUgx%L;&|bK!RAMIdSK4ch&QKN@gPT)>MV#K6OiHC8Hz| zXF%>x9O~CC=Y<19m#(6Dw4;*aF2CGH3+o@Zz1;=$81KVo>nS(30blAV(KJ1QG*t`k zH05xhdLis>GL53F(lT?=8Q zq77O~gLF$^?)ouqgQ~Uhis$gDPHL*;2w?XVS)L_%J)nxU9*B4f{IuOVp!D&hJl#$q zED#C&WI+4FpBe_BO`U>`IM9}pkng5`0+{}QaQz@I8GK;P`%oXzss)JkMtkw+&3+03=9gdXme3aN zw@LI+hJ$J8pFnAnx^L6cj@k}1PQk|4VE3;U+}#HzT6GN~TIrWub1Unw?b8<8cC%oC zHWP2=7r$hc!UCer9&iI)GH4!to%R-MfKO4V<+5P_Bf(-&uXh#U9v|4=Rd9T*hZr%44szDp9zBj!F?fnk1qgeAb-(j6vmXd?hvc0u>e zn<8Qn+OkAd#{x{*g$fFX_IZM*fRU{1;Kp9T)ZrM;!@7oIQ%Vi`C$a@J0@ECcbv;0E@ z=versn=}R88mG+D_R=zw6gjA=9c9Mg~13-;bP^^kIl{sDO<=*SQ4|2m$(bW zBH1hB+b@OJm0bygm(ZPgk*dIZJJGkQvMVd6^IKQXrnHiFx^mmw!)lpezzWaiH3X2n z^Mz>y#B%A^p=Wr-*h;!ihy6n1*RY?1+6|M`+vnE1pvmT+-*!i9At|@^sObVGME1WR z_BE^MZLhbH71UZ0Az$(!cKdXr2|y_6;PLc6GijOAZmLG%kmdP7OdiB~pRR}IBQNct zG-=O__xT~@{vjsxP}ZxO)#j`1)S*Og!wr?=KgLIjy*=o zvA({>)Odh|w7x!sfSAorc--X7rMuJ6#5xr-|W8X0NY6Po>m6 zrDs%W@lvVwp_{R>f!L}1c@X}G@Lk1KrHQ@b8Ds2$Y-sDyHh>x4AmDuv)ddWV-217w zt$Wr;_2}=nH{%Pz$6{gOJzw@+R1|4)~mhW69(aI z{iz>i(j7Wyu*?$^&T`ok&1ts#{~NmyF7tic{%Berja>5s`?pWIRbr9?Bf$+BVu{?_ zQqC;m%6e98AJtT;-m|jU4;~2EW!@-=<(GP5Qk;trAaP`}C2ZiL6Paa2xr~Z7J|~Ov zCj*c62rop_{jC?_eJk;l9I@%bkAbe)HLhz`CkE>8dy!7TIN_pTwP9M;RI3ZK{lm~x z`B4s~{|r-)TwIVSBr!k={(1}<9ZnKUCRA0|S1)}X1)@^uM82Z6Wm`eYghh?uPb!nQ zk|eSW>Tx3GDIYs+1y>bF?`x1%3b@|es8d00ILXEh@JCL)4dt*RcZi$#T z+sIQ28bMxfB85ciYhqbjGSsK2CRu?m4&n4fI)P`!GV*F>a@p=9nztTQZ1LzZGdUL} zwOdr;vE!eK^UrI0djBzYEg#km$u6Le9H+6j;uobOY2CDsX}$(1NGQXh^R_V>b&spe zH0sP%W81PuKuI(T%v+HNWMv_>n9B);4U5sv0grUI3-i+>{w>r~BtInxDxiBVG^6pw zeC58T*$99_I_Bh#R%xX$ittR^ypEbnWNW(b#$3)dv6ki`dFQ;qjSlC6uWPbSr?7-) znc#Z^Fw9!0=2R>g_29UG8J8SVl4#ZC!f(vS_5<1;o$uu&PDmwg6bQZQ_8FHL z4&5wdZ>t8giRd!LQV-?*F2L!dmwg}U6U7b@mql$e*PSL!jOK#w+f#KtIjQcMCiUTM z$1d$qgm76jKDxr*@ku44a7)k3ymRc6Q)?4%Sd2v;=hN9q9}(d1Ep+e1qY;5gr6<2< zoO_@Ag)ZctQ#kYbUj2|6X*WaoO!|jkTud^PE{h23Unk`yn{4z%mU2H_IFJJ;zLH8Q z>SooGDdb1AK)ow~e;K2s(3@4nci-ex88W8`LK7C}3hk=3YtO?0NlVbP;a-8lB{K%q z&kwd(fr8Z$F*0BzjaZf0>WD1w3gtl|8GM~K|;;`SB=JM`?9|@~T zjg14jnjI#lvj*j5Kc+ktbn#J42my{{#pFi;~ zuxXjLe$1#_oW3y7x`nc0NHeEd52$UGND8>I&__6Z%C!d zIKA8#o>11_4+oOKKyain8PmyRc4w)Ru$1?hi!9~K_c&*TFCFhYa38|<2+m6D^7_Hk zck|`tfs#=60k1G$D$){B*Yk@$D#kb5TM}sYtHU5hyjgnF(HSS8V5nJX074DAXx!{H zd=~Jzgr_DVpgF2H+^;Fy{CGo)sklvaAvO7c+(Pcdfj~7CwVyK=F4b^hl_eh;lP#HOUfeB*eh5}-%%>q3+uFU}L^f9avVUx@x&ENz z&5&n6OBL%<=V;9heAV5f%Eh%zvpQkTZ7@^FSAhD=_0F%Jq3fLAcUymSxsFG;U04{{ zX3zAdoAg}`8ZrH8Wo`TOa@V{@(S}@(t?PI6IQd830mE!h`zzqPwQnXzRRr>sn}&p!8$iW zh^{BJkc{w*l10i&-!OD;Ne&zm^#gaTZP)b1U(mQ0=1k}QfcnP|U0){7 zofPqqgS?K#)kb#zsx$P4-fKt)pBIt6wF zOJ}eWMeDw>D5KfG8QO&Bc0D!E&i~?{>W#{%>XbEMi~D0Rw59Q|Rdh%EVRyzGKhyV$ z!kD^9{TKs+h~^S>9%~Up&Oi`I*)ZR#7#(OmUrt}&%N9g*(EJXBgsfxU(>Znx*R=+O zR0IV$ZvY$o>j{ny7%H`;Q+RV59=TMwFKUq*!zc}YJ9BUU%FBK)#T3LgQc2BzIFTAx z>vFKE}-VK4PDjEo^_ycU}|v;n{QUumI@)*X!JuWo&T3KdOgOtTP>ryeOoO!IllN>XC;>jfu0KUXQQJIsyU z``l_HvdOb!G1d0{LRZ&^vN8-9HI++MME=f1hIdoK@$3-uq7^zDQ79>Q{4;T}3&5OQ zc<_;L&H_Y-O~2QHzYXjN{=nRxl^%|ky>F)&WPz9x2Cla!i0tEELqYfjd5%QNh>+(a zA#@+maytjKUWrOiI58iz|b76P~uinK$gNl(s5&@=g?@H+A^cW*`r)d52z+l*0X7NmQSNsRw!%L!{|*06M|#0+jV#rMDGuy*atk^ah~NYQah49skRBfe>YSOq+L^uDo!Q;@`@Em0ZM0WkZ=_hcrMHV8+VpGR zU_x*R)~4a0l2`V@5}Gwae2Zgl1H2dmJg;niW+!7ZT74^E+J>ktxU7k~jU_&O@&Lxf z{Bzns5B-8^rgv`qr+#;x>lB}k(aZqkH%zD`>h5$u&|!&b=A>`8vmmNiMd74KzX`%} zaQA8^>|IaZw1)t&g;j77ICZtf?DpN#cB^#zOB+wCJMC1i|3yjfb?lN~d_ZYf7CxUc zsZO=)qCMDt3L~=x4gh!bYQ6syNhiLYj(;wwYJQ|`$bURr9DR8Xc=`1Jo($_0FI1T! zT^4-Fgc!0Z3uNa7qox`)a`vCU>(sE-6XqXL4P{o8eJRA&ZVVj((C?wx?4LrH(Jpsx zoBX-M0(o{Ps-mGlh0lcG_s}8rBBavn*$Sz9oUW7O<@{ABK5B_O_2Oi0u|nkDtZvK# zf5=4F{*$cu+y+=@t8fXLLel{OPX-I2a8t1OAvXQ?xX&2-ecf?yCa*p%xW&C+bD`T&JFS zrWKHcd8x38PT)ga>^z&@60Yx1?b_1A2J9uCNnmav-}?i##XyJLB{ZrZFJ(Lc;*rKA3IxUW|W__89L; z`Sw8Pz^v=|BTaX3 zQfiz$Q4EA)Ib-VpSINde<9(o^qwhy!Qal=2jMN12A zixt0hoGYpNxgybBYOgKs@^zWzZWjrI7st+>|33ab#vq91>yNBhEd*G5+JtwJo6p+s zWSZaEX}dF%$BqPc-5$H$JQR2|EMh!ucACKgAE;cN{AJ*=1(FeZDk9hOcJ>?o_@7ek z`mFHaXP&$l&xy>nF4>z|tFNc?Y>yk136I?IsqdBV7I#1FqRK*SK^$TZ&fYBCkCeL0 zExheLd1JjyqE=tvR%z0DraR^|><0)EDAFot0b1kXe<$iUGUTE9>zbEe$Qn(`@e4z? zm$hKe*+`S(?Xh=+8u@OcI#w_4C6U<~w+nt9-KZ}`!3%1VKI(Z3?0>y!n&uP=jBvb6Ch`b-L&G-RcQCowUp1tuI4*zhJCt(={5dn{v!VJ%$>Q9hulpp(yel5tAec_f#7-3a;6wI zgPmtDot9Q|Z5Mufc{zZ$aF%iiqIMzEDu?B(=mmd{Z=WkjSm3f5ZJv$xhG_I5!5`l0 z$J9d3aa0Nd=W7ja{b+e2;e#Fd(y^>XwKd=RnColFyIrQxd@?|yGkpdTuu0vVj9}n) z5W7vn1#FeOx8eq7S(%u=muHNNEY)~7bOUpH?gX`$jY>4WI00HdB#1)PUMFHK^tNw; z-?1Q`y^GJSLSrl?R#RtZeRF&GrD8zf4zFG^Fo~3&t@X|U`Z^yK%W@_$p16PrkS<)Dth- zuL$P~H9`K=IdG%)lwEqDm5A$Cv{0Q`uZJl08z1)Wy1G}O-&X)R^w{4XmrZdv@%+mb z{MZ#WFsJqi*PodG5UFwJV$gpMyWW1g?_P)bW`%r(WCac^-C8O_K7w4u+}_9k;9#+P zom$Q&)IY-9*-)-lSiE1G9J=#H9A*4maW|CtTj;;{p$Shy;|ssu3c!C2uUPKM8rccX zxbpEGxmCcSda0@6T7_?_4ud zT<c4HeD;oVV)j*=-0{DxBIw%cU5>H{9sETQukm@&^qepfQY2IUS4-H6 z{Tb+WV+xzH>h}l(#yF#!L*l|zL{)o59dgIuH*7v{-&041YkK)_2F$}U(d}pauZgU= z_B(%oJ(%DhleH$97o|FoA{0}i%WtgtN!0b64Ood8K?gWxqEo8vfI0PN24J*+e6h>RRZlfLx6u zO`R)8v!)Rh275w}|BZ6j+-5!iKPmss+>~+B+>m%u7e735vrzO&VCyDNf&Q%=01N-S z*;l5RW&wiahn7hh0x*L+}x)Vd5`=7q|eR&O?vzqmuY4W)R*=7*8 zg*W7KX%)CB^gN&WMV#r#7V~J_&R9e8ude?nBYz)wSkgwuzTCh9d8}Ke-Wd;F3pCuN z-a5fwr%L1-$+TuYS%~{DBJJPHf@J;2|8`$hE%D_nTRkcV!@2qKQ^?bK!Ds{HrPH2I{yER-Dj6q>)${)(ZVGwzX;$?r7!M_)<3cI zWf%9xUhZ6{WC z{l=Epd{#NwqgKFI3%}{^3yEFcggC6|7B2Q!aaZW2F@0MVVG6$TUrKVfvRQ+{Kb383 zgJX3#p8i5SoB);Wgs1xcD|HMPc7Ra@Q2N#w_UnW6AL(^&hhsPwUUt-gAAUP#kCCBz zd`=N{gHh;(qW7=fL_DE?OaCR|_mrVS*KH?D#rh23O*SI2+Uz_Z>SUfYZ{Xx^uH1Cb zJ+>M^=YFX&_L>##5ij`$jWtVCvck7AL9#MX^n`555!*r0y<)&Prz^pt1ZI&E$NTf> ztRyT~BaLx-oI2&s6sVNP;s6wN8wRp~H)V)h?ie6vyfj38g&oA0?l0UgStGg^WS6dN z!4g-IV77}#48kH}AqIP`#u5sg^WTq&|;xP+;Y)E5OAMH-cn) z*IrS4hnKR$m1PocgXK(cjKH^Y93^0RF51`l@SOKHr`9Bz6f}Yx+@~9_spT?>^{K@U zI_A-cfgBChZ|6ArYN;prXq_V%mZw3sYLG#1yGxX7ZdJgm1|e>PA?+32Xc#JBTe@EM zIwdo>L*`+x@;L2M&+=Xe%Hi+yv&OZy3w$Qqf(J#P-ElwNDUKYEGk?fdZZjaAjUSlb zhW@E7fLI+}Z5O83o_EvOApOWjer*Vc=oteBs?EXx5l{z~!oe<#J`x;ZGT0T{trtDg z_)+Dc!R|@(6UmivJo6RQYTCuS4iiC{Mk)h=Wj)shXh(q1hbBI4Kt4|WzHcuixZSXi zrYJDNNDU%s-{tJ`ak)cH7Y`q`*RKLuXToyrR}Yf7c+%qY%EEO3LAZN^9u<%3`s5N> z@!<(hN9XB!4GBsueG2clJCd1p~!6rH6|; z7MYaJ&C@)d+~xij%lpHVv)rQxW3CTA;y=rWr zutv6}3P(?W;(k{Oxea$8FU;FhfLC`8N`NI=vfW4^v9jg+;7nQ1dGgyju-a?Ur#CF4 zNwyNtdJWRJ2;=Flq+-s68+3dZ1U{Q?Y9KfEQyqInd7s7`>|Rn3PmVCNIr?&;mqkJm zSc{l7RPE&07`haa^Va&vZm?$LLGI(kk1@}qDaD#r*(s-DaJu)(3ZnG7>BP|s>`lg% z#BeFwK@T2!nNbtl_98~nbsOG<5&fX{Vo>1vVeiokmTUjl*c~F6_+&~)PEqJ-Bi4|Mfp-xlUU z$$~mErgqJ5i~AIy-@-GrKG@_Qb<&Ify6?zAPoPT}S))^EDnpyEvUNGA3Osg}u`O=4 zXXaJ8Bc3d4Ul#-~R(RIz=o<(wT4A$>VL7L*jo3-3*BvZFWg3OxlglNjfs}$viXv0?YUKLAE&?CMFb|Z+;uE_1${Lw~Dvn;)6%m zogP{(7QN`*JT|^gdFVbHpvKowFr?9j00xK;oQEffT7pQ{05lvlk7J-0x6U2!7UN*U z{ZOvQ;324fp$8{Ms##Aszhk$_yVVcl|Hgk}jY2)%dAXm~w8G{G(G#M5FvfuUYVyL` z7KL2P4Hd#UbNP+X{0~StPcbwwxbq7XRY=qdvdQvoq+{S%`A&H0Vhy{lHt=;1dAn|T zid{vZS2Tqr<+_IpJ@R64;~(Hxwa#@vihIreL@7^b6(@XdO&9f#D!0vKdvVtZg>8o3 zdgQ;TKeIC{u&H3h?y!LeDonpbAI&2^rP#g>t->xzOSlAYaG* zRT>LjUWGzXDrT@2#GHz7qJn>(PGN4G!{! zWYnOTrNq5HpGSXdvJIBY#84O?i8B!Eh0nIr*=D`#ar*HOhsXCzo>tvt)6ksoe$yfS zQom|nJO9%%{~J|Nn@x$W0IG|^Q4Qbs4bTIrw?Dk1D)fgG&8%*!;qOMWa=rZOm|r^c z19JRmV10))*o7X1RzG=atm&hx^%&QbPELG%hou_RtF+ARli@H<`J4U{TL?wO zXm-(InXb;)u;PRlaC+0516Eqcks>|Q%Mv;HCbs=o?}@xjQ}kZf9L3X2x=}KB?+@4S z*gZbo$oDim87mLI6AB^Z(tZF+7|KQlsA~gk5j|R0g z4lc`eQ+9jY#GC;SnDRk8s|uIhiUbb-yC+P4_q?-+Q-QW>tID}6M9+1iUptcfU3FrT z+Y}@-vD9hGBaW$EHle$~zDLH?te|-ofsy;e4rGRT@}Q_P=p3P5><5w=scO8NBTHbx^Y6{+2rHj+ zWmisa#%(ib5+>qwKx~nceNLAeTcX|iyI{1eYU$DSZA;FMF&lFRXf`7O&iT^x^U2kPK@(o!CsfEU`(^k}NV zFPsobLST{d7!9&<1YB4IUf2iO*i-DTP<0!9;SfKbHe9PYnw=ZVMr33Nz@J|W=Em}B zW1FjL#K=H~Dl}}JMiH1s+f)GrSaQL{4Jkw1YkdGOn84=)6nB;saHgEe-w*Kbc#L%2pS~K4HEajneZ0ypsBj&+;I+;XP>I; z145jF5c>q#%UB2wB!JtxUQgAXCa~i`ib$&NNxuvVD_Ks3PK?VTfz0Jp-5jbkH&$^P zARUi^qNtwu!E+>8WS_vZ4p0PBW#%xjeX1l9lbi<<3kHM{sL~$&@;OvV7CH_ef5Zfc zZNwK2BM5D;={ielai&^n>k02wAFu$Ge5f+w0}K#4F8h8NBu48RCMu6=^8h5~Ljy_o zn?xUC+0j%vFt!Rsm4|_p`0rcy62x#+F(N>5ks`eaw2a>Y$79r-fhtuXMHV{VQ))<` zjO1Oc>^_K#Op*2g3hWc0`&96Bzq~z8$OpuAAH)%Wkzb_3Nd3}21fdBmBp#16hj78D zQY{jS;uMwpW{Ujxg{lbEl0e1aelajeY8}G{04doA2q6hphag11@Al#rbRSE9NU@n z1J-5Au@P9pU*n*!14S@#<%w^Mapf(M$!5KX;vifL2et!g*aL*DA zsq(pb)&Lnq6I;QGEqjWPX}QkV3^0Niggz_%E5klkoT0g_7APK!a}B}@m;*Tav1uSI z986$W-IT#md)t^5*C`W+)HH6aa1vEuF!=FV5bQLSH-`YfPn|iVz;dX1U`i%IigGp} zcS_eb)=DRV#XA zg4jNYf!GYL!m{_y{|)Y!)5aoT1Ric0Bip{DI4Xz}hE*VAAdU1~K2&)hLSd}93WSQB z+Z=k+x)E^>By7PZK&(ih_{q-SDk?o0D0P}DV+@e)@PY{{FaW-a9rcfQ(<8P+d5O)F zSFlql*vB__ea3vlEYXs^AjW+V?;u*Ts^K1B)18Pb{0|4-KS!@|aaiosg4FONcI7Ts zcyXuW`MNZ*KQ5MCaRpbbjE_@jphpt;;h%h{0G45CK?7%YC78Dj3pe zUBwzvNkA^kvzUfUlJQ~%kG{5tFs}m@i8y2x{YDT-yisw=kI*d{Om9z-t3tyku!W#F z?(=jquyKP}xv@Cdd0#e2x@AzTa|)_WkeLV{oRH`F%PhX{0}lsq1Y^rB0sH|3Nl3l5 zyqv!Uz?|U_8ceSI4`m>PW%cXH2eD71;r6$Ma9BxkJUmf3Um6PuM+?C4JkC$V z7G1axV>ZYyDE-|@!ei|%d|$|SRABQBuI)rnvIwuc?s)pptkPYqo#yvBwqr5VcC0Q|)0-GpdCo@3SSY{Tmv z+95c0GXCm+(OP!L)^){^_O;iX@$5c$K4-l74UEO-4i}f|M>wh5dMxcw3NF-Fs2dGpURQIqHI18M5! zFh)-;&(A(UURCwL$IIS!vBj`hwHkF*H+8>@oc`|^Gvj*Tt55v~!p)!zM z!cjuh_%ZtF<*~bE35vDC&3)hCho-3;d{S!CG{p;&Iyn|O-N|1^39Q0^lV}va6Yvu0 z7en+6PNVAv4^B)i!kcoc7+9uQtE>G>iA)mqZ}$*eJ{2Yy&ohB# zi25Vt03g(26v>ob7*!_vYlcdY;_1NS7q#*OY3Hw1p>+Zuj0P$X(?qm=ryl{$@jgbb zw@#^cHvA%pO*Bs^Y<&olVK|~fj|h@Ue{z1G--Je)74!fXLEadxSdQ&`yCJuX>3rcO zSA-FU46IgCVeygdL+SD6vpxD-+ovdcVk1 zWy%fA-e}nEeZ6v@>o;Gl1>C!;PeE&&tXRtGdPdHIzSSF#T4Q)Z7 zI?D$7{YdyC1q@KWkaS(}BiQX%IOG(|(4olO)+!YJS)K(yAl$0P1rmeM6{d6t@e;(! z0Yt;W$H=d-eo>ME6!}3syFO0HJYv^u+q!67r2yk{B&!@Hk5q3yUuEzle%wP&9I z=9OQm)bU84U3xV&f+g^+Qxl6QAH$TcgN|G&m=T-fI(CBv1CAvQ(c`f^nJ(?878o}5ex@4JDVHBYW~hf1r; zj>}|4C$Ity81!n;E{u`)3?ys77kZ}`H8*~aH@I`AxbY7~`bb(jxF@X3sU9|xa;}HB zeJO*BulS1FC2fyM{jwYd_Gx#l(JNXv!+p3FEW7lsD6Yu1G8x?R(SK; zJ;-!CkvVNd+PGf+JV(lApK)WaA6U!O+z5JktG)l|p7o0hUJ`<`D{F-+ zkW6$97ev#up#lvOBOv%Az>JT*Sn&lc>TTZQs*&5W1aV;*VmfP4_#j8`VcYyA6Cuoi zt?{1pLLpZ0kAJE#lhV-=B6=B3fXMDsITQ~U;h)khw^x^$I9tdWp&E^Ah3K0o3R}ej zt%N+c_Bwg}W4WZ-bLRq|u{tJEQb9k=#c+n2mGkUmn0N)lc6GhbMB)8jG6OE}DYyS@oI()~vg&JCA(sTDsL&gx>UP zs&VAqEcD1r*oAoUUaQlFGA3=8AT2-ovoF9o6WRY5FxP;Y&W|%=y}T+&W`*{oj#y*yrS_3U%FI%{FDPf=+f`-8x>^ z@c)$Xx~@S7$X0-(S6u-zj_AA@4U1cif`9$QNBJFNLE!0t?;bJgvTU*^e5AX`-)@~Y zyWdp+QA#}PO z7wF6whf!lQ$NVx%O7HCSPnmLn7>+0l`f z_i)xyFM*z$xWI&NuH4yVkC1=of?Md3e$ z8a`Fj#)fqg^?6gCKNBb84ev5jr4Ka#*Gs|uSj)Bw?|_cXwy__6bF%O0>oJdD~UAcAVG*^SVLnFI~p-< z`>yk(M1SF%n(B|58nWX2syKVs7zyZ269)BDVHy* zFd0>?Jgh)ngXCSqV_EP}DGmoj%Mh^;31mgU^>};?=!}n6cp63q<>F_uuX5Xgh=My2 zg?C&xDqHTGOB2~wsKo2e80J?HN=gzk8+$4S(l+m@a)8ijn<0Ekl3f8cQf(YJ{#-~#s(2~HuSrdD_rF1K`F=vsWd4{j<^^K zY1y^AcMYTb`7OjVKBD6k*3w5E(}PsmexXxY<>rxArku^}pa<8u?yVTW`6+6=0lxAV zJI(Ay!eJ=#ePM%;dmRtQdmLsAzJ(_n$GLLe>kSSckTs(d*NWc3e> ztOzh0(QA9c9ru^!$AO~ADO0XBg!OY@L)+0uCO>CIt?}HPAqo+>fC;JiPmhx6xgTtY zjauD39FeFJDgu?t?u&BePe&FpVOWNZ*ZF2ohjjaJ-)&%DxEog3lAb4K?ejOanjY-Q zw;(I9D<@UL@9SkC6y_zB)i(x)E``ulJ|iD2m*@(8N~U(Sli6{VPve0c9Axzwi{(WC z-paV!kRnXh12j0!oEYDxvW62_V&l{1)hKGuwb#xkbW!^ma1QIavLVic!t2~?j)wU8 z{Wm{523pUl2&9KNZXMjd!smfT3Bt`F?3&u_hqB~D)o?mZWFcf2_~9{Qmd9E!6nREr zP9JTf!4d3xI2KVdQ@bxDy`QbwW7P)<6Q$pq3v)#_=VlSs)#1#0WUuoo!*n&R-bg&OuNKD1#OF(>#12=|-fsH$ z?_BuHusD~t-)9oq#=w^=nYoz8(hIk5CPygGaLq>uy^pwwE{xJ2(DB)K;vMD@ddTQH zBj>XZUguyWkokn9;q;MkC}%i8DqsNyXO2YZWytj%AYMgCc{GAX04y#2f)CNmhD}16 z?P5BSKA&td*JfhU0Srewuxv@KJ(-~WMhQ3NAeKW3-@_VFV?j!KKC(SR{ZK5ST`HN= z5_{-t3?=pYOXeO*-+;)JDCc(@fxN%1c$nsH zIC;f8W_cuIxyaAZJ35>p#_NkDmCf;;?J29Wyl|mx(PYyHhi+u(^Rker` zf^r2TpQ^y3l>8-?G9^{(N0eq5g6_AgO3$hwamsN|FQMQX4r0uPKstFYRTeI~My%V) zAxPUU|E{wA{$!_R)a9n9hqg~UUG4llij|%gYwDybm^aR9hh4b|m{!NtSmL=XJ#S0W zS+oN;o_25zT)1pVK%FKfJt_RKvX_q|XP zYa;5KB8TLCQ8>&QK9@DYXb$H^!C|nlPR@0KlDB$2jQVw424?1DLN+K;qsY-Wcv+JTGbzlv3RD)dPW2Y5x4-7Si*sk~*oEDL#+$pm(VhxB$aa5gQl!U`XU92d_N*x>gQddr8mw7~_8rwu7F< z3~mPrf6WPEu+pP*TC#VVG1pIy@sjzKg*#S>tz{h9l4K${UsVZ8$(rtnqzjdTWLbdC zM~G|BK!=KGo`P}n8dC%HasE}FGY`8<9(D$3Sm**TH=YlGVCSYdNTos}xp!G!_SH74T;A}O~;QD}f%Y!PmWwze%SS>M# zIgaiOuN*~IF}JqzE@OC`2bo5LojpME-Vyq(Ea!Xb`q2!)oo&T#N{F(C@)Yd+(9 z^CV+ZLu!^IQ|M2jlu_o;hDhg1w!;%9g%yaBOxiz^pX&jL^BvC}B-A`s4(q`)jL81)mViS4 z!3^5(1x-B_F&bylqd%2;hDAbV_E-auK0WI?FROiLww-2i@uQ+wC+80ZF=Hjf*5u}^ z(NJ%$NL4$YSMjb2XdbH>oEb;tyYd_>a@J}+D3np!r<2~C%t(5lf0axR`g5n(`rBNZ zL#?KhQc-0#{~fiPb$m@SPCxzT*cm*?hUx$YQ``HVT{ycyLsJhC8jzs~?VVu=V)`%h zK^cA;1v0<(&;F{4Z=2ZK0#Qx${_lwT)JDQ1(I^WzxS)a|97m@giVM32I(qKO*Cnq~ zS@-PbLpM^mQ}I1l!`z-Rlj~BsW7095>AAMfr0Mc#LV$#tOonoSLQJvmN&!L7Ba23| z^Nf?e%ksNYz0WRQ{ulf5+nt9?7yFJAU%A-!{avX0uGO#h z;e~HtGRtW{hc<;Li6YQ@zD!9$^irNC_URpkollbH%lf5~1~hvIbWR5_+Jgp3gESMt zLE0TvCGDYH=K-_cA-B^ZPwm&f%Y%r8E{D_C^kqZ-Ny7=f!^x+^Q;9uwjUXJ?aBh`X zjNnK~(r88RXevsT?uK%H(wLO`X!YsX6YX&qLH#o9SkvkF#@yJmq>0hqiKQdvks{{q zsu4=>q>25+r1qPQ<^6dx>52*$&*(97H%oe8(j1bc}?n`o!=rQYya!l36Sqvd7B~luH>Is%s)q3;y*&l z$5|uBh2g{xP}%w2(?!;om1QrNG?nHr2`*myn4HzKJnq&>3z^qgRGFxT&$y}1C4YQD zDl8pgJ|WE&e_T3#$@PTO45P>P2!8%Wy8`W7VLe;nxU$NVvda2Nt!+gaezt11xhf;P zrt>9Ui;kg;AgFP7>G!`c=Yv32QTDIob&EbWW8n=kF=flX4Y#v(rz@MjDVu?Pn;~cC z$3~3%mYw@X#M#!Zl&v)3&6q1}mSYC$pB6AFJ2Hym5Bs;x?w-fW*Tqs5Zl-Lz^nKm& z+U@GweR;M^xw1Euvin$gH^Y5*_{z6|zP-s$d*g7nJr8bM{J)}4Un)hior?FqqJ$9h&^W8ddx_+#cx-Fo_b>-E%jm1wF+WHqVi|G}%uYf~| zS6|*QA7 zl=A9S?cV9s=hJzSfA7yk+V62#zuFQ2y76FsnoS-LeO^y~wZ4(!0wm<1l`qPkn`p=y zY8uPM%SjNW+QCe2xof>7rMlO-f?79EAf17NHH=Gna4zm}+B&MFp-OilRC980l{A*Cjx49EcS>T>< zsdsuDuzJDDB}v}3rTT_?n3kHA`GzWO#nESb>hQ8A4T(LU7Q8C=x%29h-qSYEL3(zt z6n5Rd(?3VMORw_pJ=vU`O*H#()ku;Sj2)4p2_73=#|Kl5t?}~Gv=!Y1h?uc`!YPNb z(5-czkLS5cQRb^L<&mb2)vUuy5u(kVC6_AhdwqzC={+2kq?$`i$S2^6%q3l+d>_rz zAl^&`GC_?a>9@+AXC)cW1|XKzIkhBY9`4XoC^i6;>7fc_ShPti!EAbd+sN>%3~C+q zyA#@%@Hs`%V%Syq`)S9j?mh6KNvc&-?1&^OhYArdKvLn-w2r5v=?U76OGOES5br^+q&4b=sL{;OA>-?iGHr4E~*Kd1j$qn|HPD zRaG@faMd{hvH4N*9P2xaXnk1OKCu{q+- z?>)zK+rdSQV(M{!Sfyrv*;@%yQT8Hhc}}- z?NHl6@|$+?PGcMfoOSr4l=&*W}) zrH0tyUu$I5uwCVz;_vPm&^S|4+F7LVe_AXp8|=_fK7JG~E?)z+B2l@s*25Kl+6yhO z<|Xt`3q9H$5)xizvuqTLTigdLkr0BxM+Ek~f?=^{49k_}=H&BQQtdrByGO(t+lQSY zjqfYX0Xf*H*!XlLsfNY6L+|o*`GShyp(d7wTw}Z2>7kqzk>Mk*$4)$tx-A2$BY+un+R##^- z{Xi)=&o>I4Z9}w@#PsbVh9&oqOzyBXj)au~t}p7BD#$-L!hks*Yh;Zu3B$BO`Ff@N zO!Md`1=>PcdTiIz^|UxdCBH)q)EDARV#-4#zaodmzaQngPwN-_ur|_oQ<344G!Rdk z&{KAfY5JF3cX3tKP&xj*M=a?JejeukJsrptv;Fhpt$49F%TJ~p-qclVUE6wg2=A-* z9V$}7zgCQ_$<^jgjlqQv>yq%($%kGv|B5vqA(qmNtE$TEj<@O6eGWUd%RAVJ@wFD% zK+8CLv(WOJt8%LZ;r{6CFnW`EoBXV~`?5UB^g|Eo&PGEzt_;^LC*^_(rN#`O1$vp&JU>r7$~(-q~gq( zNe$M+LU(O)P~u+%6vqt^A8IbZF2x$D<}@m`V{-xr#S{4d4H)ivK=S*%GGb6eQdyWB z34`H_SCtoSJ|Tqk-mE>qlWWYEWVxJ#(|D)huSvWoxmM=cl6I#nii|3fwT>Q56Ctfp z_n6(%RUPENju6eyFavfibr*JN#@~)CJu~9^qa^DWTQ7ruWqwPkyO4k~&}yz>3*g2I z%_D^npf9W;K4N{bjjuI+F*A9J)A@I}FiLZtr&zZYjFyhmFYkrxxRX*&gA_!KS4%t{uhemf5Xv<-KER9jeP@AI z>0GW;v?2eJn~|*F6Sv^_ql?x24E1NQ{G{X^?Pb$eNcM$~@;4I3T_s)ZGJav zEv1oEL?Dg&VI68*#H?nT5Sn8iTmC#P{JX7#RfI$_2bH6vB~#4u0AhjysmFML6@N}c zSGgIy^TLVO%}Wu+{JyevID=XqNiNF~eXg{AQz`c++q%6Yu!Tu|I1>kVD9@540mBYS z%iK`7k+`({{dsczMZs0lQj?0x+kAU&!Ksn^Q4Pv7_w#O-l%r|~zk586dZQC6wvo6z ze)V^(`7w`oAmrm8_rf;7r|%WmobLe}0yio|VE z=MGIqdu`9RG0kSu*zSL!z8&+~$3BnCJ8rq*w!|3#y>%tN`L@cx9UqPP#qqpf9S?Oj z`t-lw1cTC9jXgkIi`^f8BL#YQNQ+Q z$-VTx-%oBO|H!!YckTDt;qdj8&3ms-*Kb`pX?T40Yv5Iy@eIg|U={ae_ZICmpZ!pS z3#13f(MjXZsYMes?VKkAGsWZ1ZBlj!9yWsG;K#F|@Q?!>S2>=$6L)bDFFbYJ`e& z8>Vp@I;ZCbWWOL~cg1J>o^U=ahw=84${Vu>jB|zpa)wDcl#$GPodT{aId9^#uI-G23sV0;-RFpV1(MsG# zORjg7cb!aZxTdni_wl#N7zOu9 zQ8MMJUG_01$w}{{pJkM1kCxw;a>{=nd(8`Y2UA`WSn=AYyoWKdy08GUQ_;~-4&jS` z_O9aLi?Dl{l@BT^A9me@TxBTs%8ZJucxrMd?Wy^#7nj0jDz9@?cJJKj%Dh7fbnX7F zOl>M=lB(?L3a2#PY}u)5hE{hr6u(rJ$=S|+mRbE?Kw!$B??EJ6l zw}0Y{HGH?qm{ow1t$bX)(|)s>$zwZ_8Sl#j-&MZ-9arj4eAiSBlqLU(xN~2Cc1aZh zNtbZyRf_jmtIjK6j=>2p_%UK6YVu9)o~x&P&3Dq~nPdB}iA3MEea1#wm#^Gs{kFnt zb1cF8;UrhCEJJ}Yp`vQpdqu>o9nX28cS`+3x-@j;LzC@ z5bWj4e@n#X0iNvYE`%D$PAaQLJ=;jsbyXYI%ZH5Ltr@3QSih&L*L|R|Nhotwp&`ED z+6KVoBYRe{xBrKuGmnPyegF8ZX2sZL9ZU8YOR^hFSz~OaNFympjL2Ti*s{eaW!E4@ zim~rC_I;<2GL}k_hSZ0s`OWut&iwVv^T%`MoO$m1zOMK6dhyI*D$|J$ySs2vAJ{bJ znTSD2fMRJ3LUeUGJINpwuuwj2`%1CK{+o@!Hx|!9sMoR_Ivi(gAZRj2z!?b$JOh}N z;Vr@d+=Hx~*@-g^zKY=rsB|i~?k@5pHt;U7a*147{Ktws!M(qOm?c!S#&WmggtjdF zZuvin1s<*86Hmj{a9^qsNv%0jStCANBe_u{p(@m;c|Y`d`K*7fq9MOAOynB@nNU&{ ziRDeE9i3g{4)eu*03f?GksnB~9wK+)G-?_v!TO`5Baa^pQN_*h_&`MZ@?an2i8{+X zX{<9YW({JOUfu$*5nH&Z%$5R$QmOdj6H%p7zSkSCrZ!%yY`i|)cwTwW@1%10Uu5`o4^X(op6kL>N0&9sWx1D z3vX4HqBem;zY0P2P|+~020lxn9+s7k_sbXpT)$H2OLBf80ChvPt^2v}{ZBk!o%S5?i+Q9Jels22H)+;)2GL91 zWcRpq_McxI$V3l5ec3y(6R3Q3Fn46wGEI!432bl&b{F)}0!9{E`kT{kS9uP2)-alk z1e8Pu8$Dk;$_}Te4ZJ-ZnOW@58tDsM9A19;CWUF|KXx5AW`OnE4LpFr@2~dg3n3ElXz6{eYr4;FdS= z>*@QVnP7Vckc|atGJqz;1vBE31Ri2SgdXFde6b*RYC5}+{Sny-{PC9;8pwoaGGSxP zA014!%<>D0ppWLuLV=vm{23z1Hx_D10Q-`m0#aZv!h$c0*MkT(p=EdwxcJB`9O|t; zcHRrWDiXLVvIW)0n)WI+Zx z{#z5Jg4txK42FDL6x4pe$2XQFOBVGF{Cw5xvyKCoHxYOS&t*>pxiLVO>7TqgB0?$1 zWft#w*4mUPmlp;oZvweY1;07Vj-UTR)$(o{|o>UY|DQUV9|9Ms<%rHO4nQ z%i)+q-SA*FDiq`n1vLXf10Xjd)P~Lm8WU2CX=F13zmF)$FL0wNos*Zu$Pl0$61gIa zwwl>a?xte*t`=)bcs(-cET78`UotTuwA$@+>`YyuY6Tt%6 z1dt*DBtig*lec6T-)*Y4#PM4q)U~hwc=?F@ISyNXv>yj!KmKn0V88w`mc(_H0li4( zawBnFWM=*skpUTpUZwp2RsX>7ZUch0g&n`2@%uhMwjB>oJ<8%WW`a#H5RlS_koS^u z^^R)LlHB-?hUtz8kzdpCr`(TuUURr!^-l`*r_r0A#=N@*Y^6xdt_iQQK3mBpU>DC; z3J}=UAK$fd{6GlWr4ZQAo6onIAGSTD8;L#nw^>b1nZH)v&vEFK$Zu)I zhc&RbF{ebI;r_ez1Q~kwKV0m8(Hf19CA2C?$maynSm`~o>E1V)y?a4>k*0ge7aP-q zkO_SI=}UVY=zbUj!ani!-Po_fjQgKA!KdecYqiWMb_L?6l-&<+w;c9P1WTyoW}OFx z;y(O$TVula;J*gm={oWKrlrQL@kU1V;FJ~Q^Wthz#^J&9eNe@uME1=ei!$~*54OT& zFD@Q>%Z!!>s4)M#NqTkAdiTIbbprCCvE$;uFYLW*ZPz1-hv%Oh{&*8Pyd>THa{Nv~ z5c6IC6=TwLP@gssb9aS(IQ;M)^Nm5|H+f6WFh`dGhEGbzU30lBAq=N}sG~A#l_7mH zUH+WbWt%Kzx2nr6HwF8Q_+>}Zu*F@Y`RvfGwfSkzfV^1(&(ZTU>rPK?9;y2-%zSkz zcPeuzJ3sr)?d7?KKuHxdh0}&1`;Pma zDDi0JgWB1rKK5QnOFsVZr(epaL01`>eEF{tWxgXS+RtkjcYG9bE?!;eIY-&JHdEnN z%@G{_x;|IqJD&Lc(UsG+IAyLC)u#0Kbsh5x5R(%@Tc+U;dDGi4n%$j~vtnq7gpb61 zUx|Mo*P83BSaOcG>1g&;`_h74)=PyulkjguA@(voc^1~i_i+V&v^PotIQo5a&!kLNpK6d+=0GX>sE~)h z(@{aIZ%=t@{9b}h=(gIUrc%+n+g8{(!JF2H0EyEK;Gis3ZR4hPpkZf0mewHjdlyc& zu1YW%Z{DbCt#;I#AIGE9bJMZdRCI9d;c4B$%MTq)GJifi@zpa#K!17jvZKktZpgSJ z;BUx;9`tC|IG(RiTOfXjUXx}-k~nQ8tJ<*ZY_B~V>T;0Q!)RYJZQVGs%C4* zqBK=lWi6|Q;d*nH?e6pUrkWU{el`0tcEox(;cf0wUavE5um`T1@t?$l@{EsWU)^M# zDhzs|+&kj(dh&O^7is=?zQ-=^Sz(ZE%PNo0jFX~>p;X0{!mIGbn_f{H4dGsd8awOy zJf%;&7s+7Z2x6?pqbvo&-EQkb`#$7lNwM$EV7dG5LIE;_+T1;9?HfAU8HOV><@Scy z;~_a-H`1CfY4+c=QVXKK3YPJr@Avar?_jRv8O>07GrbmrA@(PcP7rZ#IIss}^;-X= zaFA4FnWV|(uYG(ji)6I6AO(qwyfH zoTup8Y#J>_@haO86#P8h{+ZjCdB1PWUU9=ylUI6fEjlTtUw(T|G5`0Ddw;s=jB*)I zkk;4UodB=GMltUPEv0!8cYT`EgCZ(Q#oTK%kKVimuV^g1Wzsny9KccSrHA8}_wqdt zYr6%)&At4D12%J>W!JP9mzBmZ0uvsZ?vbCJP5uUdFZ1|Vn4@8@(K9`s-Px<>dQxga z)^FV1Ze-s%{P}LlxkHYuG?U<6Dh3XeP$i6qjZT(J;Sz3X7S^vqEy$mDCcoN;$uZkUC`t>=r7d4Vz z12-SPEsrxamk~Ch`@1;`KB*^uV)%Y8ete5S9D{?BT>z>1hP?_$20s_!e(yeC*!=3? zA~YuPim%Yl*Wab^JRQ+~A8X7l)a{HMH;}gwf0lDfcZie{wie5~0WZNX$)w`TS4C>| zBzk8k_YL5slJV>3G-(Q{0m(;ir4nEo&c3h!JWgc8`lLkdc8Wp0MOf8Hx0>Y(y}(~3 zB2-Z>ezTe~Cp;#<1NY25{#uIj=VgI!@)* z!HVW2$tWQ5_WZKoJULNe2bXflA1BH!-m86n<2?Fmgxa46Hx@|;-k5vtJs#Ubft;(zW~W4VJ_HNu+r;l?!65d5on`FnkBHNk0- zo0rAKTY67_)=WDm!6zYpWSF3vMU9clT|D_g_4A4aaEB(bqC zj!Jz=`W|!D=*to1#H1Q5Mh1?DnPb$Xc1BV+z(h&un_NyOA2c!`*7|0RgZt*vLUmtT^9O&re8Yk;vf- z|8{h_AOM+t2owQe1Ju5Nuz+s>oB!8C3YiRf$hVP-SH;IJ-;rI2n5LdS zeh(X_YyTp&aO!SDk?sBF$zuJGuOrFJ?mN;aqJJ^@Ud||d(U1A_?4Qd?Qs)~bhgOq> zlHV7rEu+5iqv>^gX1ePCIuW0#)gKG5qwP*7vFH{G?5gi|>p@35Utpkmf>wmQ#e2SG zcf$O9H)h&zZR>dIxNVz?>mNIAa1`?U4e{|mzF$7#JpIJZJuaW08s$E*XmKgek9&G% z_K;UK7G-s*IvtBrAg7^5Z}E|_?hW>3m5&WJJ7c`Ut{Ntn7As1_4G_k&wq!B=n}@1@ zt)%IEerkCkZMJ+h-AHN=e8HGYSw1FM=-h+5D}#D#5A1hD zS055iDSygx)Q$Aa;yzs=oW(==kM|KVvEoy*=N-SNWLLrMvb<|mU$5koYL%}#96PER zUl{SR;%brqKLHWU-PdO=`QwHCm5QSk^1hU$=nk!$MhlxI2t2U$mw({mW=4HR07Md> zv+>*UN4S4QdZO4pBnH0=puc(l3#aj>?L{T26|y{B&C6>QK<_y?W53-i;3(14 z$D?UaK(FLty9VU51GHcg?zGw=lxj@ZFs@(i=ZMatFcQ1dA8BL=t5QbR*3#20Y z@6U0?EQ~q)QymPJ5{6?USIHqCe!Zh>bhI+#+N3%^KDXmc^ao4p{s-mo zB zWpCkxY1rGE)quZD=@@3j6dye3aI0hEm*F-5@^PCgqCNkJ$@9Rv8?pJNW&JoIvNHAK zCuf`vD{?Gq;$ZPx*BAWutMOpVgQ7#(h&oA6JXjG@v>)GRGID`+2N&b{S>c3sk8d^P zSDg31_~(Wn2aiF3XeNMtKU;gh%0FgrWogxF^2-S)LOr3S zUm7M(S4aK#epzz=ziupul*FfWX)1-9<}6q$+{^0GDwxps7F_m~CU-)OVR0guV|+gN zi-=~wW)Y=y2p)bCVH6DG-z|YFW0qiBRI~%URPg9Tw`d9>mG`Ncu%%q5)X5H>cOJDkGH9JBZ%cvgy0L=iQi=b$N47Ap z2}B4p87+q}wxtyh?}GOf7BwJt$5Q%{PdP+*Sh#nCu27si2Tr%eo{rHWb{eNIRJp>>dDu4)gJfwgBiD?|nMoi(DNbf+AT2yDRARG*j zQ|;2~V%7lB*nDY;)^~naxyyMR?Ydv+N)Hv?HcmHNj(m!<< zB14**;N=d&!+W2Z)}+BclQ7Z)K!RDWdm0awCK$E8DQjdFi$0+)a&qpZX8Vf;eyS{= zvJw}@i#F9MSqDj8PtX$PLmCl^MWsY7G}Tm+eSdc$6m+|_ZI}>m38B_?@C|K`meb{K zv!o)zC6ya`Ejn4|S(|D=b!Wi+V)brx0}Ej2LQMPk*j)JRoq2(qHEtDu)z}FP3vZLZ zc9<*hSZ24r$49pn;8i%w_4GTbK^DCW1X_(eUP8^@BCg) z^@P7>Mo_*>VE3n`hS4(OT*0hpoxLUOjy>qnl|a}aTntLmOcXOM7SZ=wXFhI8Rj1N~ zedtPvzKPVa4)h@EwG0%N)^B89jj~lsJfcJB?T`HBd+wvMSp|+ud%%1of=tos!=eJ8 zFH7sq0pCQC!O~0s7fT%o_?i5oa86b>TEXiH@Or`>tKy|IMDsVvgt*Yo&4vdY<4I}p zrIEik%khL$O8zwj8_oftc_Pm4*dNe+5uSyU41YdbS{iTsim)pCf+oFGIa%^u?5O&q z0Eg7%*S-z~g7#VQT1GNxzdrQ*Y@FG}(R)_HUR21U?_QQ<_;-PcgRx zE}sZ9Eo*A3CuWt0w?)LvpA3%dJ~t*?PVw2{Q0Hf5_(>UUi>v>5kK_QZ;LD*h^7m0H zxC^}GyFd(oFwDiaE34jNT7c;eNstaiv(7LPYqnF=yVGdxUQhZDs*X}jEh-!kdxR%D zDgP@a%`hnwcmH;PWh`O6`Fi7|b~tsdC@bn+v6_Fi!|#G$}kxU@WW#eD)3vyA2a4bt!xxeCdN`P&Wm?+oku$vdTZ8@uIYtqH=bFQW3-ei(Uma64GM*rF`$6SOwZ(R|US>xRO;awr zSnxy4*3RA$)iL(bj;(Wvg(v_|c2hp-+_40Mp99Xh5uo^P1e>HizM}>ZA<<~iGZVNz z*i}J*(a8u=q^OY|Hhk-5Qdl23lRN~2 zf3o@XS>Fhg3v&q)5g=D8+y)$!8v+Yw0TqdHW;jR~25vE--aUo6ZEZxE!#GVK3Q6$f z0X|L|TO5EtPE2wFghOi5f}bPLV6_s?SjKfDp3#A>&x~_KwM%C7jHz7NIS?u{A>?vO z^HsA#IU9}c=q$erTm2_K$S2a2P8Ni_6`TcKW59m@RD%Q~pJU*W%#4557=0XBDHM1& z0@&exm5&dM{fRk72KGGUlz)>_BQnQD!-KT%mq3Cn0LTKCmCr8Rj|{e9!Q)w0*O>5d z;sZ|tC@2Tw$ATZTfj=j~SnNJ%1_N={Mc-upA^x29mWA;zFrKb=ob@=1)dZfrhR?85Zxaw;0|EL4JghG})Y=mgKNU zCRuR=roba4pwlg2IF;)f3C2f+5wj6^%mc+-NG=&1PlCBox%io!1(-L33OUJwvq_GM zEO@lOd%=7zAe2hd#s7=9_~nxK>{{MTSl-Es?48F5Hxkg102O2LJ|kP4_^F~tgoRO| zk(@*hEq~k`jMsTwa_#ZeucE>PgD6C{J~mvR7WPLb`~@J~iIg2(diuZ1$ka%rH1=Na zG`IkZzr&6Mo@By3@o+vWmnW_$Eg76av&OODm-H>oAT}wMM!)sl5jJF4vU#7yj(p%o=fo|MoO*8*&YxiWOH(fsSFo9VKDje|Wq1pQ!yQ zzUKrEU48t^2RH~1|6m3IlA$Sjg=kTzEWM-`Y*ZCtqB;+z(F$X(A)f*6r4x|_Y(P*E z3z0!D(oW*ixOV?O7`*&7H?Oq9Pr=0l%0Q0vksDLZg9SSzWd?sy z=Vn#?X|3kyA%BPg+25)Uk#rtB9TZK6=hKmGbo6^Vk0JfK07$-0hfM|w83Ox4=zSp) zTMN~~fZM-R!jCh6kj!e{=vt-xT9vk1wP89N17u^ec_>z#<|~f9A8p=cDU+=nZDq>xtr= za}>}%`h>&#>V2^W?#!!Om%^n&8q5zG4v=)mO1g(?V?6m0)3f}AWkp^HmfR}3HkE^CXZ`l(_jQzwISUh zietj0!poR&j+F2u1Ioh!CgWX|0l-^FJ>$OsFmyPYRpp4|`ZEM|1wgMrJ2Y_Z>Cr71 z0_4;L%*TzPD*mK^-dO;6P?b#A!E@EIc*O}_E;6WNXHjS}s`!^Z4++&ptUba&mt#RA zOh60{9bAEE!_*tQp+K8}rw!FZuE@v3M8zxTxe3T{CuAQB`0z6zxe?wlfdaR~`)KVE z0ALgy9l@$frK4RZ8j7iK0^NI<4nGO4#=NXm#({26z%CFWazqG%)^?c3nKNu!v4iIr zK#nJY{g`lgKBAo?kHY~K*lI!|xO>ASU;`Ci8{G=O!u2i{IgUlh61n$nQLiSrhNvLW zOIX9ig&(cxi}}^bWFlu1a*c?7)CNwT0OZTJl{CDO#&9Dw8G?8q8Z$Vm+N&&7pG-t| z(SSVkYd=)ZHNWpu_UH^oLpT`O63Y?0(6npipg|E+9S=j0Y@hw z59uNwKG=tm!;M9?5s?=v(L)}f;fV(N?{kD`RD1rApP8Bf4)MtvjjKyCmq zwV{uj3a0^pTaQFUHvtXwUT!L=yd5pb`RUIfIk2x}QtQZK+gL&ENlgE37B3P2yiH)d zds)4}R-=cJx%e1};)5y+7FNUeHUL#Z7<=v09(E&9z6jmLJSfCFe80&t)B}ete_#?*dTm`;_1z z@3ZLn)KN%0y1IO0bg+Gz2gg}5=eZeWo_UA@Dk7KAC4>bE(S$D+q92P7K7Qpq?uxv2 z6mf)(-j9N{kgueQ_u18>@%UlM_WG9(18J- z3x1@9)K?2E6-3Q3L4kD)!O)kSo86cr^s0f-==rKxB~2A~=WJ!k{xUsf9?gHu&e;S&Hy0@`dC z0BP`kzJZt^O!YlL|G2%BetO9>z4g4;()RtSv=2biCgcPUngB4kfK6Bg z59^u;9nD8YJ^sggjf#E}SnEhd*Q-sq;n5d8psg2>A5H{TE#4l+AhR8i|K8u8Ab#D> zL)r0g-ZyPU^lLOyYnj{B@6=ECQJ*gsZ4SKN9P*kUyVHuqe?E2_0KC)oYm}1`_*8N1 zJ+IXJ0xEMK`95mw3ylPN!a|Ff2#MqA{SNa_Z?}*tKfhG1W<+mRMg#v=HgNTA-S+_T zvE~)t&;9&30$JJ|xx?aG+WfZwK;tnm01!AnS2Rk0_a1CW28&ATWOa0=er>^4%TOo$@==>d6YMb_G|GfGS5SwH4Ol9dlVVyAj$=CpJ^KL&JMwD`J4?j46 zC!{zPl8ylhk=qCI1r*-U^~LLP*PHxO>7fVBDu&a_r|Y%v(!Ek^6AX4OO_4|K-v`JE zi2{CljJIB2`W-d=+pFrAg$ME(XMbVvyI!(6_CQd8`a96E{jT)hv8AmD6taxD;N#d8 z7B^-%`JcbW9#wk(f!%*eyvS18UX+GVy2gIN(*DEidynq!lZW>VYW9nkn!=<1TzA|L z58BUh{G;#v=RswEIvsBQ1|H8GiThdgE1RoT^}p-VKvS2tNYtNK8h=vX{AVk3aQiw} zVn%u5IO2JJi`zvy%I*;Cft+IV8nUTeC$X(L@2k0G=#1*xqyJMA@0}X{lR@1ptvX?|jRD2sxb&C+Pu3V9vyT#Y*C&e9;=<`HD8_6(-Dd*2c(lX&o{Fy1Z1W5~ zW%aCmhFtSxaee3`bF0fa86s2ilpWT^KDgo3CeyhGh>qvHK@U08qZvAi*r$B!#I>kc$XWlf>S9k!nR3 zK1q_+rwUj8m$~w}vNN=S3g?2oo5AE?e8mhtG9=7ZWhUWnycpPF_nqsirj7jv;QSu$ zIj=}^bZFh&VD=AVxmzN3+`G9woF4<0*PA3Dw*O=*+EW4-o z25dD~wH$Pkun(O{NwgZu1Nt#grbE)Ept`5_Cy=OR-YY>Xhh{9FOX!PBPo-*0u(1TL z5Uku`Eob z-B#vrDMT_mBZD4W67R*tnI||q7Xu6&w44G3VLN)hg6306c>53K^2gicC(mmcDGtUt z+d99yK3@HszB#I^4p^-gq&Q3j(PY-6{$zqgGmSyCd?k+rPaluZp)++lXS9% zp8~xkBX8NtkD3d$E1WGGu2TA?0qP2QmzYfIAv1;v2w8KI&Rf0G~?m&V!B%wxy6#_5sKCP?Vh##_iD0F zsS}c|i3n`401>pl1`E2Vz-20B)sx(fUHE>F9ZP%?IyYPUGtXV;Jn;Isw)u|0y0qaZ z+@~yJillHs#Ij26T*Px~*}XAa<+A!|*>%c8mp`xNVohP+!mtY?qU&HATkoSes-KM` zS>;afQ>4z!U@XX7VH}wV-^BR}&h2281o|FC8CJ)&*zLV)=)W$s^09NlY}@cj^K}&^ zA|U|wkKQxR;3AS%o`iq7VD2x-w2p+bIxc!cg%U+UiTqJ}gA~+*@{+&s6vnbcmX-l9 z>F!i2BgwnziO60-W4sW0IQqvvjOPV4KI5?TqFZ?vChu&#EO9*|LSLLUrO>|o=sEjF zUmNl4){Y7i14I5aHv>B9X$T1u5|ku5dHwjyel7Z5P>NYb-MiH)SV97!fGKB_1iLm4 z9c=tJXs~gxxvW%%p1!*`DmuwRxQYeTCU<3t0)U!n04Q%x3D0x)UZE=xO7OLnEUh`o z20AoZQq4I^5%ANVX0WZtktNr zq{q6A331)2KJw8pioqB$A!)HxicddQ80{=uu=dnaf(jH` z7E?Y_bmG!ZT(g=7RuUWU9=n}-22#c|YDG0gP5~`gYl=T3`rVyfpgQcAM{%=YaVy%Z z2OXXs3Jv=&Tn+G0*8&Amk*`BSBjkWv@?)l0l7qX0OV*6#GH;GGHTc_6!w)me6BG(Y)dQMxR9!jds}md@jpG}`PrzqwO+L2LAS1ZE*qR} zlClDeHRB;A6|S`3LM3u^2IB9+yC)zwsA)hZmlg|%&}pnWlMukZeAMt}Go{v<%)$piPr-;e8P zpKb((qWwnP3*U6Z)LY!vuQ#+^*m7Vt%|e4Bdc{BT zCC)U9Sq9#GbDofgd)G0_>GUn5mbMeKBiPKqJHOt)6JjL1`~@YED?Ao6xg0w-E|kDO zwK4a#+!-@RGoa3G7m*tx5WT-Y;*NVR(cOhRnDKJaA}dU;?1)bBFttc6T0F8Tr%nH_ zdWx?Rksk1?JNKwxY_9Dksr-n(wH7?W(`apW4BJ$Yyp{Hdy*bD8kj?>BHh>UfIzR1HsHp;QqV8sV^{x8 z#?6Y=#e7=b@#j!}>RM-Crr-GH(;s!U{|t7r`w_!b?EN_e&S0wJ#>-Nf)9)2TBI00) z56Wh|tb9$18hw zUU-sq{=Y*cOiEA3S4k8I<6p)SG>CVq#I%7+IcghaS@S7ze*^;gDjY!g8cKq zV8tkPe$fzoTV4;L@}^9|Ee*8Zb`qR}aN2CN5VOTW*e-M4aAS)l*b8!;)Lb!AeBF${ zb^>g*ssG^z7wKFnb{!O!K^{v4OPm3qgw!ao9|kS87ACI&JB+oZHuIs!w8X62w-z2R zgV9m+*OD{}%1;U8DRDbCB?yZMTknKAFn`{4UFP!?1f zXE!`OyYaW*>5T|iE*>m)_?Op#)XBpoy?~M0&ahf5h7>T&6q@l#l_4N*;|K^-=-&39 z^k0=L2Mv30YrLj{I6Hzc*|4pF`lwyMACE19DuO`9*}>^k39Pk~QCp zSgx+cW32FhRtR{fw7GmSMh|N#G(iqE-{qWn{jd<8L^7ACk?c2^A_V$%Hte~Sl-s)Q}0AluL z$CZ*=1_TD1G$cWqLiEPyaTJR<0c`y8YOEE&q(R(lamRqp!aYbaiOM&Lu6)fu-SkW~wf(&| zmr4`78El1*GumTxh&R8=H+BhWk2-|6BJdI0L0%VWgl&hwYAQ@*bd5jn0=|VWn%T@ z!%PV0ap$!wWyvX4&2g{5udlgEU+{Tj#lnj+4b7Rc$cersR4oTGZ8c%g>ttpV-C3Pv zww~I9$+yfa@A-Vm{FW=KOpb5-W-6*2VB1!QBs^(iqA8*Lit*ZdKabN|<%({C3$-fw zS<-?aS~!sQ|@&+_^M-s5ah+Hk`G-gQ9KRJG8+vHhe}#BjCh3_$N; zRr`)wy?y<+*!tSasxdKj)%>bl9o(<;>e6<@y;-PkJL~Vxl)NtGQ#~46Q6eXD$lQCi zy=x<G&n!StT zu;IFVf4jF2$UJ0nU)FJBxyt=vGG`JCaX;?0SX@olShE=6$m*ElPX|Du7VrZB5W){% zC-dV}WcJAUDJU4Uc4Gw4fU89Qt;ARlp?gR9xat2!Y)Ai$@o(7G+1o95jY>xaj?hF{CuOCGbYhKx!z3|1={e(7>Bxc-98 zPk!^_vdP){s_{R%2G^YuCr7Xw6l9mfPtR9;L<(vGfMk(*SY-JdlWnbbKeM`GR9q2M zI~zkS8|`**>5SXGOaNyo5&E^9+%5~~QT&l{t)wXqK zumEq>Q~S>@2I|(aQsp28I^bN)v7f*h9zC8GTqT-8)+`@)G-!$ZO5trD7Cvs!oMX^l zKjemZG;LtrKr}hg&|h`Azgn=Iy*VQuqtS?Zw5SR^BXL4>AbZayR;HY+qDK*+gI6As z6D{IGe;L}SnmiTnk;hw>Q^}k;1vA${etVEQ0HiS2d?*H#U{p5irE?R2Y@j(X`=AK8 zD^)Qsr8&{?VOsyqYTuL8lu{q;ZsyrDY83bYC`$rVI-H$o*E;6ktdi8Bq8G=F?eV-d zZTBg~9y)wP(C(X|%jZ@@(Sf!^ZM_}w9w)|GlIwA}bFUM&N2fg2z8tiu^4gFABoNx3 zw=GBpx4nvnNRUwy*0D`Wpx%ms?_!iMp%c92Z${!oh(`M1gQk)se0Xl`kt8P*cUlUn z9mR}~!^f3(cPy=T$XmyzR5mBJk?onM4E5S-YkhI0V*obHrWUY$9zlVuNT-MDPv{P-;sN7PvxiFYM8s_K5K4Ti+alPP=4 zc>@U-5R5jboU=MfXC(&W3`tAPdYvfjM+`H*Zv`@ajG~g$x)_2&?8V-N1EsMbRxv#{ z;w`TpC2}9O5Gta1S@$qHTbY;=8+|mZk+3fPZIzJa%ktRc7rjMn!m4!#dWU6hCigW~H>K zr*0}?ZFZv_K)ys9#I+k)$6^2pa~5&6e!_$#a_M`(J(nq|y;!LMXDQm~UoEZfHb9ht z?!^()+~{^?ruX+uvEzCT`hkysey3De^zbXiOP@2CUyjvp1poWa;LrI4-RZtN5Rcl+ zWca+ZHe50yxmE4XrvVm#Qs>133i+q&`khgqx{p0n^C;79cRl8IKDC3pnS7?S4!hB> zSNN_yO2r;cA!r(j=Cog}#K{)|lF_u}`T@Y7r{9CI4@UquUh5bd0qHe${21Pl5UgHY zMC2s`9V(=FDWcowgGJhHEB5g)@tbAUcLQ_`UDsvS`8s#itn2Cp?KEvr zUzh)!*3F*+y||2Yq41N3h5~B%Ci+ExX&`dQ`RQYso~d@F+6xPB?R_jyaaIZj@Xty; zK%s8p*mMey(|<3j!VgBdkJs}mfn_}?{ObUu-_&0fP~J0C!Iu3|w70jfa;$PH@lpF9vD~5htIh zkIwQ;cS^aGU3s*k`>p5HR=e6Lh8Q@#RUPpCJL?jvk@kwJ8??X`ScTboH>RoWyK38e zX8&<2qT{N<9_KbnZ^;j%d>uVI?}WzL36;+jz0W##f=YT%d_mgK0#)MfxUf@94J&Q$ zY#KZfzPe5Bz%-9>Pt-;fT}{8C`OxL+J^%NwZ-O_|j1ko?H%9B?)=0(O$4_M)=egKZ zbl>mt86T*|2YXVJwK%Bm!nxDe%(Fu89b6P; z81%gYs1x7G5TW1Aa(x?4g2f*H{nmRZUg(Vq!G13CF4hNIQZyNE84Tm+VrH-Ev_IGR zR((h7Rf5!UX3hB4ODAkTg|rzCfK2ZBX+jOhK5tAu>X&+x-TetN@AES-b(I^JpaL+m zmX5V&oPBO_!f=33^>r(wEzX>owo*y97oGhLg^H1vp^#7Kp4<`*dlhD0eAZN0keV&@ z?dD`^3lT$8XLHhfloP`u>}|Y3bMx`fsemWo_5iE6L0Vz|d*k&m|SR!eM9M57NPPVR8Y`yT2} z+ZoT&ceCHo@F5Y^-!C)97fLN!DGlee|BYO03j9{nT}_PdYWW@Is9xy8koF zk>q>DC;Nww{aQSdvu~#@+3$Vi7KOTItTO zCe5TMV;}d|?EpYYM@cFO%m3*i_%a{AgcViP#Y!i3&+Dn6PhzR|Vtr)6X z*Z9+lDd9s$^ZCv@H>9`3i%+nax9j*ddS_MVFjwAboqhlNhUdzgAI>6yfB)QS;Im~~ zPg#JN4PkO=5vzX={RP!y=7j!w@6K>5F4C%>kRV^@8=yWvewgY7pSv+T>oj=mokZ+- z=h1hb5pMrU$1^H~=C0m8{@(=h_dKi%T9+wo=F9u{cn=!Z@J!~Ewk2laPU6YEl3Tz_ zz7mv+_e&Pf!F8V#L%GlNOQ*5FmY4b|6+JiSalWPJcD^L}RHvWM<)q2v-><#D0*W7r(z?B9oRNR{XJfNw_zV|GV$YWjP zx#DiJvjE*e-H!3`@uMV6Z;-PKUuL|~Q%jro?-@s$sqJTF%5R4+2z=gbc(r}lOVsk1x|3C+Uq*eQ~awF*fW= z9rzCtRzOdNnrR9sUs-`Tp*!U!CgSWpIb|bJa|K&Kii|5THf%dR=CG+l_itIIkd|A~ z<5}x*AnIoQApc{+8K621$d$WiCB`WM8x}BmPGT+j%$Z37Xc=A`QV$or6Ur9VyQH89 zUvc?Y)2aLzV00Qqd&RZa40=%${^r2RX9C-!LMj10W7=SUP$38-bIk%WMM8tY0Z#N% zWqUeTNF<7kJSFq%^fILWSH=Y0@4-Wzx&MelgNDTk56d8z#GdYF^UAMCQp&*31-D$@C>ekcs5yYE-t8f>lv=%ruT$D)@)l98JQ{QIe{Gf>R@GRe*9N< zj4~5XQt$6u@tz9K?v>$#t*mt+c&wg={*%KUObJ|&I%QM+wet3(!H3Rzh&Us6O>R%7 zIi%epsX}i>S_V^Q!Tl%0t*iDfuDP2l%ddYP__M@dcs)HO5}(w`X7Y((dn9EUR`{DB z?xWUSO0U=3?FIP+Y2{rWO9RPub7e4Rod6+UH(cC}L0qDZzhdXNPLwAVBaMYTN!v-n zqIE!F%sJNUNR@^v8Hf;375I5=84u*?QRJMkq?l|@(**k?Z4osGn0Q6 zSh>Hm0dUz^gZf1)J^O|(>&Lg*y$KzVuZSl*@}fr0tvoEdL$T86cR^l}43p~< zL=OV%8hd1B&F_7^Hl=esxB6Jq>ulMrcPerDxqWLO-^?S+x$oMo^sXcwQA@)_ziWQv=x&1xWV6W z)8X1j$7iW$EEmQ5i2Z!&C%W~jR6O zx={V!kq3Kv!M7()o!Tljxc&Y)Zz4NvHa06G=s4-|y{8uiJfx7;>h=J_EJgI4W<{Lr zD-UO%)z4dHDq0bGDdDc7-J4&&qFSpV#3$9cZ++s>Ij%bOGRNo6xKO@)xJ2%|)_Q6S zU(+chGHEHD=YlATJ*awo?Ax>O&a;`HH66^(csv!|G3qG1wjN^eN5hn!rZiZS?jtKC z{Jv}3$2c(^NsprScH`MdX*wNC3CyZ}9lqZke@ z&^6-gFj+e<6~AKP?z-m|vSjb7C30Zalc~t+ZiG}d4jwRn4O39If6(A!vA*bqXQqRQ z9wY6|Gl%~`mbH2M)qvCxPN4W0(GnahF5;|b?io-p60UhUD81J1sw9- z`=zBRms-_q*DN2l89xw z0dw&4ON*l25HDvOvy^xuf`X=%~~4x>9dVI8O{2Sdvt^+qH>{DS`U9F>jafFR)=v6 zhJNEO8Iu&TDDT}A49_K5YBe|E-7H@6vdn+_(*U6N3|_ojtyh1e1_LV+jH-2z?!~_w zK6w1+h+l#0@iQ>&;K4l$B(AK5xy(9Qujp7eg{&RVbeo}mFd-AW-^k7>i?UDrwd{L3 zKd49+Lhn?7jw$|(@rpiqWsW`6Fo6|$UK6QqDYJr!F9S-^ZRAy{;=W`!rWZ|2J?{V! zw<61I^PR=fqG&Qj+zhxa7~J0rM7KyE-$}dCitG@tL3Vj{W=xz%k- zuX*dIOj3wvH1c#l{5x+Gl(VFQ*170bKFmCkg(*r%kTiLciu)Tm=C zPmE$>-k3-B78i?XFB`Jhs;dL(>0ug0JeRGsHt8HnF-dT4%*P*7 zc!B0RK*Ghm=cNQ^3uv-(rd`3ux>YScxNOW7Lq?FNi^*8V(PP9xy83{l+0zcyeDXuo zv7Hc56;L!hPi`l~^;M}?G#xcVQ7q$L&<&CJA2?2h{q1w40dZ%i_9gQf&I^LWn!RpB zcenl*hfzQ|POq@So?~VpnK!SF1RQ}Fx=N9#I*oe|Uk@Q(AMklT_=83zC=i4^f%e+~ z8M9~ZfBR&x`4l+_Zh?%Rr<^^&Bec5gXSj-)@rqE=oQ02EnENZraa#a!w~t5z*%SjLxdjeqr-Y;VPa!SnM5VM;khOFmbb!?QyGT@e zg^Zb@Loh{B9Lo0@j>AJwF^AOj-^J)ys)yW+3P$FKFPV}|5fV_LsuZ0h%Du8w6;+0- z;Y^J9OwK767vRvL(cvTQtZV*&H81-6;7pi++?!*3i%P36?f;okuOP<0Bz3Mvv zqKEm_lXOiRp2Iwm2&O8%7nHe}Qo%f#Z2)nDDYGjivJDVj0SYWZ-E5u#nJO_3N&pon#GjiS){pI9^1SvakZ9fXEq& z+zc6mreJz96}>28D_nJdXPg%Q3DFC9B^V@EN%h*^Yw!i&0!sx8Y`_J82#F3)0=54Z z4Rah2*pg}u9t4yEvBz3$oKHMV}Y}Dc3S+5<+?c*^|s8R`T{?Kzb{mH3dZH zHULMSQo-z-=^Bz zST1b#+Z2aS8*!n*AaEITzYWN68>C0>6Z~R=ZQK5{R9rMOAizZeEJ5Us6Ku%RE4^$9 zkYupHCAzElX*_66tGZd9ViNFIqIksUHEuOU@}9&CV_|PPPj1B{!zq<8NhYk2 zG6gb#wr0>bkxAwm~{zCU^&6$UX^An$+COPf;P8i$w!eZ8%aE z`9kYco*i77jpBC>9bbh54#n_3{^Z?BMa9}}obW7H{{b=_X6oATRD%1|=Xi&`=>1;g z`~v_P5*5)%fd%ut$<)mi;H-wVP{ja|4pPfz{@jpa3ux77fLaHD*xx^LgrY>^sPfH~ zf+;vJ3S?eW)KFLEuMm=U(w<8eUpgfpUg%aMSc7hWiS9xsXi-!YZYEkXADCQ{8r~Fs z$Z;Sv1O%m#6}@@|EU98R6Ktd%@f)BT4Ny8q_!OHDcHk0s1{5nd50~+T%{JXCze*bP zo^EfQllTJZxWO_W6x~hrh0Is#+aCX`lN8(A7swwtdhWRPHqX^VNUK{<;c6DlfsDhx zP(iJSg@DF`nP3mXEWRjwkt^+Jc}UChLlJ{;Hl45&?yy3!$AIJ=xO{zzrYBHdS72^Z z2rPh_LlicejOCKWl6aFv030d|d=zK{=>;!}N4&LM(09K0s-Ha7ycHiV=KIV@q}RXL z(AuDvh@v={be5)ZiL9EiMngFdinQh#xFe*!35YABf@xHAf01LD;8T3DsAfVXz$|a; zgy8`6c!_wzs-j14!l~2njn$)5F>d|?^6yR=(U|JNeZ(H>Ya66!FhdBOugES`G<1oS zlSYlZMT!(*94*B!NqN>#aA-aii(-WR@PK7sQ*3y)rXgUYDHJKHlRsU||E%;`bePWf zFxi3A+W;#uXBe0_CSmDM5{|wI_*hrse%2L6YkHbY4!KPH_;V%#DiCQIij&+3F<|E_ zpq>E*P=6y#idP?LFHXFARIE3&o^e);LNVb4t|s@fAer#RDB)!6!7kyn{)8 z5=VqZoSolb-7k_f?piK_d%S=HU^%?dxk zYLP2Q6P7ls4ROgiR$Bcl-Z}n~BLA zlEs316RgBy=J-WI75*xe5sl+AoXKnWdT^Y|@_PaDEnzB^@n) zld9fddf7bR&jB*9bF^lR#B)wF8N6SZQu-gu^RC!|-sMq?-w$q$A)QQ~{;cFO$h3V! z1NWnbJS_qO)v9`KfK^qY!s8Cu9?NMHuA~K7eDwirEr0);w6I2sUHAiV5y0Eo9iANu z%Xj}+^0Lp$6})#fAh*ez%MI6n{E1Dz5d0_Ht|&ZCqOpWt@@%`Zu6M|q{IZnplpCru zp)M1>*QWW`o90l76|lo`7x7#IN>wDj=pc&rmFy}0k&0;~OqCUUz#Igr<$nm9n8rMe z7TDev1N_*aY-YL|MSh)ocpez~s!eExs=vXrTLI~y`_TRXq)j&A7MSP@Q7&IqOrl88 zsM1Lgr_5wrLbrD9U9yq*6mMI=&dT140Gt2olenfd>*+i^D{bWL5k?J_F4CMhZM;uX z%?x6sCq*pczKsQfb5cR-?(TG+w5KF7m=90Ncct~pkU{dn%*b5o&LNO!&-!7u7CAV< zW9dXMOhP}Vb1OVW-PGH`lNg+iQYFM`WOo&^WJFxz{xN=^&vY*kIoM76y+3jW?1!5) z1F4VYT59JNkeD&)=utz%TW}StbyuU%$9~ct_lqLjC2R1s*adpP({v1y`mo~%pUN`z z)uzXCjh^Kq_fE#z_O(K5HDuOnOfE1^rfMck7QI|}FD}R4LksTgv*ooom}^Au+y!EC zVSejgIFF4fjsstTabVE~)FL6Nv{<$w*0prWlfWNinQtAYnk$H?d)2up=`%oYZgWXY zMeV&XlO>5d-ZYZbR`&9>r zV`s=Rj{P0WqevKvcYEN>$33R%u2>~BwgRCm3+mARSZpD(T_QUhNzJ5Rz5WOh(GIKQ zEw)Q2-BZcvg4u$!@7dK{O~3S&DwG2ktgsmx?OcYWVH-WNh^oMcQ}hO%IDjq

    ---- - -Page Title: Blocks - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/ -- Summary: Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. - -# Blocks - -## Introduction - -In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the network. By understanding these concepts, developers can better grasp how blockchains maintain security, consistency, and performance within the Polkadot ecosystem. - -## What is a Block? - -In the Polkadot SDK, a block is a fundamental unit that encapsulates both the header and an array of transactions. The block header includes critical metadata to ensure the integrity and sequence of the blockchain. Here's a breakdown of its components: - -- **Block height**: Indicates the number of blocks created in the chain so far. -- **Parent hash**: The hash of the previous block, providing a link to maintain the blockchain's immutability. -- **Transaction root**: Cryptographic digest summarizing all transactions in the block. -- **State root**: A cryptographic digest representing the post-execution state. -- **Digest**: Additional information that can be attached to a block, such as consensus-related messages. - -Each transaction is part of a series that is executed according to the runtime's rules. The transaction root is a cryptographic digest of this series, which prevents alterations and enables succinct verification by light clients. This verification process allows light clients to confirm whether a transaction exists in a block with only the block header, avoiding downloading the entire block. - -## Block Production - -When an authoring node is authorized to create a new block, it selects transactions from the transaction queue based on priority. This step, known as block production, relies heavily on the executive module to manage the initialization and finalization of blocks. The process is summarized as follows: - -### Initialize Block - -The block initialization process begins with a series of function calls that prepare the block for transaction execution: - -1. **Call `on_initialize`**: The executive module calls the [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hook from the system pallet and other runtime pallets to prepare for the block's transactions. -2. **Coordinate runtime calls**: Coordinates function calls in the order defined by the transaction queue. -3. **Verify information**: Once [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} functions are executed, the executive module checks the parent hash in the block header and the trie root to verify information is consistent. - -### Finalize Block - -Once transactions are processed, the block must be finalized before being broadcast to the network. The finalization steps are as follows: - -1. **Call `on_finalize`**: The executive module calls the [`on_finalize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_finalize){target=\_blank} hooks in each pallet to ensure any remaining state updates or checks are completed before the block is sealed and published. -2. **Verify information**: The block's digest and storage root in the header are checked against the initialized block to ensure consistency. -3. **Call `on_idle`**: The [`on_idle`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_idle){target=\_blank} hook is triggered to process any remaining tasks using the leftover weight from the block. - -## Block Authoring and Import - -Once the block is finalized, it is gossiped to other nodes in the network. Nodes follow this procedure: - -1. **Receive transactions**: The authoring node collects transactions from the network. -2. **Validate**: Transactions are checked for validity. -3. **Queue**: Valid transactions are placed in the transaction pool for execution. -4. **Execute**: State changes are made as the transactions are executed. -5. **Publish**: The finalized block is broadcast to the network. - -### Block Import Queue - -After a block is published, other nodes on the network can import it into their chain state. The block import queue is part of the outer node in every Polkadot SDK-based node and ensures incoming blocks are valid before adding them to the node's state. - -In most cases, you don't need to know details about how transactions are gossiped or how other nodes on the network import blocks. The following traits are relevant, however, if you plan to write any custom consensus logic or want a deeper dive into the block import queue: - -- **[`ImportQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.ImportQueue.html){target=\_blank}**: The trait that defines the block import queue. -- **[`Link`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Link.html){target=\_blank}**: The trait that defines the link between the block import queue and the network. -- **[`BasicQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/struct.BasicQueue.html){target=\_blank}**: A basic implementation of the block import queue. -- **[`Verifier`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Verifier.html){target=\_blank}**: The trait that defines the block verifier. -- **[`BlockImport`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/block_import/trait.BlockImport.html){target=\_blank}**: The trait that defines the block import process. - -These traits govern how blocks are validated and imported across the network, ensuring consistency and security. - -## Additional Resources - -To learn more about the block structure in the Polkadot SDK runtime, see the [`Block` reference](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.Block.html){target=\_blank} entry in the Rust Docs. - - ---- - -Page Title: Chain Data - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/chain-data/ -- Summary: Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. - -# Chain Data - -## Introduction - -Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you can ensure seamless communication between your applications and the blockchain. - -## Application Development - -You might not be directly involved in building frontend applications as a blockchain developer. However, most applications that run on a blockchain require some form of frontend or user-facing client to enable users or other programs to access and modify the data that the blockchain stores. For example, you might develop a browser-based, mobile, or desktop application that allows users to submit transactions, post articles, view their assets, or track previous activity. The backend for that application is configured in the runtime logic for your blockchain, but the frontend client makes the runtime features accessible to your users. - -For your custom chain to be useful to others, you'll need to provide a client application that allows users to view, interact with, or update information that the blockchain keeps track of. In this article, you'll learn how to expose information about your runtime so that client applications can use it, see examples of the information exposed, and explore tools and libraries that use it. - -## Understand Metadata - -Polkadot SDK-based blockchain networks are designed to expose their runtime information, allowing developers to learn granular details regarding pallets, RPC calls, and runtime APIs. The metadata also exposes their related documentation. The chain's metadata is [SCALE-encoded](/reference/parachains/data-encoding/){target=\_blank}, allowing for the development of browser-based, mobile, or desktop applications to support the chain's runtime upgrades seamlessly. It is also possible to develop applications compatible with multiple Polkadot SDK-based chains simultaneously. - -## Expose Runtime Information as Metadata - -To interact with a node or the state of the blockchain, you need to know how to connect to the chain and access the exposed runtime features. This interaction involves a Remote Procedure Call (RPC) through a node endpoint address, commonly through a secure web socket connection. - -An application developer typically needs to know the contents of the runtime logic, including the following details: - -- Version of the runtime the application is connecting to. -- Supported APIs. -- Implemented pallets. -- Defined functions and corresponding type signatures. -- Defined custom types. -- Exposed parameters users can set. - -As the Polkadot SDK is modular and provides a composable framework for building blockchains, there are limitless opportunities to customize the schema of properties. Each runtime can be configured with its properties, including function calls and types, which can be changed over time with runtime upgrades. - -The Polkadot SDK enables you to generate the runtime metadata schema to capture information unique to a runtime. The metadata for a runtime describes the pallets in use and types defined for a specific runtime version. The metadata includes information about each pallet's storage items, functions, events, errors, and constants. The metadata also provides type definitions for any custom types included in the runtime. - -Metadata provides a complete inventory of a chain's runtime. It is key to enabling client applications to interact with the node, parse responses, and correctly format message payloads sent back to that chain. - -## Generate Metadata - -To efficiently use the blockchain's networking resources and minimize the data transmitted over the network, the metadata schema is encoded using the [Parity SCALE Codec](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank}. This encoding is done automatically through the [`scale-info`](https://docs.rs/scale-info/latest/scale_info/){target=\_blank}crate. - -At a high level, generating the metadata involves the following steps: - -1. The pallets in the runtime logic expose callable functions, types, parameters, and documentation that need to be encoded in the metadata. -2. The `scale-info` crate collects type information for the pallets in the runtime, builds a registry of the pallets that exist in a particular runtime, and the relevant types for each pallet in the registry. The type information is detailed enough to enable encoding and decoding for every type. -3. The [`frame-metadata`](https://github.com/paritytech/frame-metadata){target=\_blank} crate describes the structure of the runtime based on the registry provided by the `scale-info` crate. -4. Nodes provide the RPC method `state_getMetadata` to return a complete description of all the types in the current runtime as a hex-encoded vector of SCALE-encoded bytes. - -## Retrieve Runtime Metadata - -The type information provided by the metadata enables applications to communicate with nodes using different runtime versions and across chains that expose different calls, events, types, and storage items. The metadata also allows libraries to generate a substantial portion of the code needed to communicate with a given node, enabling libraries like [`subxt`](https://github.com/paritytech/subxt){target=\_blank} to generate frontend interfaces that are specific to a target chain. - -### Use Polkadot.js - -Visit the [Polkadot.js Portal](https://polkadot.js.org/apps/#/rpc){target=\_blank} and select the **Developer** dropdown in the top banner. Select **RPC Calls** to make the call to request metadata. Follow these steps to make the RPC call: - -1. Select **state** as the endpoint to call. -2. Select **`getMetadata(at)`** as the method to call. -3. Click **Submit RPC call** to submit the call and return the metadata in JSON format. - -### Use Curl - -You can fetch the metadata for the network by calling the node's RPC endpoint. This request returns the metadata in bytes rather than human-readable JSON: - -```sh -curl -H "Content-Type: application/json" \ --d '{"id":1, "jsonrpc":"2.0", "method": "state_getMetadata"}' \ -https://rpc.polkadot.io - -``` - -### Use Subxt - -[`subxt`](https://github.com/paritytech/subxt){target=\_blank} may also be used to fetch the metadata of any data in a human-readable JSON format: - -```sh -subxt metadata --url wss://rpc.polkadot.io --format json > spec.json -``` - -Another option is to use the [`subxt` explorer web UI](https://paritytech.github.io/subxt-explorer/#/){target=\_blank}. - -## Client Applications and Metadata - -The metadata exposes the expected way to decode each type, meaning applications can send, retrieve, and process application information without manual encoding and decoding. Client applications must use the [SCALE codec library](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank} to encode and decode RPC payloads to use the metadata. Client applications use the metadata to interact with the node, parse responses, and format message payloads sent to the node. - -## Metadata Format - -Although the SCALE-encoded bytes can be decoded using the `frame-metadata` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} libraries, there are other tools, such as `subxt` and the Polkadot-JS API, that can convert the raw data to human-readable JSON format. - -The types and type definitions included in the metadata returned by the `state_getMetadata` RPC call depend on the runtime's metadata version. - -In general, the metadata includes the following information: - -- A constant identifying the file as containing metadata. -- The version of the metadata format used in the runtime. -- Type definitions for all types used in the runtime and generated by the `scale-info` crate. -- Pallet information for the pallets included in the runtime in the order that they are defined in the `construct_runtime` macro. - -!!!tip - Depending on the frontend library used (such as the [Polkadot API](https://papi.how/){target=\_blank}), they may format the metadata differently than the raw format shown. - -The following example illustrates a condensed and annotated section of metadata decoded and converted to JSON: - -```json -[ - 1635018093, - { - "V14": { - "types": { - "types": [{}] - }, - "pallets": [{}], - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [{}] - }, - "ty": 141 - } - } -] - -``` - -The constant `1635018093` is a magic number that identifies the file as a metadata file. The rest of the metadata is divided into the `types`, `pallets`, and `extrinsic` sections: - -- The `types` section contains an index of the types and information about each type's type signature. -- The `pallets` section contains information about each pallet in the runtime. -- The `extrinsic` section describes the type identifier and transaction format version that the runtime uses. - -Different extrinsic versions can have varying formats, especially when considering [signed transactions](/reference/parachains/blocks-transactions-fees/transactions/#signed-transactions){target=\_blank}. - -### Pallets - -The following is a condensed and annotated example of metadata for a single element in the `pallets` array (the [`sudo`](https://paritytech.github.io/polkadot-sdk/master/pallet_sudo/index.html){target=\_blank} pallet): - -```json -{ - "name": "Sudo", - "storage": { - "prefix": "Sudo", - "entries": [ - { - "name": "Key", - "modifier": "Optional", - "ty": { - "Plain": 0 - }, - "default": [0], - "docs": ["The `AccountId` of the sudo key."] - } - ] - }, - "calls": { - "ty": 117 - }, - "event": { - "ty": 42 - }, - "constants": [], - "error": { - "ty": 124 - }, - "index": 8 -} - -``` - -Every element metadata contains the name of the pallet it represents and information about its storage, calls, events, and errors. You can look up details about the definition of the calls, events, and errors by viewing the type index identifier. The type index identifier is the `u32` integer used to access the type information for that item. For example, the type index identifier for calls in the Sudo pallet is 117. If you view information for that type identifier in the `types` section of the metadata, it provides information about the available calls, including the documentation for each call. - -For example, the following is a condensed excerpt of the calls for the Sudo pallet: - -```json -{ - "id": 117, - "type": { - "path": ["pallet_sudo", "pallet", "Call"], - "params": [ - { - "name": "T", - "type": null - } - ], - "def": { - "variant": { - "variants": [ - { - "name": "sudo", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 0, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "sudo_unchecked_weight", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - }, - { - "name": "weight", - "type": 8, - "typeName": "Weight" - } - ], - "index": 1, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "set_key", - "fields": [ - { - "name": "new", - "type": 103, - "typeName": "AccountIdLookupOf" - } - ], - "index": 2, - "docs": [ - "Authenticates current sudo key, sets the given AccountId (`new`) as the new sudo" - ] - }, - { - "name": "sudo_as", - "fields": [ - { - "name": "who", - "type": 103, - "typeName": "AccountIdLookupOf" - }, - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 3, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Signed` origin from a given account" - ] - } - ] - } - } - } -} - -``` - -For each field, you can access type information and metadata for the following: - -- **Storage metadata**: Provides the information required to enable applications to get information for specific storage items. -- **Call metadata**: Includes information about the runtime calls defined by the `#[pallet]` macro including call names, arguments and documentation. -- **Event metadata**: Provides the metadata generated by the `#[pallet::event]` macro, including the name, arguments, and documentation for each pallet event. -- **Constants metadata**: Provides metadata generated by the `#[pallet::constant]` macro, including the name, type, and hex-encoded value of the constant. -- **Error metadata**: Provides metadata generated by the `#[pallet::error]` macro, including the name and documentation for each pallet error. - -!!!tip - Type identifiers change from time to time, so you should avoid relying on specific type identifiers in your applications. - -### Extrinsic - -The runtime generates extrinsic metadata and provides useful information about transaction format. When decoded, the metadata contains the transaction version and the list of signed extensions. - -For example: - -```json -{ - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [ - { - "identifier": "CheckNonZeroSender", - "ty": 132, - "additional_signed": 41 - }, - { - "identifier": "CheckSpecVersion", - "ty": 133, - "additional_signed": 4 - }, - { - "identifier": "CheckTxVersion", - "ty": 134, - "additional_signed": 4 - }, - { - "identifier": "CheckGenesis", - "ty": 135, - "additional_signed": 11 - }, - { - "identifier": "CheckMortality", - "ty": 136, - "additional_signed": 11 - }, - { - "identifier": "CheckNonce", - "ty": 138, - "additional_signed": 41 - }, - { - "identifier": "CheckWeight", - "ty": 139, - "additional_signed": 41 - }, - { - "identifier": "ChargeTransactionPayment", - "ty": 140, - "additional_signed": 41 - } - ] - }, - "ty": 141 -} - -``` - -The type system is [composite](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank}, meaning each type identifier contains a reference to a specific type or to another type identifier that provides information about the associated primitive types. - -For example, you can encode the `BitVec` type, but to decode it properly, you must know the types used for the `Order` and `Store` types. To find type information for `Order` and `Store`, you can use the path in the decoded JSON to locate their type identifiers. - -## Included RPC APIs - -A standard node comes with the following APIs to interact with a node: - -- **[`AuthorApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/author/trait.AuthorApiServer.html){target=\_blank}**: Make calls into a full node, including authoring extrinsics and verifying session keys. -- **[`ChainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/chain/trait.ChainApiServer.html){target=\_blank}**: Retrieve block header and finality information. -- **[`OffchainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/offchain/trait.OffchainApiServer.html){target=\_blank}**: Make RPC calls for off-chain workers. -- **[`StateApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/state/trait.StateApiServer.html){target=\_blank}**: Query information about on-chain state such as runtime version, storage items, and proofs. -- **[`SystemApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/system/trait.SystemApiServer.html){target=\_blank}**: Retrieve information about network state, such as connected peers and node roles. - -## Additional Resources - -The following tools can help you locate and decode metadata: - -- [Subxt Explorer](https://paritytech.github.io/subxt-explorer/#/){target=\_blank} -- [Metadata Portal 🌗](https://github.com/paritytech/metadata-portal){target=\_blank} -- [De[code] Sub[strate]](https://github.com/paritytech/desub){target=\_blank} - - --- Page Title: Contract Deployment @@ -1021,7480 +587,3339 @@ Both backends support contract deployment effectively, with REVM offering drop-i --- -Page Title: Convert Assets on Asset Hub +Page Title: Deploy an ERC-20 to Polkadot Hub -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-convert-assets.md -- Canonical (HTML): https://docs.polkadot.com/chain-interactions/token-operations/convert-assets/ -- Summary: A guide detailing the step-by-step process of converting assets on Asset Hub, helping users efficiently navigate asset management on the platform. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/ +- Summary: Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Hardhat. -# Convert Assets on Asset Hub +# Deploy an ERC-20 to Polkadot Hub ## Introduction -Asset Conversion is an Automated Market Maker (AMM) utilizing [Uniswap V2](https://github.com/Uniswap/v2-core){target=\_blank} logic and implemented as a pallet on Polkadot's Asset Hub. - -This guide will provide detailed information about the key functionalities offered by the [Asset Conversion](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/asset-conversion){target=\_blank} pallet on Asset Hub, including: +[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. -- Creating a liquidity pool. -- Adding liquidity to a pool. -- Swapping assets. -- Withdrawing liquidity from a pool. +This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Hardhat](https://hardhat.org/){target=\_blank}, an Ethereum development environment. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. ## Prerequisites -Before converting assets on Asset Hub, you must ensure you have: - -- Access to the [Polkadot.js Apps](https://polkadot.js.org/apps){target=\_blank} interface and a connection with the intended blockchain. -- A funded wallet containing the assets you wish to convert and enough available funds to cover the transaction fees. -- An asset registered on Asset Hub that you want to convert. If you haven't created an asset on Asset Hub yet, refer to the [Register a Local Asset](/chain-interactions/token-operations/register-local-asset/){target=\_blank} or [Register a Foreign Asset](/chain-interactions/token-operations/register-foreign-asset/){target=\_blank} documentation to create an asset. +Before starting, make sure you have: -## Create a Liquidity Pool +- Basic understanding of Solidity programming and fungible tokens. +- Node.js v22.13.1 or later. +- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -If an asset on Asset Hub does not have an existing liquidity pool, the first step is to create one. +## Set Up Your Project -The asset conversion pallet provides the `createPool` extrinsic to create a new liquidity pool, creating an empty liquidity pool and a new `LP token` asset. +This tutorial uses a [Hardhat ERC-20 template](https://github.com/polkadot-developers/revm-hardhat-examples/tree/master/erc20-hardhat){target=\_blank} that contains all the necessary files. To get started, take the following steps: -!!! tip - A testing token with the asset ID `1112` and the name `PPM` was created for this example. +1. Clone the GitHub repository locally: -As stated in the [Test Environment Setup](#test-environment-setup) section, this tutorial is based on the assumption that you have an instance of Polkadot Asset Hub running locally. Therefore, the demo liquidity pool will be created between DOT and PPM tokens. However, the same steps can be applied to any other asset on Asset Hub. + ```bash + git clone https://github.com/polkadot-developers/revm-hardhat-examples/ + cd revm-hardhat-examples/erc20-hardhat + ``` -From the Asset Hub perspective, the Multilocation that identifies the PPM token is the following: +2. Install the dependencies: -```javascript -{ - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } -} -``` + ```bash + npm i + ``` -The `PalletInstance` value of `50` represents the Assets pallet on Asset Hub. The `GeneralIndex` value of `1112` is the PPM asset's asset ID. +This will fetch all the necessary packages to help you deploy an ERC-20 with Hardhat to Polkadot. -To create the liquidity pool, you can follow these steps: +## Configure Hardhat -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: +Once you've [setup your project](#set-up-your-project), you can configure the `hardhat.config.ts` to your needs. This tutorial has the file prepared to deploy to the Polkadot TestNet. - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. +To store and use private keys or network URLs, you can use Hardhat's configuration variables. This can be set via tasks in the **vars** scope. For example, to store the private key to deploy to the Polkadot TestNet, run the following command: - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) +```bash +npx hardhat vars set TESTNET_PRIVATE_KEY +``` -2. Select extrinsic to create the pool: +The command will initiate a wizard in which you'll have to enter the value to be stored: - 1. Select the **`AssetConversion`** pallet. - 2. Choose the **`createPool`** extrinsic from the list of available extrinsics. +
    + npx hardhat vars set TESTNET_PRIVATE_KEY + ✔ Enter value: · ••••••••• + The configuration variable has been stored in /Users/albertoviera/Library/Preferences/hardhat-nodejs/vars.json +
    - ![Create Pool Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-02.webp) +??? warning "Key Encryption" + This solution just prevents variables to be included in the code repository. You should find a solution that encrypts private keys and access them securely. -3. Fill in the required fields: +You can now use the account related to this private key by importing it into the Hardhat configuration file: - 1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents. +```ts title="hardhat.config.ts" hl_lines="1 17" - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` +const config: HardhatUserConfig = { + solidity: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + networks: { + polkadotTestnet: { + url: vars.get("TESTNET_URL", "http://127.0.0.1:8545"), + accounts: vars.has("TESTNET_PRIVATE_KEY") ? [vars.get("TESTNET_PRIVATE_KEY")] : [], + }, + }, + mocha: { + timeout: 40000, + }, +}; - 2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies. +export default config; +``` - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` +## Compile your Contract - 3. Click on **Submit Transaction** to create the liquidity pool. +Once you've configured Hardhat, you can compile the contract. - ![Create Pool Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-03.webp) +In this tutorial, a simple ERC-20 is provided. Therefore, to compile the contract you can run the following command: -Signing and submitting the transaction triggers the creation of the liquidity pool. To verify the new pool's creation, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`PoolCreated`** event was emitted. +```bash +npx hardhat compile +``` -![Pool Created Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-04.webp) +If everything compiles successfully, you should see the following output: -As the preceding image shows, the **`lpToken`** ID created for this pool is 19. This ID is essential to identify the liquidity pool and associated LP tokens. +
    + npx hardhat compile + Generating typings for: 23 artifacts in dir: typechain-types for target: ethers-v6 + Successfully generated 62 typings! + Compiled 21 Solidity files successfully (evm target: paris). +
    -## Add Liquidity to a Pool +## Test your Contract -The `addLiquidity` extrinsic allows users to provide liquidity to a pool of two assets. Users specify their preferred amounts for both assets and minimum acceptable quantities. The function determines the best asset contribution, which may vary from the amounts desired but won't fall below the specified minimums. Providers receive liquidity tokens representing their pool portion in return for their contribution. +Hardhat has a native feature to test contracts. You can run tests against the local Hardhat development node, but it could have some technical differences to Polkadot. Therefore, in this tutorial, you'll be testing against the Polkadot TestNet -To add liquidity to a pool, follow these steps: +This example has a predefined test file located in [`test/Token.test.js`](https://github.com/polkadot-developers/revm-hardhat-examples/blob/master/erc20-hardhat/test/MyToken.test.ts){target=\_blank}, that runs the following tests: -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: +1. The token was deployed by verifying its **name** and **symbol**. +2. The token has the right owner configured. +3. The token has an initial supply of zero. +4. The owner can mint tokens. +5. The total supply is increased after a mint. +6. Perform multiple mints to different addresses and checks the balance of each address and the new total supply. - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. +To run the test, you can execute the following command: - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) +```bash +npx hardhat test --network polkadotTestnet +``` -2. Select extrinsic to add liqudity: +If tests are successful, you should see the following logs: - 1. Select the **`assetConversion`** pallet. - 2. Choose the **`addLiquidity`** extrinsic from the list of available extrinsics. +
    + npx hardhat test --network polkadotTestnet + +   MyToken +     Deployment +       ✔ Should have correct name and symbol +       ✔ Should set the right owner +       ✔ Should have zero initial supply +     Minting +       ✔ Should allow owner to mint tokens +       ✔ Should increase total supply on mint +     Multiple mints +       ✔ Should correctly track balance after multiple mints + +   6 passing (369ms) +
    - ![Add Liquidity Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-05.webp) +## Deploy your Contract -3. Fill in the required fields: +With the Hardhat configuration file ready, the private key stored as a variable under **vars**, and the contract compiled, you can proceed to deploy the contract to a given network. In this tutorial, you are deploying it to the Polkadot TestNet. - 1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents. +To deploy the contract, run the following command: - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` - - 2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies. - - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` - - 3. **`amount1Desired`**: The amount of the first asset that will be contributed to the pool. - 4. **`amount2Desired`**: The quantity of the second asset intended for pool contribution. - 5. **`amount1Min`**: The minimum amount of the first asset that will be contributed. - 6. **`amount2Min`**: The lowest acceptable quantity of the second asset for contribution. - 7. **`mintTo`**: The account to which the liquidity tokens will be minted. - 8. Click on **Submit Transaction** to add liquidity to the pool. - - ![Add Liquidity Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-06.webp) - - !!! warning - Ensure that the appropriate amount of tokens provided has been minted previously and is available in your account before adding liquidity to the pool. - - In this case, the liquidity provided to the pool is between DOT tokens and PPM tokens with the asset ID 1112 on Polkadot Asset Hub. The intention is to provide liquidity for 1 DOT token (`u128` value of 1000000000000 as it has 10 decimals) and 1 PPM token (`u128` value of 1000000000000 as it also has 10 decimals). - -Signing and submitting the transaction adds liquidity to the pool. To verify the liquidity addition, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`LiquidityAdded`** event was emitted. - -![Liquidity Added Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-07.webp) - -## Swap Assets +```bash +npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet +``` -### Swap from an Exact Amount of Tokens +You'll need to confirm the target network (by chain ID): -The asset conversion pallet enables users to exchange a specific quantity of one asset for another in a designated liquidity pool by swapping them for an exact amount of tokens. It guarantees the user will receive at least a predetermined minimum amount of the second asset. This function increases trading predictability and allows users to conduct asset exchanges with confidence that they are assured a minimum return. +
    + npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet + ✔ Confirm deploy to network polkadotTestnet (420420420)? … yes +   + Hardhat Ignition 🚀 +   + Deploying [ TokenModule ] +   + Batch #1 + Executed TokenModule#MyToken +   + Batch #2 + Executed TokenModule#MyToken.mint +   + [ TokenModule ] successfully deployed 🚀 +   + Deployed Addresses +   + TokenModule#MyToken - 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3 +
    -To swap assets for an exact amount of tokens, follow these steps: +And that is it! You've successfully deployed an ERC-20 token contract to the Polkadot TestNet using Hardhat. -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: +## Where to Go Next - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. +
    - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) +- Guide __Deploy an NFT with Remix__ -2. Select extrinsic to swap assets: + --- - 1. Select the **`AssetConversion`** pallet. - 2. Choose the **`swapExactTokensForTokens`** extrinsic from the list of available extrinsics. + Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. - ![Swap From Exact Tokens Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-08.webp) + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) -3. Fill in the required fields: +
    - 1. **`path: Vec`**: An array of Multilocations representing the path of the swap. The first and last elements of the array are the input and output assets, respectively. In this case, the path consists of two elements: - - **`0: StagingXcmV3MultiLocation`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents. +--- - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` +Page Title: Deploy an ERC-20 to Polkadot Hub - - **`1: StagingXcmV3MultiLocation`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/ +- Summary: Deploy an ERC-20 token contract on Polkadot Hub. This guide covers contract creation, compilation, deployment, and interaction via the Remix IDE. - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` +# Deploy an ERC-20 to Polkadot Hub - 2. **`amountOut`**: The exact amount of the second asset that the user wants to receive. - 3. **`amountInMax`**: The maximum amount of the first asset that the user is willing to swap. - 4. **`sendTo`**: The account to which the swapped assets will be sent. - 5. **`keepAlive`**: A boolean value that determines whether the pool should be kept alive after the swap. - 6. Click on **Submit Transaction** to swap assets for an exact amount of tokens. +## Introduction - ![Swap For Exact Tokens Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-09.webp) +[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. - !!! warning - Ensure that the appropriate amount of tokens provided has been minted previously and is available in your account before adding liquidity to the pool. +This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Remix IDE](https://remix.ethereum.org/){target=\_blank}, a web-based development tool. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. - In this case, the intention is to swap 0.01 DOT token (u128 value of 100000000000 as it has 10 decimals) for 0.04 PPM token (u128 value of 400000000000 as it also has 10 decimals). +## Prerequisites -Signing and submitting the transaction will execute the swap. To verify execution, check the **Explorer** section on the Polkadot.js Apps interface and make sure that the **`SwapExecuted`** event was emitted. +Before starting, make sure you have: -![Swap From Exact Tokens Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-10.webp) +- Basic understanding of Solidity programming and fungible tokens. +- An EVM-compatible wallet [connected to Polkadot Hub](/smart-contracts/integrations/wallets){target=\_blank}. This example utilizes [MetaMask](https://metamask.io/){target=\_blank}. +- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -### Swap to an Exact Amount of Tokens +## Create Your Contract -Conversely, the Asset Conversion pallet comes with a function that allows users to trade a variable amount of one asset to acquire a precise quantity of another. It ensures that users stay within a set maximum of the initial asset to obtain the desired amount of the second asset. This provides a method to control transaction costs while achieving the intended result. +To create the ERC-20 contract, you can follow the steps below: -To swap assets for an exact amount of tokens, follow these steps: +1. Navigate to the [Polkadot Remix IDE](https://remix.polkadot.io){target=\_blank}. +2. Click in the **Create new file** button under the **contracts** folder, and name your contract as `MyToken.sol`. -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: + ![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-1.webp) - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. +3. Now, paste the following ERC-20 contract code into the editor: - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) + ```solidity title="MyToken.sol" + // SPDX-License-Identifier: MIT + // Compatible with OpenZeppelin Contracts ^5.4.0 + pragma solidity ^0.8.27; -2. Select extrinsic to swap tokens: + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; + import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; - 1. Select the **`AssetConversion`** pallet. - 2. Choose the **`swapTokensForExactTokens`** extrinsic from the list of available extrinsics. + contract MyToken is ERC20, Ownable, ERC20Permit { + constructor(address initialOwner) + ERC20("MyToken", "MTK") + Ownable(initialOwner) + ERC20Permit("MyToken") + {} - ![Swap Tokens For Exact Tokens Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-11.webp) + function mint(address to, uint256 amount) public onlyOwner { + _mint(to, amount); + } + } + ``` -3. Fill in the required fields: + The key components of the code above are: - 1. **`path: Vec`**: An array of Multilocations representing the path of the swap. The first and last elements of the array are the input and output assets, respectively. In this case, the path consists of two elements: - - **`0: StagingXcmV3MultiLocation`**: The Multilocation of the first asset in the pool. In this case, it is the PPM token, which the following Multilocation represents. + - Contract imports: - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` + - **[`ERC20.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/ERC20.sol){target=\_blank}**: The base contract for fungible tokens, implementing core functionality like transfers, approvals, and balance tracking. + - **[`ERC20Permit.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/extensions/ERC20Permit.sol){target=\_blank}**: [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612){target=\_blank} extension for ERC-20 that adds the [permit function](https://docs.openzeppelin.com/contracts/5.x/api/token/erc20#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-){target=\_blank}, allowing approvals via off-chain signatures (no on-chain tx from the holder). Manages nonces and EIP-712 domain separator and updates allowances when a valid signature is presented. + - **[`Ownable.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/access/Ownable.sol){target=\_blank}**: Provides basic authorization control, ensuring only the contract owner can mint new tokens. + + - Constructor parameters: - - **`1: StagingXcmV3MultiLocation`**: The second asset's Multilocation within the pool. This refers to the DOT token, which the following Multilocation identifies. + - **`initialOwner`**: Sets the address that will have administrative rights over the contract. + - **`"MyToken"`**: The full name of your token. + - **`"MTK"`**: The symbol representing your token in wallets and exchanges. - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` + - Key functions: - 2. **`amountOut`**: The exact amount of the second asset that the user wants to receive. - 3. **`amountInMax`**: The maximum amount of the first asset that the user is willing to swap. - 4. **`sendTo`**: The account to which the swapped assets will be sent. - 5. **`keepAlive`**: A boolean value that determines whether the pool should be kept alive after the swap. - 6. Click on **Submit Transaction** to swap assets for an exact amount of tokens. + - **`mint(address to, uint256 amount)`**: Allows the contract owner to create new tokens for any address. The amount should include 18 decimals (e.g., 1 token = 1000000000000000000). + - Inherited [Standard ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/){target=\_blank} functions: + - **`transfer(address recipient, uint256 amount)`**: Sends a specified amount of tokens to another address. + - **`approve(address spender, uint256 amount)`**: Grants permission for another address to spend a specific number of tokens on behalf of the token owner. + - **`transferFrom(address sender, address recipient, uint256 amount)`**: Transfers tokens from one address to another, if previously approved. + - **`balanceOf(address account)`**: Returns the token balance of a specific address. + - **`allowance(address owner, address spender)`**: Checks how many tokens an address is allowed to spend on behalf of another address. - ![Swap Tokens For Exact Tokens Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-12.webp) + !!! tip + Use the [OpenZeppelin Contracts Wizard](https://wizard.openzeppelin.com/){target=\_blank} to generate customized smart contracts quickly. Simply configure your contract, copy the generated code, and paste it into the Remix IDE for deployment. Below is an example of an ERC-20 token contract created with it: - !!! warning - Before swapping assets, ensure that the tokens provided have been minted previously and are available in your account. + ![Screenshot of the OpenZeppelin Contracts Wizard showing an ERC-20 contract configuration.](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-2.webp) + - In this case, the intention is to swap 0.01 DOT token (`u128` value of 100000000000 as it has ten decimals) for 0.04 PPM token (`u128` value of 400000000000 as it also has ten decimals). +## Compile -Signing and submitting the transaction will execute the swap. To verify execution, check the **Explorer** section on the Polkadot.js Apps interface and make sure that the **`SwapExecuted`** event was emitted. +The compilation transforms your Solidity source code into bytecode that can be deployed on the blockchain. During this process, the compiler checks your contract for syntax errors, ensures type safety, and generates the machine-readable instructions needed for blockchain execution. -![Swap Tokens For Exact Tokens Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-13.webp) +To compile your contract, ensure you have it opened in the Remix IDE Editor, and follow the instructions below: -## Withdraw Liquidity from a Pool +1. Select the **Solidity Compiler** plugin from the left panel. +2. Click the **Compile MyToken.sol** button. +3. If the compilation succeeded, you'll see a green checkmark indicating success in the **Solidity Compiler** icon. -The Asset Conversion pallet provides the `removeLiquidity` extrinsic to remove liquidity from a pool. This function allows users to withdraw the liquidity they offered from a pool, returning the original assets. When calling this function, users specify the number of liquidity tokens (representing their share in the pool) they wish to burn. They also set minimum acceptable amounts for the assets they expect to receive back. This mechanism ensures that users can control the minimum value they receive, protecting against unfavorable price movements during the withdrawal process. +![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-3.gif) -To withdraw liquidity from a pool, follow these steps: +## Deploy -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: +Deployment is the process of publishing your compiled smart contract to the blockchain, making it permanently available for interaction. During deployment, you'll create a new instance of your contract on the blockchain, which involves: - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. +1. Select the **Deploy & Run Transactions** plugin from the left panel. +2. Configure the deployment settings: + 1. From the **ENVIRONMENT** dropdown, select **Injected Provider - MetaMask** (check the [Deploying Contracts](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} section of the Remix IDE guide for more details). + 2. (Optional) From the **ACCOUNT** dropdown, select the acccount you want to use for the deploy. - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) +3. Configure the contract parameters: + 1. Enter the address that will own the deployed token contract. + 2. Click the **Deploy** button to initiate the deployment. -2. Select extrinsic to withdraw liqudity from a pool: +4. **MetaMask will pop up**: Review the transaction details. Click **Confirm** to deploy your contract. +5. If the deployment process succeeded, you will see the transaction details in the terminal, including the contract address and deployment transaction hash. - 1. Select the **`AssetConversion`** pallet. - 2. Choose the **`removeLiquidity`** extrinsic from the list of available extrinsics. +![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-4.gif) - ![Remove Liquidity Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-14.webp) +## Interact with Your Contract -3. Fill in the required fields: +Once deployed, you can interact with your contract through Remix. Find your contract under **Deployed/Unpinned Contracts**, and click it to expand the available methods. In this example, you'll mint some tokens to a given address: - 1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents. +1. Expand the **mint** function: + 1. Enter the recipient address and the amount (remember to add 18 zeros for 1 whole token). + 2. Click **transact**. - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` +2. Click **Approve** to confirm the transaction in the MetaMask popup. - 2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies. +3. If the transaction succeeds, you will see a green check mark in the terminal. - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` +4. You can also call the **balanceOf** function by passing the address of the **mint** call to confirm the new balance. - 3. **`lpTokenBurn`**: The number of liquidity tokens to burn. - 4. **`amount1MinReceived`**: The minimum amount of the first asset that the user expects to receive. - 5. **`amount2MinReceived`**: The minimum quantity of the second asset the user expects to receive. - 6. **`withdrawTo`**: The account to which the withdrawn assets will be sent. - 7. Click on **Submit Transaction** to withdraw liquidity from the pool. +![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-5.gif) - ![Remove Liquidity Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-15.webp) - !!! warning - Ensure that the tokens provided have been minted previously and are available in your account before withdrawing liquidity from the pool. +Other standard functions you can use: - In this case, the intention is to withdraw 0.05 liquidity tokens from the pool, expecting to receive 0.004 DOT token (`u128` value of 40000000000 as it has 10 decimals) and 0.04 PPM token (`u128` value of 400000000000 as it also has 10 decimals). +- **`transfer(address to, uint256 amount)`**: Send tokens to another address. +- **`approve(address spender, uint256 amount)`**: Allow another address to spend your tokens. -Signing and submitting the transaction will initiate the withdrawal of liquidity from the pool. To verify the withdrawal, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`LiquidityRemoved`** event was emitted. +Feel free to explore and interact with the contract's other functions using the same approach: select the method, provide any required parameters, and confirm the transaction in MetaMask when needed. -![Remove Liquidity Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-16.webp) +## Where to Go Next -## Test Environment Setup +
    -To test the Asset Conversion pallet, you can set up a local test environment to simulate different scenarios. This guide uses Chopsticks to spin up an instance of Polkadot Asset Hub. For further details on using Chopsticks, please refer to the [Chopsticks documentation](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank}. +- Guide __Deploy an NFT with Remix__ -To set up a local test environment, execute the following command: + --- -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` + Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. -This command initiates a lazy fork of Polkadot Asset Hub, including the most recent block information from the network. For Kusama Asset Hub testing, simply switch out `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) -You now have a local Asset Hub instance up and running, ready for you to test various asset conversion procedures. The process here mirrors what you'd do on MainNet. After completing a transaction on TestNet, you can apply the same steps to convert assets on MainNet. +
    --- -Page Title: Cryptography +Page Title: Deploy an NFT to Polkadot Hub with Foundry -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/cryptography/ -- Summary: A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/.foundry/ +- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Foundry, a Rust toolkit with high-performance compilation. -# Cryptography +# Deploy an NFT with Foundry ## Introduction -Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem. - -## Hash Functions - -Hash functions are fundamental to blockchain technology, creating a unique digital fingerprint for any piece of data, including simple text, images, or any other form of file. They map input data of any size to a fixed-size output (typically 32 bytes) using complex mathematical operations. Hashing is used to verify data integrity, create digital signatures, and provide a secure way to store passwords. This form of mapping is known as the ["pigeonhole principle,"](https://en.wikipedia.org/wiki/Pigeonhole_principle){target=\_blank} it is primarily implemented to efficiently and verifiably identify data from large sets. - -### Key Properties of Hash Functions - -- **Deterministic**: The same input always produces the same output. -- **Quick computation**: It's easy to calculate the hash value for any given input. -- **Pre-image resistance**: It's infeasible to generate the input data from its hash. -- **Small changes in input yield large changes in output**: Known as the ["avalanche effect"](https://en.wikipedia.org/wiki/Avalanche_effect){target=\_blank}. -- **Collision resistance**: The probabilities are extremely low to find two different inputs with the same hash. +Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. -### Blake2 +This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. It showcases a secure approach using [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and the [Foundry](https://getfoundry.sh/){target=\_blank} toolchain. Foundry, a fast, Rust-written toolkit, ensures high-performance compilation and is fully compatible with the Hub’s EVM environment via standard Solidity compilation. -The Polkadot SDK utilizes Blake2, a state-of-the-art hashing method that offers: +## Prerequisites -- Equal or greater security compared to [SHA-2](https://en.wikipedia.org/wiki/SHA-2){target=\_blank}. -- Significantly faster performance than other algorithms. +- Basic understanding of Solidity programming and NFT standards. +- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank}. +- A wallet with a private key for signing transactions. -These properties make Blake2 ideal for blockchain systems, reducing sync times for new nodes and lowering the resources required for validation. For detailed technical specifications about Blake2, see the [official Blake2 paper](https://www.blake2.net/blake2.pdf){target=\_blank}. +## Set Up Your Project -## Types of Cryptography +To get started, take the following steps: -There are two different ways that cryptographic algorithms are implemented: symmetric cryptography and asymmetric cryptography. +1. Install Foundry: -### Symmetric Cryptography + ```bash + curl -L https://foundry.paradigm.xyz | bash + foundryup + ``` -Symmetric encryption is a branch of cryptography that isn't based on one-way functions, unlike asymmetric cryptography. It uses the same cryptographic key to encrypt plain text and decrypt the resulting ciphertext. +2. Initialize your project: -Symmetric cryptography is a type of encryption that has been used throughout history, such as the Enigma Cipher and the Caesar Cipher. It is still widely used today and can be found in Web2 and Web3 applications alike. There is only one single key, and a recipient must also have access to it to access the contained information. + ```bash + forge init foundry-nft-deployment + cd foundry-nft-deployment + ``` -#### Advantages {: #symmetric-advantages } +3. Install OpenZeppelin contracts: -- Fast and efficient for large amounts of data. -- Requires less computational power. + ```bash + forge install OpenZeppelin/openzeppelin-contracts + ``` -#### Disadvantages {: #symmetric-disadvantages } +## Configure Foundry -- Key distribution can be challenging. -- Scalability issues in systems with many users. +Edit `foundry.toml`: -### Asymmetric Cryptography +```toml title="foundry.toml" +[profile.default] +src = "src" +out = "out" +libs = ["lib"] +remappings = ['@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/'] -Asymmetric encryption is a type of cryptography that uses two different keys, known as a keypair: a public key, used to encrypt plain text, and a private counterpart, used to decrypt the ciphertext. +[rpc_endpoints] +polkadot_hub_testnet = "https://testnet-passet-hub-eth-rpc.polkadot.io" +``` -The public key encrypts a fixed-length message that can only be decrypted with the recipient's private key and, sometimes, a set password. The public key can be used to cryptographically verify that the corresponding private key was used to create a piece of data without compromising the private key, such as with digital signatures. This has obvious implications for identity, ownership, and properties and is used in many different protocols across Web2 and Web3. +## Create Your Contract -#### Advantages {: #asymmetric-advantages } +Create `src/MyNFT.sol`: -- Solves the key distribution problem. -- Enables digital signatures and secure key exchange. +```solidity title="src/MyNFT.sol" +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; -#### Disadvantages {: #asymmetric-disadvantages } +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; -- Slower than symmetric encryption. -- Requires more computational resources. +contract MyNFT is ERC721, Ownable { + uint256 private _nextTokenId; -### Trade-offs and Compromises + constructor(address initialOwner) + ERC721("MyToken", "MTK") + Ownable(initialOwner) + {} -Symmetric cryptography is faster and requires fewer bits in the key to achieve the same level of security that asymmetric cryptography provides. However, it requires a shared secret before communication can occur, which poses issues to its integrity and a potential compromise point. On the other hand, asymmetric cryptography doesn't require the secret to be shared ahead of time, allowing for far better end-user security. + function safeMint(address to) public onlyOwner { + uint256 tokenId = _nextTokenId++; + _safeMint(to, tokenId); + } +} +``` -Hybrid symmetric and asymmetric cryptography is often used to overcome the engineering issues of asymmetric cryptography, as it is slower and requires more bits in the key to achieve the same level of security. It encrypts a key and then uses the comparatively lightweight symmetric cipher to do the "heavy lifting" with the message. +## Compile -## Digital Signatures +```bash +forge build +``` -Digital signatures are a way of verifying the authenticity of a document or message using asymmetric keypairs. They are used to ensure that a sender or signer's document or message hasn't been tampered with in transit, and for recipients to verify that the data is accurate and from the expected sender. +Verify the compilation by inspecting the bytecode: -Signing digital signatures only requires a low-level understanding of mathematics and cryptography. For a conceptual example -- when signing a check, it is expected that it cannot be cashed multiple times. This isn't a feature of the signature system but rather the check serialization system. The bank will check that the serial number on the check hasn't already been used. Digital signatures essentially combine these two concepts, allowing the signature to provide the serialization via a unique cryptographic fingerprint that cannot be reproduced. +```bash +forge inspect MyNFT bytecode +``` -Unlike pen-and-paper signatures, knowledge of a digital signature cannot be used to create other signatures. Digital signatures are often used in bureaucratic processes, as they are more secure than simply scanning in a signature and pasting it onto a document. +## Deploy -Polkadot SDK provides multiple different cryptographic schemes and is generic so that it can support anything that implements the [`Pair` trait](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Pair.html){target=\_blank}. +Deploy to Polkadot Hub TestNet: -### Example of Creating a Digital Signature +```bash +forge create MyNFT \ + --rpc-url polkadot_hub_testnet \ + --private-key YOUR_PRIVATE_KEY \ + --constructor-args YOUR_OWNER_ADDRESS \ + --broadcast +``` -The process of creating and verifying a digital signature involves several steps: +Replace `YOUR_PRIVATE_KEY` with your private key and `YOUR_OWNER_ADDRESS` with the address that will own the NFT contract. -1. The sender creates a hash of the message. -2. The hash is encrypted using the sender's private key, creating the signature. -3. The message and signature are sent to the recipient. -4. The recipient decrypts the signature using the sender's public key. -5. The recipient hashes the received message and compares it to the decrypted hash. +## Where to Go Next -If the hashes match, the signature is valid, confirming the message's integrity and the sender's identity. +
    -## Elliptic Curve +- Guide __Verify Your Contract__ -Blockchain technology requires the ability to have multiple keys creating a signature for block proposal and validation. To this end, Elliptic Curve Digital Signature Algorithm (ECDSA) and Schnorr signatures are two of the most commonly used methods. While ECDSA is a far simpler implementation, Schnorr signatures are more efficient when it comes to multi-signatures. + --- -Schnorr signatures bring some noticeable features over the ECDSA/EdDSA schemes: + Now that you've deployed an NFT contract, learn how to verify it with Foundry. -- It is better for hierarchical deterministic key derivations. -- It allows for native multi-signature through [signature aggregation](https://bitcoincore.org/en/2017/03/23/schnorr-signature-aggregation/){target=\_blank}. -- It is generally more resistant to misuse. + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/foundry/verify-a-contract/) -One sacrifice that is made when using Schnorr signatures over ECDSA is that both require 64 bytes, but only ECDSA signatures communicate their public key. +- Guide __Deploy an ERC-20__ -### Various Implementations + --- -- **[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm){target=\_blank}**: Polkadot SDK provides an ECDSA signature scheme using the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1){target=\_blank} curve. This is the same cryptographic algorithm used to secure [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin){target=\_blank} and [Ethereum](https://en.wikipedia.org/wiki/Ethereum){target=\_blank}. + Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Foundry. -- **[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519){target=\_blank}**: An EdDSA signature scheme using [Curve25519](https://en.wikipedia.org/wiki/Curve25519){target=\_blank}. It is carefully engineered at several levels of design and implementation to achieve very high speeds without compromising security. + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/foundry/) -- **[SR25519](https://research.web3.foundation/Polkadot/security/keys/accounts-more){target=\_blank}**: Based on the same underlying curve as Ed25519. However, it uses Schnorr signatures instead of the EdDSA scheme. +
    --- -Page Title: Data Encoding +Page Title: Deploy an NFT to Polkadot Hub with Hardhat -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/data-encoding/ -- Summary: SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/ +- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub with Hardhat, a comprehenive development environment with built-in deployment capabilities. -# Data Encoding +# Deploy an NFT with Hardhat ## Introduction -The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data. - -The SCALE codec enables communication between the runtime and the outer node. This mechanism is designed for high-performance, copy-free data encoding and decoding in resource-constrained environments like the Polkadot SDK [Wasm runtime](/develop/parachains/deployment/build-deterministic-runtime/#introduction){target=\_blank}. - -It is not self-describing, meaning the decoding context must fully know the encoded data types. +Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. -Parity's libraries utilize the [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} crate (a Rust implementation of the SCALE codec) to handle encoding and decoding for interactions between RPCs and the runtime. +This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Hardhat](https://hardhat.org/docs/getting-started){target=\_blank}, a comprehensive development environment with built-in testing, debugging, and deployment capabilities. Hardhat uses standard Solidity compilation to generate EVM bytecode, making it fully compatible with Polkadot Hub's EVM environment. -The `codec` mechanism is ideal for Polkadot SDK-based chains because: +## Prerequisites -- It is lightweight compared to generic serialization frameworks like [`serde`](https://serde.rs/){target=\_blank}, which add unnecessary bulk to binaries. -- It doesn’t rely on Rust’s `libstd`, making it compatible with `no_std` environments like Wasm runtime. -- It integrates seamlessly with Rust, allowing easy derivation of encoding and decoding logic for new types using `#[derive(Encode, Decode)]`. +- Basic understanding of Solidity programming and NFT standards. +- Node.js v22.13.1 or later. +- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. +- A wallet with a private key for signing transactions. -Defining a custom encoding scheme in the Polkadot SDK-based chains, rather than using an existing Rust codec library, is crucial for enabling cross-platform and multi-language support. +## Set Up Your Project -## SCALE Codec +Take the following steps to get started: -The codec is implemented using the following traits: +1. Initialize your Hardhat project: -- [`Encode`](#encode) -- [`Decode`](#decode) -- [`CompactAs`](#compactas) -- [`HasCompact`](#hascompact) -- [`EncodeLike`](#encodelike) - -### Encode + ```bash + mkdir hardhat-nft-deployment + cd hardhat-nft-deployment + npx hardhat --init + ``` -The [`Encode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Encode.html){target=\_blank} trait handles data encoding into SCALE format and includes the following key functions: +2. Install OpenZeppelin contracts: -- **`size_hint(&self) -> usize`**: Estimates the number of bytes required for encoding to prevent multiple memory allocations. This should be inexpensive and avoid complex operations. Optional if the size isn’t known. -- **`encode_to(&self, dest: &mut T)`**: Encodes the data, appending it to a destination buffer. -- **`encode(&self) -> Vec`**: Encodes the data and returns it as a byte vector. -- **`using_encoded R>(&self, f: F) -> R`**: Encodes the data and passes it to a closure, returning the result. -- **`encoded_size(&self) -> usize`**: Calculates the encoded size. Should be used when the encoded data isn’t required. + ```bash + npm install @openzeppelin/contracts + ``` -!!!tip - For best performance, value types should override `using_encoded`, and allocating types should override `encode_to`. It's recommended to implement `size_hint` for all types where possible. +## Configure Hardhat -### Decode +Edit `hardhat.config.ts`: -The [`Decode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Decode.html){target=\_blank} trait handles decoding SCALE-encoded data back into the appropriate types: +```typescript title="hardhat.config.ts" +import type { HardhatUserConfig } from 'hardhat/config'; -- **`fn decode(value: &mut I) -> Result`**: Decodes data from the SCALE format, returning an error if decoding fails. +import hardhatToolboxViemPlugin from '@nomicfoundation/hardhat-toolbox-viem'; +import { configVariable } from 'hardhat/config'; -### CompactAs +const config: HardhatUserConfig = { + plugins: [hardhatToolboxViemPlugin], + solidity: { + profiles: { + default: { + version: '0.8.28', + }, + production: { + version: '0.8.28', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + }, + }, + networks: { + hardhatMainnet: { + type: 'edr-simulated', + chainType: 'l1', + }, + hardhatOp: { + type: 'edr-simulated', + chainType: 'op', + }, + sepolia: { + type: 'http', + chainType: 'l1', + url: configVariable('SEPOLIA_RPC_URL'), + accounts: [configVariable('SEPOLIA_PRIVATE_KEY')], + }, + polkadotHubTestnet: { + type: 'http', + url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + accounts: [configVariable('PRIVATE_KEY')], + }, + }, +}; -The [`CompactAs`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.CompactAs.html){target=\_blank} trait wraps custom types for compact encoding: +export default config; +``` -- **`encode_as(&self) -> &Self::As`**: Encodes the type as a compact type. -- **`decode_from(_: Self::As) -> Result`**: decodes from a compact encoded type. +!!! tip + Learn how to use Hardhat's [Config Variables](https://hardhat.org/docs/learn-more/configuration-variables){target=\_blank} to handle your private keys in a secure way. -### HasCompact +## Create Your Contract -The [`HasCompact`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.HasCompact.html){target=\_blank} trait indicates a type supports compact encoding. +Create `contracts/MyNFT.sol`: -### EncodeLike +```solidity title="contracts/MyNFT.sol" +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; -The [`EncodeLike`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.EncodeLike.html){target=\_blank} trait is used to ensure multiple types that encode similarly are accepted by the same function. When using `derive`, it is automatically implemented. +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; -### Data Types +contract MyNFT is ERC721, Ownable { + uint256 private _nextTokenId; -The table below outlines how the Rust implementation of the Parity SCALE codec encodes different data types. + constructor(address initialOwner) + ERC721("MyToken", "MTK") + Ownable(initialOwner) + {} -| Type | Description | Example SCALE Decoded Value | SCALE Encoded Value | -|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| -| Boolean | Boolean values are encoded using the least significant bit of a single byte. | `false` / `true` | `0x00` / `0x01` | -| Compact/general integers | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2^536) and is more efficient at encoding most values than the fixed-width version. | `unsigned integer 0` / `unsigned integer 1` / `unsigned integer 42` / `unsigned integer 69` / `unsigned integer 65535` / `BigInt(100000000000000)` | `0x00` / `0x04` / `0xa8` / `0x1501` / `0xfeff0300` / `0x0b00407a10f35a` | -| Enumerations (tagged-unions) | A fixed number of variants, each mutually exclusive and potentially implying a further value or series of values. Encoded as the first byte identifying the index of the variant that the value is. Any further bytes are used to encode any data that the variant implies. Thus, no more than 256 variants are supported. | `Int(42)` and `Bool(true)` where `enum IntOrBool { Int(u8), Bool(bool) }` | `0x002a` and `0x0101` | -| Fixed-width integers | Basic integers are encoded using a fixed-width little-endian (LE) format. | `signed 8-bit integer 69` / `unsigned 16-bit integer 42` / `unsigned 32-bit integer 16777215` | `0x45` / `0x2a00` / `0xffffff00` | -| Options | One or zero values of a particular type. | `Some` / `None` | `0x01` followed by the encoded value / `0x00` | -| Results | Results are commonly used enumerations which indicate whether certain operations were successful or unsuccessful. | `Ok(42)` / `Err(false)` | `0x002a` / `0x0100` | -| Strings | Strings are Vectors of bytes (Vec) containing a valid UTF8 sequence. | | | -| Structs | For structures, the values are named, but that is irrelevant for the encoding (names are ignored - only order matters). | `SortedVecAsc::from([3, 5, 2, 8])` | `[3, 2, 5, 8] ` | -| Tuples | A fixed-size series of values, each with a possibly different but predetermined and fixed type. This is simply the concatenation of each encoded value. | Tuple of compact unsigned integer and boolean: `(3, false)` | `0x0c00` | -| Vectors (lists, series, sets) | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. | Vector of unsigned `16`-bit integers: `[4, 8, 15, 16, 23, 42]` | `0x18040008000f00100017002a00` | + function safeMint(address to) public onlyOwner { + uint256 tokenId = _nextTokenId++; + _safeMint(to, tokenId); + } +} +``` -## Encode and Decode Rust Trait Implementations +## Compile -Here's how the `Encode` and `Decode` traits are implemented: +```bash +npx hardhat compile +``` +## Set Up Deployment -```rust -use parity_scale_codec::{Encode, Decode}; - -[derive(Debug, PartialEq, Encode, Decode)] -enum EnumType { - #[codec(index = 15)] - A, - B(u32, u64), - C { - a: u32, - b: u64, - }, -} +Create a deployment module in `ignition/modules/MyNFT.ts`: -let a = EnumType::A; -let b = EnumType::B(1, 2); -let c = EnumType::C { a: 1, b: 2 }; +```typescript title="ignition/modules/MyNFT.ts" +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -a.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x0f"); +export default buildModule('MyNFTModule', (m) => { + const initialOwner = m.getParameter('initialOwner', 'INSERT_OWNER_ADDRESS'); + const myNFT = m.contract('MyNFT', [initialOwner]); + return { myNFT }; }); +``` -b.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); +Replace `INSERT_OWNER_ADDRESS` with your desired owner address. -c.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); +## Deploy -let mut da: &[u8] = b"\x0f"; -assert_eq!(EnumType::decode(&mut da).ok(), Some(a)); +Deploy to Polkadot Hub TestNet: -let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut db).ok(), Some(b)); +```bash +npx hardhat ignition deploy ignition/modules/MyNFT.ts --network polkadotHubTestnet +``` -let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut dc).ok(), Some(c)); +## Where to Go Next -let mut dz: &[u8] = &[0]; -assert_eq!(EnumType::decode(&mut dz).ok(), None); -``` +
    -## SCALE Codec Libraries +- Guide __Verify Your Contract__ -Several SCALE codec implementations are available in various languages. Here's a list of them: + --- -- **AssemblyScript**: [`LimeChain/as-scale-codec`](https://github.com/LimeChain/as-scale-codec){target=\_blank} -- **C**: [`MatthewDarnell/cScale`](https://github.com/MatthewDarnell/cScale){target=\_blank} -- **C++**: [`qdrvm/scale-codec-cpp`](https://github.com/qdrvm/scale-codec-cpp){target=\_blank} -- **JavaScript**: [`polkadot-js/api`](https://github.com/polkadot-js/api){target=\_blank} -- **Dart**: [`leonardocustodio/polkadart`](https://github.com/leonardocustodio/polkadart){target=\_blank} -- **Haskell**: [`airalab/hs-web3`](https://github.com/airalab/hs-web3/tree/master/packages/scale){target=\_blank} -- **Golang**: [`itering/scale.go`](https://github.com/itering/scale.go){target=\_blank} -- **Java**: [`splix/polkaj`](https://github.com/splix/polkaj){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **Ruby**: [` wuminzhe/scale_rb`](https://github.com/wuminzhe/scale_rb){target=\_blank} -- **TypeScript**: [`parity-scale-codec-ts`](https://github.com/tjjfvi/subshape){target=\_blank}, [`scale-ts`](https://github.com/unstoppablejs/unstoppablejs/tree/main/packages/scale-ts#scale-ts){target=\_blank}, [`soramitsu/scale-codec-js-library`](https://github.com/soramitsu/scale-codec-js-library){target=\_blank}, [`subsquid/scale-codec`](https://github.com/subsquid/squid-sdk/tree/master/substrate/scale-codec){target=\_blank} + Now that you've deployed an NFT contract, learn how to verify it with Hardhat. + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/verify-a-contract/) ---- -Page Title: Dedot +- Guide __Deploy an ERC-20__ -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/dedot/ -- Summary: Dedot is a next-gen JavaScript client for Polkadot and Polkadot SDK-based blockchains, offering lightweight, tree-shakable APIs with strong TypeScript support. + --- -# Dedot + Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Hardhat. -## Introduction + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/hardhat/) -[Dedot](https://github.com/dedotdev/dedot){target=\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\_blank}. +
    -### Key Features -- **Lightweight and tree-shakable**: No more bn.js or WebAssembly blobs, optimized for dapps bundle size. -- **Fully typed API**: Comprehensive TypeScript support for seamless on-chain interaction and ink! smart contract integration. -- **Multi-version JSON-RPC support**: Compatible with both [legacy](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md){target=\_blank} and [new](https://paritytech.github.io/json-rpc-interface-spec/introduction.html){target=\_blank} JSON-RPC APIs for broad ecosystem interoperability. -- **Light client support**: Designed to work with light clients such as [Smoldot](https://github.com/smol-dot/smoldot){target=\_blank}. -- **Native TypeScript for scale codec**: Implements scale codec parsing directly in TypeScript without relying on custom wrappers. -- **Wallet integration**: Works out-of-the-box with [@polkadot/extension-based](https://github.com/polkadot-js/extension?tab=readme-ov-file#api-interface){target=\_blank} wallets. -- **Familiar API design**: Similar API style to Polkadot.js for easy and fast migration. +--- -## Installation +Page Title: Deploy an NFT to Polkadot Hub with Remix -To add Dedot to your project, use the following command: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/ +- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Remix, a browser-based IDE for quick prototyping and learning. -=== "npm" +# Deploy an NFT with Remix - ```bash - npm i dedot - ``` +## Introduction -=== "pnpm" +Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. - ```bash - pnpm add dedot - ``` +This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Remix](https://remix.ethereum.org/){target=\_blank}, a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development. -=== "yarn" +## Prerequisites - ```bash - yarn add dedot - ``` +- Basic understanding of Solidity programming and NFT standards. +- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank} +- A wallet with a private key for signing transactions. -To enable auto-completion/IntelliSense for individual chains, install the [`@dedot/chaintypes`](https://www.npmjs.com/package/@dedot/chaintypes){target=\_blank} package as a development dependency: +## Access Remix -=== "npm" +Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. - ```bash - npm i -D @dedot/chaintypes - ``` +The interface will load with a default workspace containing sample contracts. In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. -=== "pnpm" +## Create Your Contract - ```bash - pnpm add -D @dedot/chaintypes - ``` +1. Create a new file `contracts/MyNFT.sol`. +2. Paste the following code: -=== "yarn" + ```solidity title="contracts/MyNFT.sol" + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.20; - ```bash - yarn add -D @dedot/chaintypes - ``` + import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + import "@openzeppelin/contracts/access/Ownable.sol"; -## Get Started + contract MyNFT is ERC721, Ownable { + uint256 private _nextTokenId; -### Initialize a Client Instance + constructor(address initialOwner) + ERC721("MyToken", "MTK") + Ownable(initialOwner) + {} -To connect to and interact with different networks, Dedot provides two client options depending on your needs: + function safeMint(address to) public onlyOwner { + uint256 tokenId = _nextTokenId++; + _safeMint(to, tokenId); + } + } + ``` -- **[`DedotClient`](https://docs.dedot.dev/clients-and-providers/clients#dedotclient){target=\_blank}**: Interacts with chains via the [new JSON-RPC APIs](https://paritytech.github.io/json-rpc-interface-spec/introduction.html){target=\_blank}. -- **[`LegacyClient`](https://docs.dedot.dev/clients-and-providers/clients#legacyclient){target=\_blank}**: Interacts with chains via the [legacy JSON-RPC APIs](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md){target=\_blank}. +![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-01.webp) -Use the following snippets to connect to Polkadot using `DedotClient`: +## Compile -=== "WebSocket" +1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). +2. Click **Compile MyNFT.sol** or press `Ctrl+S`. - ```typescript - import { DedotClient, WsProvider } from 'dedot'; - import type { PolkadotApi } from '@dedot/chaintypes'; +![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-02.webp) - // Initialize providers & clients - const provider = new WsProvider('wss://rpc.polkadot.io'); - const client = await DedotClient.new(provider); +Compilation errors and warnings appear in the terminal panel at the bottom of the screen. - ``` +## Deploy -=== "Light Client (Smoldot)" +1. Navigate to the **Deploy & Run Transactions** tab. +2. Click the **Environment** dropdown, select **Browser Extension**, and click on **Injected Provider - MetaMask**. - ```typescript - import { DedotClient, SmoldotProvider } from 'dedot'; - import type { PolkadotApi } from '@dedot/chaintypes'; - import * as smoldot from 'smoldot'; + ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-03.webp) - // import `polkadot` chain spec to connect to Polkadot - import { polkadot } from '@substrate/connect-known-chains'; +3. In the deploy section, enter the initial owner address in the constructor parameter field. +4. Click **Deploy**. - // Start smoldot instance & initialize a chain - const client = smoldot.start(); - const chain = await client.addChain({ chainSpec: polkadot }); + ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-04.webp) - // Initialize providers & clients - const provider = new SmoldotProvider(chain); - const client = await DedotClient.new(provider); +5. Approve the transaction in your MetaMask wallet. - ``` +Your deployed contract will appear in the **Deployed Contracts** section, ready for interaction. -If the node doesn't support new JSON-RPC APIs yet, you can connect to the network using the `LegacyClient`, which is built on top of the legacy JSON-RPC APIs. +## Where to Go Next -```typescript -import { LegacyClient, WsProvider } from 'dedot'; -import type { PolkadotApi } from '@dedot/chaintypes'; +
    -const provider = new WsProvider('wss://rpc.polkadot.io'); -const client = await LegacyClient.new(provider); +- Guide __Verify Your Contract__ -``` + --- -### Enable Type and API Suggestions + Now that you've deployed an NFT contract, learn how to verify it with Remix. -It is recommended to specify the `ChainApi` interface (e.g., `PolkadotApi` in the example in the previous section) of the chain you want to interact with. This enables type and API suggestions/autocompletion for that particular chain (via IntelliSense). If you don't specify a `ChainApi` interface, a default `SubstrateApi` interface will be used. + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/verify-a-contract/) -```typescript -import { DedotClient, WsProvider } from 'dedot'; -import type { PolkadotApi, KusamaApi } from '@dedot/chaintypes'; +- Guide __Deploy an ERC-20__ -const polkadotClient = await DedotClient.new( - new WsProvider('wss://rpc.polkadot.io') -); -const kusamaClient = await DedotClient.new( - new WsProvider('wss://kusama-rpc.polkadot.io') -); -const genericClient = await DedotClient.new( - new WsProvider('ws://localhost:9944') -); + --- -``` + Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Remix. -If you don't find the `ChainApi` for the network you're working with in [the list](https://github.com/dedotdev/chaintypes?tab=readme-ov-file#supported-networks){target=\_blank}, you can generate the `ChainApi` (types and APIs) using the built-in [`dedot` cli](https://docs.dedot.dev/cli){target=\_blank}. + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) -```bash -# Generate ChainApi interface for Polkadot network via rpc endpoint: wss://rpc.polkadot.io -npx dedot chaintypes -w wss://rpc.polkadot.io -``` +
    -Or open a pull request to add your favorite network to the [`@dedot/chaintypes`](https://github.com/dedotdev/chaintypes){target=\_blank} repo. -### Read On-Chain Data +--- -Dedot provides several ways to read data from the chain: +Page Title: Deploying Uniswap V2 on Polkadot -- **Access runtime constants**: Use the syntax `client.consts..` to inspect runtime constants (parameter types). +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/ +- Summary: Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. - ```typescript - const ss58Prefix = client.consts.system.ss58Prefix; - console.log('Polkadot ss58Prefix:', ss58Prefix); +# Deploy Uniswap V2 - ``` +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -- **Storage queries**: Use the syntax `client.query..` to query on-chain storage. +Decentralized exchanges (DEXs) are a cornerstone of the DeFi ecosystem, allowing for permissionless token swaps without intermediaries. [Uniswap V2](https://docs.uniswap.org/contracts/v2/overview){target=\_blank}, with its Automated Market Maker (AMM) model, revolutionized DEXs by enabling liquidity provision for any ERC-20 token pair. - ```typescript - const balance = await client.query.system.account('INSERT_ADDRESS'); - console.log('Balance:', balance.data.free); +This tutorial will guide you through how Uniswap V2 works so you can take advantage of it in your projects deployed to Polkadot Hub. By understanding these contracts, you'll gain hands-on experience with one of the most influential DeFi protocols and understand how it functions across blockchain ecosystems. - ``` +## Prerequisites -- **Subscribe to storage changes**: +Before starting, make sure you have: - ```typescript - const unsub = await client.query.system.number((blockNumber) => { - console.log(`Current block number: ${blockNumber}`); - }); +- Node.js (v16.0.0 or later) and npm installed. +- Basic understanding of Solidity and JavaScript. +- Familiarity with [`hardhat-polkadot`](/smart-contracts/dev-environments/hardhat/get-started/){target=\_blank} development environment. +- Some PAS test tokens to cover transaction fees (obtained from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}). +- Basic understanding of how AMMs and liquidity pools work. - ``` +## Set Up the Project -- **Call Runtime APIs**: Use the syntax `client.call..` to execute Runtime APIs. +Let's start by cloning the Uniswap V2 project: - ```typescript - const metadata = await client.call.metadata.metadataAtVersion(15); - console.log('Metadata V15', metadata); +1. Clone the Uniswap V2 repository: ``` + git clone https://github.com/polkadot-developers/polkavm-hardhat-examples.git -b v0.0.6 + cd polkavm-hardhat-examples/uniswap-v2-polkadot/ + ``` -- **Watch on-chain events**: Use the syntax `client.events..` to access pallet events. - - ```typescript - const unsub = await client.events.system.NewAccount.watch((events) => { - console.log('New Account Created', events); - }); +2. Install the required dependencies: + ```bash + npm install ``` -### Sign and Send Transactions - -Sign the transaction using `IKeyringPair` from Keyring ([`@polkadot/keyring`](https://polkadot.js.org/docs/keyring/start/sign-verify/){target=\_blank}) and send the transaction. - -```typescript -import { cryptoWaitReady } from '@polkadot/util-crypto'; -import { Keyring } from '@polkadot/keyring'; -// Setup keyring -await cryptoWaitReady(); -const keyring = new Keyring({ type: 'sr25519' }); -const alice = keyring.addFromUri('//Alice'); -// Send transaction -const unsub = await client.tx.balances - .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n) - .signAndSend(alice, async ({ status }) => { - console.log('Transaction status', status.type); - if (status.type === 'BestChainBlockIncluded') { - console.log(`Transaction is included in best block`); - } - if (status.type === 'Finalized') { - console.log( - `Transaction completed at block hash ${status.value.blockHash}` - ); - await unsub(); - } - }); +3. Update the `hardhat.config.js` file so the paths for the Substrate node and the ETH-RPC adapter match with the paths on your machine. For more info, check the [Testing your Contract](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} section in the Hardhat guide. -``` + ```js title="hardhat.config.js" + hardhat: { + polkavm: true, + nodeConfig: { + nodeBinaryPath: '../bin/substrate-node', + rpcPort: 8000, + dev: true, + }, + adapterConfig: { + adapterBinaryPath: '../bin/eth-rpc', + dev: true, + }, + }, + ``` -You can also use `Signer` from wallet extensions: - -```typescript -const injected = await window.injectedWeb3['polkadot-js'].enable('My dApp'); -const account = (await injected.accounts.get())[0]; -const signer = injected.signer; -const unsub = await client.tx.balances - .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n) - .signAndSend(account.address, { signer }, async ({ status }) => { - console.log('Transaction status', status.type); - if (status.type === 'BestChainBlockIncluded') { - console.log(`Transaction is included in best block`); - } - if (status.type === 'Finalized') { - console.log( - `Transaction completed at block hash ${status.value.blockHash}` - ); - await unsub(); - } - }); +4. Create a `.env` file in your project root to store your private keys (you can use as an example the `env.example` file): -``` + ```text title=".env" + LOCAL_PRIV_KEY="INSERT_LOCAL_PRIVATE_KEY" + AH_PRIV_KEY="INSERT_AH_PRIVATE_KEY" + ``` -## Where to Go Next - -For more detailed information about Dedot, check the [official documentation](https://dedot.dev/){target=\_blank}. - - ---- - -Page Title: Deploy an ERC-20 to Polkadot Hub - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/ -- Summary: Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Hardhat. - -# Deploy an ERC-20 to Polkadot Hub - -## Introduction - -[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. - -This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Hardhat](https://hardhat.org/){target=\_blank}, an Ethereum development environment. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. - -## Prerequisites - -Before starting, make sure you have: - -- Basic understanding of Solidity programming and fungible tokens. -- Node.js v22.13.1 or later. -- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. - -## Set Up Your Project - -This tutorial uses a [Hardhat ERC-20 template](https://github.com/polkadot-developers/revm-hardhat-examples/tree/master/erc20-hardhat){target=\_blank} that contains all the necessary files. To get started, take the following steps: - -1. Clone the GitHub repository locally: - - ```bash - git clone https://github.com/polkadot-developers/revm-hardhat-examples/ - cd revm-hardhat-examples/erc20-hardhat - ``` - -2. Install the dependencies: - - ```bash - npm i - ``` - -This will fetch all the necessary packages to help you deploy an ERC-20 with Hardhat to Polkadot. - -## Configure Hardhat - -Once you've [setup your project](#set-up-your-project), you can configure the `hardhat.config.ts` to your needs. This tutorial has the file prepared to deploy to the Polkadot TestNet. - -To store and use private keys or network URLs, you can use Hardhat's configuration variables. This can be set via tasks in the **vars** scope. For example, to store the private key to deploy to the Polkadot TestNet, run the following command: - -```bash -npx hardhat vars set TESTNET_PRIVATE_KEY -``` - -The command will initiate a wizard in which you'll have to enter the value to be stored: - -
    - npx hardhat vars set TESTNET_PRIVATE_KEY - ✔ Enter value: · ••••••••• - The configuration variable has been stored in /Users/albertoviera/Library/Preferences/hardhat-nodejs/vars.json -
    - -??? warning "Key Encryption" - This solution just prevents variables to be included in the code repository. You should find a solution that encrypts private keys and access them securely. - -You can now use the account related to this private key by importing it into the Hardhat configuration file: - -```ts title="hardhat.config.ts" hl_lines="1 17" - -const config: HardhatUserConfig = { - solidity: { - version: "0.8.28", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - networks: { - polkadotTestnet: { - url: vars.get("TESTNET_URL", "http://127.0.0.1:8545"), - accounts: vars.has("TESTNET_PRIVATE_KEY") ? [vars.get("TESTNET_PRIVATE_KEY")] : [], - }, - }, - mocha: { - timeout: 40000, - }, -}; - -export default config; -``` - -## Compile your Contract - -Once you've configured Hardhat, you can compile the contract. - -In this tutorial, a simple ERC-20 is provided. Therefore, to compile the contract you can run the following command: - -```bash -npx hardhat compile -``` - -If everything compiles successfully, you should see the following output: - -
    - npx hardhat compile - Generating typings for: 23 artifacts in dir: typechain-types for target: ethers-v6 - Successfully generated 62 typings! - Compiled 21 Solidity files successfully (evm target: paris). -
    - -## Test your Contract - -Hardhat has a native feature to test contracts. You can run tests against the local Hardhat development node, but it could have some technical differences to Polkadot. Therefore, in this tutorial, you'll be testing against the Polkadot TestNet - -This example has a predefined test file located in [`test/Token.test.js`](https://github.com/polkadot-developers/revm-hardhat-examples/blob/master/erc20-hardhat/test/MyToken.test.ts){target=\_blank}, that runs the following tests: - -1. The token was deployed by verifying its **name** and **symbol**. -2. The token has the right owner configured. -3. The token has an initial supply of zero. -4. The owner can mint tokens. -5. The total supply is increased after a mint. -6. Perform multiple mints to different addresses and checks the balance of each address and the new total supply. - -To run the test, you can execute the following command: - -```bash -npx hardhat test --network polkadotTestnet -``` - -If tests are successful, you should see the following logs: - -
    - npx hardhat test --network polkadotTestnet - -   MyToken -     Deployment -       ✔ Should have correct name and symbol -       ✔ Should set the right owner -       ✔ Should have zero initial supply -     Minting -       ✔ Should allow owner to mint tokens -       ✔ Should increase total supply on mint -     Multiple mints -       ✔ Should correctly track balance after multiple mints - -   6 passing (369ms) -
    - -## Deploy your Contract - -With the Hardhat configuration file ready, the private key stored as a variable under **vars**, and the contract compiled, you can proceed to deploy the contract to a given network. In this tutorial, you are deploying it to the Polkadot TestNet. - -To deploy the contract, run the following command: - -```bash -npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet -``` - -You'll need to confirm the target network (by chain ID): - -
    - npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet - ✔ Confirm deploy to network polkadotTestnet (420420420)? … yes -   - Hardhat Ignition 🚀 -   - Deploying [ TokenModule ] -   - Batch #1 - Executed TokenModule#MyToken -   - Batch #2 - Executed TokenModule#MyToken.mint -   - [ TokenModule ] successfully deployed 🚀 -   - Deployed Addresses -   - TokenModule#MyToken - 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3 -
    - -And that is it! You've successfully deployed an ERC-20 token contract to the Polkadot TestNet using Hardhat. - -## Where to Go Next - -
    - -- Guide __Deploy an NFT with Remix__ - - --- - - Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) - -
    - - ---- - -Page Title: Deploy an ERC-20 to Polkadot Hub - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/ -- Summary: Deploy an ERC-20 token contract on Polkadot Hub. This guide covers contract creation, compilation, deployment, and interaction via the Remix IDE. - -# Deploy an ERC-20 to Polkadot Hub - -## Introduction - -[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. - -This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Remix IDE](https://remix.ethereum.org/){target=\_blank}, a web-based development tool. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. - -## Prerequisites - -Before starting, make sure you have: - -- Basic understanding of Solidity programming and fungible tokens. -- An EVM-compatible wallet [connected to Polkadot Hub](/smart-contracts/integrations/wallets){target=\_blank}. This example utilizes [MetaMask](https://metamask.io/){target=\_blank}. -- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. - -## Create Your Contract - -To create the ERC-20 contract, you can follow the steps below: - -1. Navigate to the [Polkadot Remix IDE](https://remix.polkadot.io){target=\_blank}. -2. Click in the **Create new file** button under the **contracts** folder, and name your contract as `MyToken.sol`. - - ![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-1.webp) - -3. Now, paste the following ERC-20 contract code into the editor: - - ```solidity title="MyToken.sol" - // SPDX-License-Identifier: MIT - // Compatible with OpenZeppelin Contracts ^5.4.0 - pragma solidity ^0.8.27; - - import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; - import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; - - contract MyToken is ERC20, Ownable, ERC20Permit { - constructor(address initialOwner) - ERC20("MyToken", "MTK") - Ownable(initialOwner) - ERC20Permit("MyToken") - {} - - function mint(address to, uint256 amount) public onlyOwner { - _mint(to, amount); - } - } - ``` - - The key components of the code above are: - - - Contract imports: - - - **[`ERC20.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/ERC20.sol){target=\_blank}**: The base contract for fungible tokens, implementing core functionality like transfers, approvals, and balance tracking. - - **[`ERC20Permit.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/extensions/ERC20Permit.sol){target=\_blank}**: [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612){target=\_blank} extension for ERC-20 that adds the [permit function](https://docs.openzeppelin.com/contracts/5.x/api/token/erc20#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-){target=\_blank}, allowing approvals via off-chain signatures (no on-chain tx from the holder). Manages nonces and EIP-712 domain separator and updates allowances when a valid signature is presented. - - **[`Ownable.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/access/Ownable.sol){target=\_blank}**: Provides basic authorization control, ensuring only the contract owner can mint new tokens. - - - Constructor parameters: - - - **`initialOwner`**: Sets the address that will have administrative rights over the contract. - - **`"MyToken"`**: The full name of your token. - - **`"MTK"`**: The symbol representing your token in wallets and exchanges. - - - Key functions: - - - **`mint(address to, uint256 amount)`**: Allows the contract owner to create new tokens for any address. The amount should include 18 decimals (e.g., 1 token = 1000000000000000000). - - Inherited [Standard ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/){target=\_blank} functions: - - **`transfer(address recipient, uint256 amount)`**: Sends a specified amount of tokens to another address. - - **`approve(address spender, uint256 amount)`**: Grants permission for another address to spend a specific number of tokens on behalf of the token owner. - - **`transferFrom(address sender, address recipient, uint256 amount)`**: Transfers tokens from one address to another, if previously approved. - - **`balanceOf(address account)`**: Returns the token balance of a specific address. - - **`allowance(address owner, address spender)`**: Checks how many tokens an address is allowed to spend on behalf of another address. - - !!! tip - Use the [OpenZeppelin Contracts Wizard](https://wizard.openzeppelin.com/){target=\_blank} to generate customized smart contracts quickly. Simply configure your contract, copy the generated code, and paste it into the Remix IDE for deployment. Below is an example of an ERC-20 token contract created with it: - - ![Screenshot of the OpenZeppelin Contracts Wizard showing an ERC-20 contract configuration.](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-2.webp) - - -## Compile - -The compilation transforms your Solidity source code into bytecode that can be deployed on the blockchain. During this process, the compiler checks your contract for syntax errors, ensures type safety, and generates the machine-readable instructions needed for blockchain execution. - -To compile your contract, ensure you have it opened in the Remix IDE Editor, and follow the instructions below: - -1. Select the **Solidity Compiler** plugin from the left panel. -2. Click the **Compile MyToken.sol** button. -3. If the compilation succeeded, you'll see a green checkmark indicating success in the **Solidity Compiler** icon. - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-3.gif) - -## Deploy - -Deployment is the process of publishing your compiled smart contract to the blockchain, making it permanently available for interaction. During deployment, you'll create a new instance of your contract on the blockchain, which involves: - -1. Select the **Deploy & Run Transactions** plugin from the left panel. -2. Configure the deployment settings: - 1. From the **ENVIRONMENT** dropdown, select **Injected Provider - MetaMask** (check the [Deploying Contracts](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} section of the Remix IDE guide for more details). - 2. (Optional) From the **ACCOUNT** dropdown, select the acccount you want to use for the deploy. - -3. Configure the contract parameters: - 1. Enter the address that will own the deployed token contract. - 2. Click the **Deploy** button to initiate the deployment. - -4. **MetaMask will pop up**: Review the transaction details. Click **Confirm** to deploy your contract. -5. If the deployment process succeeded, you will see the transaction details in the terminal, including the contract address and deployment transaction hash. - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-4.gif) - -## Interact with Your Contract - -Once deployed, you can interact with your contract through Remix. Find your contract under **Deployed/Unpinned Contracts**, and click it to expand the available methods. In this example, you'll mint some tokens to a given address: - -1. Expand the **mint** function: - 1. Enter the recipient address and the amount (remember to add 18 zeros for 1 whole token). - 2. Click **transact**. - -2. Click **Approve** to confirm the transaction in the MetaMask popup. - -3. If the transaction succeeds, you will see a green check mark in the terminal. - -4. You can also call the **balanceOf** function by passing the address of the **mint** call to confirm the new balance. - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-5.gif) - - -Other standard functions you can use: - -- **`transfer(address to, uint256 amount)`**: Send tokens to another address. -- **`approve(address spender, uint256 amount)`**: Allow another address to spend your tokens. - -Feel free to explore and interact with the contract's other functions using the same approach: select the method, provide any required parameters, and confirm the transaction in MetaMask when needed. - -## Where to Go Next - -
    - -- Guide __Deploy an NFT with Remix__ - - --- - - Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) - -
    - - ---- - -Page Title: Deploy an NFT to Polkadot Hub with Foundry - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/.foundry/ -- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Foundry, a Rust toolkit with high-performance compilation. - -# Deploy an NFT with Foundry - -## Introduction - -Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. - -This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. It showcases a secure approach using [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and the [Foundry](https://getfoundry.sh/){target=\_blank} toolchain. Foundry, a fast, Rust-written toolkit, ensures high-performance compilation and is fully compatible with the Hub’s EVM environment via standard Solidity compilation. - -## Prerequisites - -- Basic understanding of Solidity programming and NFT standards. -- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank}. -- A wallet with a private key for signing transactions. - -## Set Up Your Project - -To get started, take the following steps: - -1. Install Foundry: - - ```bash - curl -L https://foundry.paradigm.xyz | bash - foundryup - ``` - -2. Initialize your project: - - ```bash - forge init foundry-nft-deployment - cd foundry-nft-deployment - ``` - -3. Install OpenZeppelin contracts: - - ```bash - forge install OpenZeppelin/openzeppelin-contracts - ``` - -## Configure Foundry - -Edit `foundry.toml`: - -```toml title="foundry.toml" -[profile.default] -src = "src" -out = "out" -libs = ["lib"] -remappings = ['@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/'] - -[rpc_endpoints] -polkadot_hub_testnet = "https://testnet-passet-hub-eth-rpc.polkadot.io" -``` - -## Create Your Contract - -Create `src/MyNFT.sol`: - -```solidity title="src/MyNFT.sol" -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract MyNFT is ERC721, Ownable { - uint256 private _nextTokenId; - - constructor(address initialOwner) - ERC721("MyToken", "MTK") - Ownable(initialOwner) - {} - - function safeMint(address to) public onlyOwner { - uint256 tokenId = _nextTokenId++; - _safeMint(to, tokenId); - } -} -``` - -## Compile - -```bash -forge build -``` - -Verify the compilation by inspecting the bytecode: - -```bash -forge inspect MyNFT bytecode -``` - -## Deploy - -Deploy to Polkadot Hub TestNet: - -```bash -forge create MyNFT \ - --rpc-url polkadot_hub_testnet \ - --private-key YOUR_PRIVATE_KEY \ - --constructor-args YOUR_OWNER_ADDRESS \ - --broadcast -``` - -Replace `YOUR_PRIVATE_KEY` with your private key and `YOUR_OWNER_ADDRESS` with the address that will own the NFT contract. - -## Where to Go Next - -
    - -- Guide __Verify Your Contract__ - - --- - - Now that you've deployed an NFT contract, learn how to verify it with Foundry. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/foundry/verify-a-contract/) - -- Guide __Deploy an ERC-20__ - - --- - - Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Foundry. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/foundry/) - -
    - - ---- - -Page Title: Deploy an NFT to Polkadot Hub with Hardhat - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/ -- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub with Hardhat, a comprehenive development environment with built-in deployment capabilities. - -# Deploy an NFT with Hardhat - -## Introduction - -Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. - -This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Hardhat](https://hardhat.org/docs/getting-started){target=\_blank}, a comprehensive development environment with built-in testing, debugging, and deployment capabilities. Hardhat uses standard Solidity compilation to generate EVM bytecode, making it fully compatible with Polkadot Hub's EVM environment. - -## Prerequisites - -- Basic understanding of Solidity programming and NFT standards. -- Node.js v22.13.1 or later. -- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -- A wallet with a private key for signing transactions. - -## Set Up Your Project - -Take the following steps to get started: - -1. Initialize your Hardhat project: - - ```bash - mkdir hardhat-nft-deployment - cd hardhat-nft-deployment - npx hardhat --init - ``` - -2. Install OpenZeppelin contracts: - - ```bash - npm install @openzeppelin/contracts - ``` - -## Configure Hardhat - -Edit `hardhat.config.ts`: - -```typescript title="hardhat.config.ts" -import type { HardhatUserConfig } from 'hardhat/config'; - -import hardhatToolboxViemPlugin from '@nomicfoundation/hardhat-toolbox-viem'; -import { configVariable } from 'hardhat/config'; - -const config: HardhatUserConfig = { - plugins: [hardhatToolboxViemPlugin], - solidity: { - profiles: { - default: { - version: '0.8.28', - }, - production: { - version: '0.8.28', - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - }, - }, - networks: { - hardhatMainnet: { - type: 'edr-simulated', - chainType: 'l1', - }, - hardhatOp: { - type: 'edr-simulated', - chainType: 'op', - }, - sepolia: { - type: 'http', - chainType: 'l1', - url: configVariable('SEPOLIA_RPC_URL'), - accounts: [configVariable('SEPOLIA_PRIVATE_KEY')], - }, - polkadotHubTestnet: { - type: 'http', - url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - accounts: [configVariable('PRIVATE_KEY')], - }, - }, -}; - -export default config; -``` - -!!! tip - Learn how to use Hardhat's [Config Variables](https://hardhat.org/docs/learn-more/configuration-variables){target=\_blank} to handle your private keys in a secure way. - -## Create Your Contract - -Create `contracts/MyNFT.sol`: - -```solidity title="contracts/MyNFT.sol" -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract MyNFT is ERC721, Ownable { - uint256 private _nextTokenId; - - constructor(address initialOwner) - ERC721("MyToken", "MTK") - Ownable(initialOwner) - {} - - function safeMint(address to) public onlyOwner { - uint256 tokenId = _nextTokenId++; - _safeMint(to, tokenId); - } -} -``` - -## Compile - -```bash -npx hardhat compile -``` - -## Set Up Deployment - -Create a deployment module in `ignition/modules/MyNFT.ts`: - -```typescript title="ignition/modules/MyNFT.ts" -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; - -export default buildModule('MyNFTModule', (m) => { - const initialOwner = m.getParameter('initialOwner', 'INSERT_OWNER_ADDRESS'); - const myNFT = m.contract('MyNFT', [initialOwner]); - return { myNFT }; -}); -``` - -Replace `INSERT_OWNER_ADDRESS` with your desired owner address. - -## Deploy - -Deploy to Polkadot Hub TestNet: - -```bash -npx hardhat ignition deploy ignition/modules/MyNFT.ts --network polkadotHubTestnet -``` - -## Where to Go Next - -
    - -- Guide __Verify Your Contract__ - - --- - - Now that you've deployed an NFT contract, learn how to verify it with Hardhat. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/verify-a-contract/) - - -- Guide __Deploy an ERC-20__ - - --- - - Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Hardhat. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/hardhat/) - -
    - - ---- - -Page Title: Deploy an NFT to Polkadot Hub with Remix - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/ -- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Remix, a browser-based IDE for quick prototyping and learning. - -# Deploy an NFT with Remix - -## Introduction - -Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. - -This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Remix](https://remix.ethereum.org/){target=\_blank}, a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development. - -## Prerequisites - -- Basic understanding of Solidity programming and NFT standards. -- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank} -- A wallet with a private key for signing transactions. - -## Access Remix - -Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. - -The interface will load with a default workspace containing sample contracts. In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. - -## Create Your Contract - -1. Create a new file `contracts/MyNFT.sol`. -2. Paste the following code: - - ```solidity title="contracts/MyNFT.sol" - // SPDX-License-Identifier: MIT - pragma solidity ^0.8.20; - - import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; - import "@openzeppelin/contracts/access/Ownable.sol"; - - contract MyNFT is ERC721, Ownable { - uint256 private _nextTokenId; - - constructor(address initialOwner) - ERC721("MyToken", "MTK") - Ownable(initialOwner) - {} - - function safeMint(address to) public onlyOwner { - uint256 tokenId = _nextTokenId++; - _safeMint(to, tokenId); - } - } - ``` - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-01.webp) - -## Compile - -1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). -2. Click **Compile MyNFT.sol** or press `Ctrl+S`. - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-02.webp) - -Compilation errors and warnings appear in the terminal panel at the bottom of the screen. - -## Deploy - -1. Navigate to the **Deploy & Run Transactions** tab. -2. Click the **Environment** dropdown, select **Browser Extension**, and click on **Injected Provider - MetaMask**. - - ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-03.webp) - -3. In the deploy section, enter the initial owner address in the constructor parameter field. -4. Click **Deploy**. - - ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-04.webp) - -5. Approve the transaction in your MetaMask wallet. - -Your deployed contract will appear in the **Deployed Contracts** section, ready for interaction. - -## Where to Go Next - -
    - -- Guide __Verify Your Contract__ - - --- - - Now that you've deployed an NFT contract, learn how to verify it with Remix. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/verify-a-contract/) - -- Guide __Deploy an ERC-20__ - - --- - - Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Remix. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) - -
    - - ---- - -Page Title: Deploying Uniswap V2 on Polkadot - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/ -- Summary: Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. - -# Deploy Uniswap V2 - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Decentralized exchanges (DEXs) are a cornerstone of the DeFi ecosystem, allowing for permissionless token swaps without intermediaries. [Uniswap V2](https://docs.uniswap.org/contracts/v2/overview){target=\_blank}, with its Automated Market Maker (AMM) model, revolutionized DEXs by enabling liquidity provision for any ERC-20 token pair. - -This tutorial will guide you through how Uniswap V2 works so you can take advantage of it in your projects deployed to Polkadot Hub. By understanding these contracts, you'll gain hands-on experience with one of the most influential DeFi protocols and understand how it functions across blockchain ecosystems. - -## Prerequisites - -Before starting, make sure you have: - -- Node.js (v16.0.0 or later) and npm installed. -- Basic understanding of Solidity and JavaScript. -- Familiarity with [`hardhat-polkadot`](/smart-contracts/dev-environments/hardhat/get-started/){target=\_blank} development environment. -- Some PAS test tokens to cover transaction fees (obtained from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}). -- Basic understanding of how AMMs and liquidity pools work. - -## Set Up the Project - -Let's start by cloning the Uniswap V2 project: - -1. Clone the Uniswap V2 repository: - - ``` - git clone https://github.com/polkadot-developers/polkavm-hardhat-examples.git -b v0.0.6 - cd polkavm-hardhat-examples/uniswap-v2-polkadot/ - ``` - -2. Install the required dependencies: - - ```bash - npm install - ``` - -3. Update the `hardhat.config.js` file so the paths for the Substrate node and the ETH-RPC adapter match with the paths on your machine. For more info, check the [Testing your Contract](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} section in the Hardhat guide. - - ```js title="hardhat.config.js" - hardhat: { - polkavm: true, - nodeConfig: { - nodeBinaryPath: '../bin/substrate-node', - rpcPort: 8000, - dev: true, - }, - adapterConfig: { - adapterBinaryPath: '../bin/eth-rpc', - dev: true, - }, - }, - ``` - -4. Create a `.env` file in your project root to store your private keys (you can use as an example the `env.example` file): - - ```text title=".env" - LOCAL_PRIV_KEY="INSERT_LOCAL_PRIVATE_KEY" - AH_PRIV_KEY="INSERT_AH_PRIVATE_KEY" - ``` - - Ensure to replace `"INSERT_LOCAL_PRIVATE_KEY"` with a private key available in the local environment (you can get them from this [file](https://github.com/paritytech/hardhat-polkadot/blob/main/packages/hardhat-polkadot-node/src/constants.ts#L22){target=\_blank}). And `"INSERT_AH_PRIVATE_KEY"` with the account's private key you want to use to deploy the contracts. You can get this by exporting the private key from your wallet (e.g., MetaMask). - - !!!warning - Keep your private key safe, and never share it with anyone. If it is compromised, your funds can be stolen. - -5. Compile the contracts: - - ```bash - npx hardhat compile - ``` - -If the compilation is successful, you should see the following output: - -
    - npx hardhat compile - Compiling 12 Solidity files - Successfully compiled 12 Solidity files -
    - -After running the above command, you should see the compiled contracts in the `artifacts-pvm` directory. This directory contains the ABI and bytecode of your contracts. - -## Understanding Uniswap V2 Architecture - -Before interacting with the contracts, it's essential to understand the core architecture that powers Uniswap V2. This model forms the basis of nearly every modern DEX implementation and operates under automated market making, token pair liquidity pools, and deterministic pricing principles. - -At the heart of Uniswap V2 lies a simple but powerful system composed of two major smart contracts: - -- **Factory contract**: The factory acts as a registry and creator of new trading pairs. When two ERC-20 tokens are to be traded, the Factory contract is responsible for generating a new Pair contract that will manage that specific token pair’s liquidity pool. It keeps track of all deployed pairs and ensures uniqueness—no duplicate pools can exist for the same token combination. -- **Pair contract**: Each pair contract is a decentralized liquidity pool that holds reserves of two ERC-20 tokens. These contracts implement the core logic of the AMM, maintaining a constant product invariant (x \* y = k) to facilitate swaps and price determination. Users can contribute tokens to these pools in return for LP (liquidity provider) tokens, which represent their proportional share of the reserves. - -This minimal architecture enables Uniswap to be highly modular, trustless, and extensible. By distributing responsibilities across these components, developers, and users can engage with the protocol in a composable and predictable manner, making it an ideal foundation for DEX functionality across ecosystems, including Polkadot Hub. - -The project scaffolding is as follows: - -```bash -uniswap-V2-polkadot -├── bin/ -├── contracts/ -│ ├── interfaces/ -│ │ ├── IERC20.sol -│ │ ├── IUniswapV2Callee.sol -│ │ ├── IUniswapV2ERC20.sol -│ │ ├── IUniswapV2Factory.sol -│ │ └── IUniswapV2Pair.sol -│ ├── libraries/ -│ │ ├── Math.sol -│ │ ├── SafeMath.sol -│ │ └── UQ112x112.sol -│ ├── test/ -│ │ └── ERC20.sol -│ ├── UniswapV2ERC20.sol -│ ├── UniswapV2Factory.sol -│ └── UniswapV2Pair.sol -├── ignition/ -├── scripts/ -│ └── deploy.js -├── node_modules/ -├── test/ -│ ├── shared/ -│ │ ├── fixtures.js -│ │ └── utilities.js -│ ├── UniswapV2ERC20.js -│ ├── UniswapV2Factory.js -│ └── UniswapV2Pair.js -├── .env.example -├── .gitignore -├── hardhat.config.js -├── package.json -└── README.md -``` - -## Test the Contracts - -You can run the provided test suite to ensure the contracts are working as expected. The tests cover various scenarios, including creating pairs, adding liquidity, and executing swaps. - -To test it locally, you can run the following commands: - -1. Spawn a local node for testing: - - ```bash - npx hardhat node - ``` - - This command will spawn a local Substrate node along with the ETH-RPC adapter. The node will be available at `ws://127.0.0.1:8000` and the ETH-RPC adapter at `http://localhost:8545`. - -2. In a new terminal, run the tests: - - ```bash - npx hardhat test --network localNode - ``` - -The result should look like this: - -
    - npx hardhat test --network localNode - Compiling 12 Solidity files - Successfully compiled 12 Solidity files - - UniswapV2ERC20 - ✔ name, symbol, decimals, totalSupply, balanceOf, DOMAIN_SEPARATOR, PERMIT_TYPEHASH (44ms) - ✔ approve (5128ms) - ✔ transfer (5133ms) - ✔ transfer:fail - ✔ transferFrom (6270ms) - ✔ transferFrom:max (6306ms) - - UniswapV2Factory - ✔ feeTo, feeToSetter, allPairsLength - ✔ createPair (176ms) - ✔ createPair:reverse (1224ms) - ✔ setFeeTo (1138ms) - ✔ setFeeToSetter (1125ms) - - UniswapV2Pair - ✔ mint (11425ms) - ✔ getInputPrice:0 (12590ms) - ✔ getInputPrice:1 (17600ms) - ✔ getInputPrice:2 (17618ms) - ✔ getInputPrice:3 (17704ms) - ✔ getInputPrice:4 (17649ms) - ✔ getInputPrice:5 (17594ms) - ✔ getInputPrice:6 (13643ms) - ✔ optimistic:0 (17647ms) - ✔ optimistic:1 (17946ms) - ✔ optimistic:2 (17657ms) - ✔ optimistic:3 (21625ms) - ✔ swap:token0 (12665ms) - ✔ swap:token1 (17631ms) - ✔ burn (17690ms) - ✔ feeTo:off (23900ms) - ✔ feeTo:on (24991ms) - - 28 passing (12m) -
    - -## Deploy the Contracts - -After successfully testing the contracts, you can deploy them to the local node or Polkadot Hub. The deployment script is located in the `scripts` directory and is named `deploy.js`. This script deploys the `Factory` and `Pair` contracts to the network. - -To deploy the contracts, run the following command: - -```bash -npx hardhat run scripts/deploy.js --network localNode -``` - -This command deploys the contracts to your local blockchain for development and testing. If you want to deploy to Polkadot Hub, you can use the following command: - -```bash -npx hardhat run scripts/deploy.js --network passetHub -``` - -The command above deploys to the actual Polkadot TestNet. It requires PAS test tokens, persists on the network, and operates under real network conditions. - -The deployment script will output the addresses of the deployed contracts. Save these addresses, as you will need them to interact with the contracts. For example, the output should look like this: - -
    - npx hardhat run scripts/deploy.js --network localNode - Successfully compiled 12 Solidity files - Deploying contracts using 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac - Deploying UniswapV2ERC20... - ETH deployed to : 0x7acc1aC65892CF3547b1b0590066FB93199b430D - Deploying UniswapV2Factory... - Factory deployed to : 0x85b108660f47caDfAB9e0503104C08C1c96e0DA9 - Deploying UniswapV2Pair with JsonRpcProvider workaround... - Pair deployed to : 0xF0e46847c8bFD122C4b5EEE1D4494FF7C5FC5104 -
    - -## Conclusion - -This tutorial guided you through deploying Uniswap V2 contracts to Polkadot Hub. This implementation brings the powerful AMM architecture to the Polkadot ecosystem, laying the foundation for the decentralized trading of ERC-20 token pairs. - -By following this guide, you've gained practical experience with: - -- Setting up a Hardhat project for deploying to Polkadot Hub. -- Understanding the Uniswap V2 architecture. -- Testing Uniswap V2 contracts in a local environment. -- Deploying contracts to both local and testnet environments. - -To build on this foundation, you could extend this project by implementing functionality to create liquidity pools, execute token swaps, and build a user interface for interacting with your deployment. - -This knowledge can be leveraged to build more complex DeFi applications or to integrate Uniswap V2 functionality into your existing projects on Polkadot. - - ---- - -Page Title: Dual Virtual Machine Stack - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/ -- Summary: Compare Polkadot’s dual smart contract VMs—REVM for EVM compatibility and PolkaVM for RISC-V performance, flexibility, and efficiency. - -# Dual Virtual Machine Stack - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot's smart contract platform supports two distinct virtual machine (VM) architectures, providing developers with flexibility in selecting the optimal execution backend for their specific needs. This approach strikes a balance between immediate Ethereum compatibility and long-term innovation, enabling developers to deploy either unmodified (Ethereum Virtual Machine) EVM contracts using Rust Ethereum Virtual Machine (REVM) or optimize for higher performance using PolkaVM (PVM). - -Both VM options share common infrastructure, including RPC interfaces, tooling support, and precompiles. The following sections compare architectures and guide you in selecting the best VM for your project's needs. - -## Migrate from EVM - -The [REVM backend](https://github.com/bluealloy/revm){target=\_blank} integrates a complete Rust implementation of the EVM, enabling Solidity contracts to run unchanged on Polkadot's smart contract platform. - -REVM allows developers to use their existing Ethereum tooling and infrastructure to build on Polkadot. Choose REVM to: - -- Migrate existing Ethereum contracts without modifications. -- Retain exact EVM behavior for audit tools. -- Use developer tools that rely upon inspecting EVM bytecode. -- Prioritize rapid deployment over optimization. -- Work with established Ethereum infrastructure and tooling to build on Polkadot. - -REVM enables Ethereum developers to seamlessly migrate to Polkadot, achieving performance and fee improvements without modifying their existing contracts or developer tooling stack. - -## Upgrade to PolkaVM - -[**PolkaVM**](https://github.com/paritytech/polkavm){target=\_blank} is a custom virtual machine optimized for performance with [RISC-V-based](https://en.wikipedia.org/wiki/RISC-V){target=\_blank} architecture, supporting Solidity and additional high-performance languages. It serves as the core execution environment, integrated directly within the runtime. Choose the PolkaVM for: - -- An efficient interpreter for immediate code execution. -- A planned [Just In Time (JIT)](https://en.wikipedia.org/wiki/Just-in-time_compilation){target=\_blank} compiler for optimized performance. -- Dual-mode execution capability, allowing selection of the most appropriate backend for specific workloads. -- Optimized performance for short-running contract calls through the interpreter. - -The interpreter remains particularly beneficial for contracts with minimal code execution, as it enables immediate code execution through lazy interpretation. - -## Architecture - -The following key components of PolkaVM work together to enable Ethereum compatibility on Polkadot-based chains. - -### Revive Pallet - -[**`pallet_revive`**](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/index.html){target=\_blank} is a runtime module that executes smart contracts by adding extrinsics, runtime APIs, and logic to convert Ethereum-style transactions into formats compatible with Polkadot SDK-based blockchains. It processes Ethereum-style transactions through the following workflow: - -```mermaid -sequenceDiagram - participant User as User/dApp - participant Proxy as Ethereum JSON RPC Proxy - participant Chain as Blockchain Node - participant Pallet as pallet_revive - - User->>Proxy: Submit Ethereum Transaction - Proxy->>Chain: Repackage as Polkadot Compatible Transaction - Chain->>Pallet: Process Transaction - Pallet->>Pallet: Decode Ethereum Transaction - Pallet->>Pallet: Execute Contract via PolkaVM - Pallet->>Chain: Return Results - Chain->>Proxy: Forward Results - Proxy->>User: Return Ethereum-compatible Response -``` - -This proxy-based approach eliminates the need for node binary modifications, maintaining compatibility across different client implementations. Preserving the original Ethereum transaction payload simplifies the adaptation of existing tools, which can continue processing familiar transaction formats. - -### PolkaVM Design Fundamentals - -PolkaVM differs from the EVM in two key ways that make it faster, more hardware-efficient, and easier to extend: - -- **Register-based design**: Instead of a stack machine, PolkaVM uses a RISC-V–style register model. This design: - - - Uses a fixed set of registers to pass arguments, not an infinite stack. - - Maps cleanly to real hardware like x86-64. - - Simplifies compilation and boosts runtime efficiency. - - Enables tighter control over register allocation and performance tuning. - -- **64-bit word size**: PolkaVM runs on a native 64-bit word size, aligning directly with modern CPUs. This design: - - - Executes arithmetic operations with direct hardware support. - - Maintains compatibility with Solidity’s 256-bit types via YUL translation. - - Accelerates computation-heavy workloads through native word alignment. - - Integrates easily with low-level, performance-focused components. - -## Where To Go Next - -
    - -- Learn __Contract Deployment__ - - --- - - Learn how REVM and PVM compare for compiling and deploying smart contracts. - - [:octicons-arrow-right-24: Reference](/smart-contracts/for-eth-devs/contract-deployment/) - -
    - - ---- - -Page Title: Get Started with Parachain Development - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/get-started/ -- Summary: Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. - -# Get Started - -The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. - -## Quick Start Guides - -Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. - -| Tutorial | Tools | Description | -| :--------------------------------------------------------------------------------------------: | :----------------------------: | :---------------------------------------------------------------------: | -| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | Learn how to set up and run the Polkadot SDK Parachain Template locally | -| [Launch a Local Parachain](/parachains/testing/run-a-parachain-network/) | Zombienet, Chopsticks | Set up a local development environment for testing | -| [Connect to Polkadot](/chain-interactions/query-on-chain-data/query-sdks/) | Polkadot.js, Substrate Connect | Connect your application to Polkadot networks | -| [Fork an Existing Parachain](/parachains/testing/fork-a-parachain/) | Chopsticks | Create a local fork of a live parachain for testing | - -## Launch a Simple Parachain - -Learn the fundamentals of launching and deploying a parachain to the Polkadot network. - -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------: | -| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | -| [Deploy to Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/) | Step-by-step tutorial to deploying your parachain to Polkadot | -| [Obtain Coretime](/parachains/launch-a-parachain/obtain-coretime/) | Learn how to acquire blockspace using Polkadot's coretime model (RegionX) | - -## Customize Your Runtime - -Build custom functionality for your parachain by composing and creating pallets. - -| Tutorial | Description | -| :-------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------: | -| [Add Existing Pallets to the Runtime](/parachains/customize-runtime/add-existing-pallets/) | Integrate pre-built pallets from the FRAME ecosystem | -| [Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/) | Configure and use multiple instances of the same pallet | -| [Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/) | Enable smart contract capabilities using Contracts or EVM pallets | - -### Pallet Development - -Deep dive into creating and managing custom pallets for your parachain. - -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------: | -| [Create a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/) | Build a pallet from scratch with custom logic | -| [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/) | Set up a mock runtime environment for testing | -| [Pallet Unit Testing](/parachains/customize-runtime/pallet-development/pallet-testing/) | Write comprehensive tests for your pallet logic | -| [Add Your Custom Pallet to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/) | Integrate your custom pallet into your parachain runtime | -| [Benchmark the Custom Pallet](/parachains/customize-runtime/pallet-development/benchmark-pallet/) | Measure and optimize pallet performance with benchmarking | - -## Testing - -Test your parachain in various environments before production deployment. - -| Tutorial | Description | -| :---------------------------------------------------------------------: | :-----------------------------------------------------: | -| [Fork a Parachain](/parachains/testing/fork-a-parachain/) | Use Chopsticks to create a local fork for testing | -| [Run a Parachain Network](/parachains/testing/run-a-parachain-network/) | Launch a complete parachain test network with Zombienet | - -## Runtime Upgrades and Maintenance - -Manage your parachain's lifecycle with forkless upgrades and maintenance operations. - -| Tutorial | Description | -| :-----------------------------------------------------------------------: | :--------------------------------------------------: | -| [Runtime Upgrades](/parachains/runtime-maintenance/runtime-upgrades/) | Perform forkless runtime upgrades via governance | -| [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/) | Safely migrate storage when updating runtime logic | -| [Unlock Parachains](/parachains/runtime-maintenance/unlock-parachains/) | Understand parachain lifecycle and unlock mechanisms | - -## Interoperability - -Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). - -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: | -| [Open HRMP Channels Between Parachains](/parachains/interoperability/channels-between-parachains/) | Establish communication channels with other parachains | -| [Open HRMP Channels with System Parachains](/parachains/interoperability/channels-with-system-parachains/) | Connect with Asset Hub and other system parachains | - -## Integrations - -Integrate your parachain with essential ecosystem tools and services. - -| Tutorial | Description | -| :--------------------------------------------: | :----------------------------------------------------: | -| [Wallets](/parachains/integrations/wallets/) | Integrate wallet support for user interactions | -| [Indexers](/parachains/integrations/indexers/) | Set up indexing solutions for querying blockchain data | -| [Oracles](/parachains/integrations/oracles/) | Connect your parachain to off-chain data sources | - -## Additional Resources - -- [Polkadot SDK Documentation](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/index.html) -- [Polkadot Wiki - Parachains](https://wiki.polkadot.network/docs/learn-parachains/) - - ---- - -Page Title: Get Started with Smart Contracts - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/get-started/ -- Summary: Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. - -# Get Started - -This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need. - -## Quick Starts - -Kick off development fast with curated links for connecting, funding, exploring, and deploying your first contract. - -| Quick Start | Tools | Description | -|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:| -| [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer | -| [Get Test Tokens](/smart-contracts/faucets/){target=\_blank} | - | Request test funds to deploy and interact with contracts | -| [Explore Transactions](/smart-contracts/explorers/){target=\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state | -| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} | Remix | One‑click browser deployment to Polkadot Hub | -| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\_blank} | Foundry | Scripted deployments and testing from the CLI | -| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} | Hardhat | Project scaffolding, testing, and deployments | - -## Build and Test Locally - -Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. - -| Build and Test Locally | Tools | Description | -|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:| -| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\_blank} | Polkadot SDK node | Spin up a local node for iterative development | -| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts | -| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\_blank} | Remix | Publish verified source on explorers | -| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\_blank} | Foundry | Install toolchain and configure networks | -| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\_blank} | Foundry | Write and run Solidity tests locally | -| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\_blank} | Foundry | Verify deployed bytecode and metadata | -| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} | Hardhat | Initialize a project and configure networks | -| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} | Hardhat | Unit test contracts and run scripts | -| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\_blank} | Hardhat | Verify deployments on explorers | - -## Ethereum Developer Resources - -Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. - -| Ethereum Developer Guides | Description | -|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:| -| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts | -| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\_blank} | Transaction types, fees, and multi‑dimensional metering | -| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} | Gas vs. weight, proof size, and storage deposits | -| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\_blank} | Deployment patterns and best practices on Polkadot Hub | -| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank} | Supported Ethereum JSON‑RPC methods and examples | -| [Migration](/smart-contracts/for-eth-devs/migration/){target=\_blank} | Port existing apps and tooling to Polkadot Hub | -| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} | Overview of EVM and native execution on the Hub | - -## Cookbook: Hands‑on Tutorials - -Follow step‑by‑step guides that walk through common tasks and complete dApp examples. - -| Tutorial | Tools | Description | -|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:| -| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} | Remix | Minimal deployment walkthrough | -| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token | -| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection | -| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\_blank} | Hardhat | Full dApp project: compile, test, deploy | -| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\_blank} | Multiple | End‑to‑end dApp patterns and practices | - -## Libraries - -Choose the client libraries that fit your stack for connecting wallets and calling contracts. - -| Library | Description | -|:------------------------------------------------------------------:|:-------------------------------------------------------:| -| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank} | Connect, sign, and interact with contracts using Ethers | -| [viem](/smart-contracts/libraries/viem/){target=\_blank} | Type‑safe EVM interactions and utilities | -| [Wagmi](/smart-contracts/libraries/wagmi/){target=\_blank} | React hooks for wallet connections and contract calls | -| [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank} | Web3 provider and contract APIs | -| [Web3.py](/smart-contracts/libraries/web3-py/){target=\_blank} | Python toolkit for on‑chain interactions and scripts | - -## Integrations - -Integrate essential services like wallets, indexers, and oracles to round out your dApp. - -| Integration | Description | -|:-------------------------------------------------------------------:|:-----------------------------------------:| -| [Wallets](/smart-contracts/integrations/wallets/){target=\_blank} | Supported wallets and configuration notes | -| [Indexers](/smart-contracts/integrations/indexers/){target=\_blank} | Index and query blockchain data | -| [Oracles](/smart-contracts/integrations/oracles/){target=\_blank} | Bring external data on‑chain | - -## Precompiles - -Discover precompiled system contracts available on the Hub and how to use them. - -| Topic | Description | -|:------------------------------------------------------------------------:|:---------------------------------------------------:| -| [Overview of Precompiles](/smart-contracts/precompiles/){target=\_blank} | What precompiles are available on the Hub | -| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\_blank} | EVM precompiles and interfaces | -| [Staking](/smart-contracts/precompiles/staking/){target=\_blank} | Interact with staking functionality via precompiles | -| [XCM](/smart-contracts/precompiles/xcm/){target=\_blank} | Cross‑chain messaging helpers for contracts | - -From here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\_blank} or reach out in the community channels. - - ---- - -Page Title: Glossary - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md -- Canonical (HTML): https://docs.polkadot.com/reference/glossary/ -- Summary: Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. - -# Glossary - -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. - -Additional glossaries from around the ecosystem you might find helpful: - -- [Polkadot Wiki Glossary](https://wiki.polkadot.com/general/glossary){target=\_blank} -- [Polkadot SDK Glossary](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/glossary/index.html){target=\_blank} - -## Authority - -The role in a blockchain that can participate in consensus mechanisms. - -- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final. -- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author). - -Authority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol. - -## Authority Round (Aura) - -A deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol. - -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. - -## Blind Assignment of Blockchain Extension (BABE) - -A [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block. - -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. - -## Block Author - -The node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_. - -## Byzantine Fault Tolerance (BFT) - -The ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack. - -### Byzantine Failure - -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. - -### Practical Byzantine Fault Tolerance (pBFT) - -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. - -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. - -### Preimage - -A preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\_blank}, the output, the hash, cannot be used to reveal the input, the preimage. - -## Call - -In the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object. - -## Chain Specification - -A chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains. - -## Collator - -An [author](#block-author) of a [parachain](#parachain) network. -They aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus). - -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. - -## Collective - -Most often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network. - -## Consensus - -Consensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship. - -See also [hybrid consensus](#hybrid-consensus). - -## Consensus Algorithm - -Ensures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft). - -Consensus algorithms are generally concerned with ensuring two properties: - -- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. -- **Liveness**: Indicating the ability of the chain to keep progressing. - -## Consensus Engine - -The node subsystem responsible for consensus tasks. - -For detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} blog series. - -See also [hybrid consensus](#hybrid-consensus). - -## Coretime - -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. - -On-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety. - -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank}. - -## Development Phrase - -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. - -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: - -``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk -``` - -Many tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`. - -## Digest - -An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: - -- [Light clients](#light-client) for chain synchronization. -- Consensus engines for block verification. -- The runtime itself, in the case of pre-runtime digests. - -## Dispatchable - -Function objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations. - -## Events - -A means of recording that some particular [state](#state) transition happened. - -In the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization. - -## Executor - -A means of executing a function call in a given [runtime](#runtime) with a set of dependencies. -There are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_. - -- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes. - -- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain. - -## Existential Deposit - -The minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. - -If an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\_blank} to drop its references to that account. - -If the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\_blank}. - -## Extrinsic - -A general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder. - -It is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). - -For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. - -## Fork Choice Rule/Strategy - -A fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\_blank}, in which the chain with the most blocks is selected. - -## FRAME (Framework for Runtime Aggregation of Modularized Entities) - -Enables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes. - -[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank} - -## Full Node - -A node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization. - -## Genesis Configuration - -A mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file. - -## GRANDPA - -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. - -The [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\_blank}. - -## Header - -A structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization. - -## Hybrid Consensus - -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. - -Hybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa). - -## Inherent Transactions - -A special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block. - -Only the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified. - -## JSON-RPC - -A stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON. - -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. - -## Keystore - -A subsystem for managing keys for the purpose of producing new blocks. - -## Kusama - -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. - -Kusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\_blank} network and is referred to as [Polkadot's "wild cousin."](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\_blank}. - -As a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation. - -## libp2p - -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). - -Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. - -## Light Client - -A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. - -A light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\_blank} server, enabling blockchain users to interact with the network. - -## Metadata - -Data that provides information about one or more aspects of a system. -The metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system. - -## Nominated Proof of Stake (NPoS) - -A method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes. - -## Oracle - -An entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services. - -## Origin - -A [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\_blank}. - -## Pallet - -A module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime). -Pallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item). - -## Parachain - -A parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_. -You can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\_blank}. - -## Paseo - -Paseo TestNet provisions testing on Polkadot's "production" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing. - -## Polkadot - -The [Polkadot network](https://polkadot.com/){target=\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain). - -## Polkadot Cloud - -Polkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance. - -## Polkadot Hub - -Polkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3. - -## PolkaVM - -PolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution. - -## Relay Chain - -Relay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another. - -## Rococo - -A [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead. - -## Runtime - -The runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function. - -## Slot - -A fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block. - -## Sovereign Account - -The unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem. - -The sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier. - -## SS58 Address Format - -A public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain - -The [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks - -## State Transition Function (STF) - -The logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime). - -## Storage Item - -[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime). -Learn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\_blank} reference document in the Polkadot SDK. - -## Substrate - -A flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\_blank}. - -## Transaction - -An [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}. - -## Transaction Era - -A definable period expressed as a range of block numbers during which a transaction can be included in a block. -Transaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero. - -## Trie (Patricia Merkle Tree) - -A data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set. - -In Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays. - -## Validator - -A validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance. - -## WebAssembly (Wasm) - -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. - -[Wasm](https://webassembly.org/){target=\_blank} can be compiled from many languages, including -the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state. - -## Weight - -A convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block. -Polkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware. - -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: - -- Block construction -- Network propagation -- Import and verification - -By defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements. - -## Westend - -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. - - ---- - -Page Title: Indexers - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md -- Canonical (HTML): https://docs.polkadot.com/parachains/integrations/indexers/ -- Summary: Discover blockchain indexers. Enhance data access, enable fast and complex queries, and optimize blockchain data for seamless app performance. - -# Indexers - -## The Challenge of Blockchain Data Access - -Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges: - -- Data is scattered and unorganized across the blockchain. -- Retrieving large datasets can take days or weeks to sync. -- Complex operations (like aggregations, averages, or cross-chain queries) require additional processing. -- Direct blockchain queries can impact dApp performance and responsiveness. - -## What is a Blockchain Indexer? - -A blockchain indexer is a specialized infrastructure tool that processes, organizes, and stores blockchain data in an optimized format for efficient querying. Think of it as a search engine for blockchain data that: - -- Continuously monitors the blockchain for new blocks and transactions. -- Processes and categorizes this data according to predefined schemas. -- Stores the processed data in an easily queryable database. -- Provides efficient APIs (typically [GraphQL](https://graphql.org/){target=\_blank}) for data retrieval. - -## Indexer Implementations - -
    - -- __Subsquid__ - - --- - - Subsquid is a data network that allows rapid and cost-efficient retrieval of blockchain data from 100+ chains using Subsquid's decentralized data lake and open-source SDK. In simple terms, Subsquid can be considered an ETL (extract, transform, and load) tool with a GraphQL server included. It enables comprehensive filtering, pagination, and even full-text search capabilities. Subsquid has native and full support for EVM and Substrate data, even within the same project. - - [:octicons-arrow-right-24: Reference](https://www.sqd.ai/){target=\_blank} - -- __Subquery__ - - --- - - SubQuery is a fast, flexible, and reliable open-source data decentralised infrastructure network that provides both RPC and indexed data to consumers worldwide. - It provides custom APIs for your web3 project across multiple supported chains. - - [:octicons-arrow-right-24: Reference](https://subquery.network/){target=\_blank} - -
    - - ---- - -Page Title: Install Polkadot SDK - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md -- Canonical (HTML): https://docs.polkadot.com/parachains/install-polkadot-sdk/ -- Summary: Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. - -# Install Polkadot SDK - -This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts: - -- **Installing dependencies**: Setting up Rust, required system packages, and development tools. -- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. - -Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. - -## Install Dependencies: macOS - -You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. - -### Before You Begin {: #before-you-begin-mac-os } - -Before you install Rust and set up your development environment on macOS, verify that your computer meets the following basic requirements: - -- Operating system version is 10.7 Lion or later. -- Processor speed of at least 2 GHz. Note that 3 GHz is recommended. -- Memory of at least 8 GB RAM. Note that 16 GB is recommended. -- Storage of at least 10 GB of available space. -- Broadband Internet connection. - -### Install Homebrew - -In most cases, you should use Homebrew to install and manage packages on macOS computers. If you don't already have Homebrew installed on your local computer, you should download and install it before continuing. - -To install Homebrew: - -1. Open the Terminal application. -2. Download and install Homebrew by running the following command: - - ```bash - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - ``` - -3. Verify Homebrew has been successfully installed by running the following command: - - ```bash - brew --version - ``` - - The command displays output similar to the following: - -
    - brew --version - Homebrew 4.3.15 -
    - -### Support for Apple Silicon - -Protobuf must be installed before the build process can begin. To install it, run the following command: - -```bash -brew install protobuf -``` - -### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } - -Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `openssl`. - -To install `openssl` and the Rust toolchain on macOS: - -1. Open the Terminal application. -2. Ensure you have an updated version of Homebrew by running the following command: - - ```bash - brew update - ``` - -3. Install the `openssl` package by running the following command: - - ```bash - brew install openssl - ``` - -4. Download the `rustup` installation program and use it to install Rust by running the following command: - - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -5. Follow the prompts displayed to proceed with a default installation. -6. Update your current shell to include Cargo by running the following command: - - ```bash - source ~/.cargo/env - ``` - -7. Configure the Rust toolchain to default to the latest stable version by running the following commands: - - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` - -8. Install `cmake` using the following command: - - ```bash - brew install cmake - ``` - -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - -## Install Dependencies: Linux - -Rust supports most Linux distributions. Depending on the specific distribution and version of the operating system you use, you might need to add some software dependencies to your environment. In general, your development environment should include a linker or a C-compatible compiler, such as `clang`, and an appropriate integrated development environment (IDE). - -### Before You Begin {: #before-you-begin-linux } - -Check the documentation for your operating system for information about the installed packages and how to download and install any additional packages you might need. For example, if you use Ubuntu, you can use the Ubuntu Advanced Packaging Tool (`apt`) to install the `build-essential` package: - -```bash -sudo apt install build-essential -``` - -At a minimum, you need the following packages before you install Rust: - -```text -clang curl git make -``` - -Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `libssl-dev` or `openssl-devel`. - -### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } - -To install the Rust toolchain on Linux: - -1. Open a terminal shell. -2. Check the packages installed on the local computer by running the appropriate package management command for your Linux distribution. -3. Add any package dependencies you are missing to your local development environment by running the appropriate package management command for your Linux distribution: - - === "Ubuntu" - - ```bash - sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler - ``` - - === "Debian" - - ```sh - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` - - === "Arch" - - ```sh - pacman -Syu --needed --noconfirm curl git clang make protobuf - ``` - - === "Fedora" - - ```sh - sudo dnf update - sudo dnf install clang curl git openssl-devel make protobuf-compiler - ``` - - === "OpenSUSE" - - ```sh - sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf - ``` - - Remember that different distributions might use different package managers and bundle packages in different ways. For example, depending on your installation selections, Ubuntu Desktop and Ubuntu Server might have different packages and different requirements. However, the packages listed in the command-line examples are applicable to many common Linux distributions, including Debian, Linux Mint, MX Linux, and Elementary OS. - -4. Download the `rustup` installation program and use it to install Rust by running the following command: - - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -5. Follow the prompts displayed to proceed with a default installation. -6. Update your current shell to include Cargo by running the following command: - - ```bash - source $HOME/.cargo/env - ``` - -7. Verify your installation by running the following command: - - ```bash - rustc --version - ``` - -8. Configure the Rust toolchain to default to the latest stable version by running the following commands: - - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` - -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - -## Install Dependencies: Windows (WSL) - -In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. - -However, suppose your local computer uses Microsoft Windows instead of a UNIX-based operating system. In that case, you can configure it with additional software to make it a suitable development environment for building Substrate-based blockchains. To prepare a development environment on a Microsoft Windows computer, you can use Windows Subsystem for Linux (WSL) to emulate a UNIX operating environment. - -### Before You Begin {: #before-you-begin-windows-wls } - -Before installing on Microsoft Windows, verify the following basic requirements: - -- You have a computer running a supported Microsoft Windows operating system: - - **For Windows desktop**: You must be running Microsoft Windows 10, version 2004 or later, or Microsoft Windows 11 to install WSL. - - **For Windows server**: You must be running Microsoft Windows Server 2019, or later, to install WSL on a server operating system. -- You have a good internet connection and access to a shell terminal on your local computer. - -### Set Up Windows Subsystem for Linux - -WSL enables you to emulate a Linux environment on a computer that uses the Windows operating system. The primary advantage of this approach for Substrate development is that you can use all of the code and command-line examples as described in the Substrate documentation. For example, you can run common commands—such as `ls` and `ps`—unmodified. By using WSL, you can avoid configuring a virtual machine image or a dual-boot operating system. - -To prepare a development environment using WSL: - -1. Check your Windows version and build number to see if WSL is enabled by default. - - If you have Microsoft Windows 10, version 2004 (Build 19041 and higher), or Microsoft Windows 11, WSL is available by default and you can continue to the next step. - - If you have an older version of Microsoft Windows installed, see the [WSL manual installation steps for older versions](https://learn.microsoft.com/en-us/windows/wsl/install-manual){target=\_blank}. If you are installing on an older version of Microsoft Windows, you can download and install WLS 2 if your computer has Windows 10, version 1903 or higher. - -2. Select **Windows PowerShell** or **Command Prompt** from the **Start** menu, right-click, then **Run as administrator**. - -3. In the PowerShell or Command Prompt terminal, run the following command: - - ```bash - wsl --install - ``` - - This command enables the required WSL 2 components that are part of the Windows operating system, downloads the latest Linux kernel, and installs the Ubuntu Linux distribution by default. - - If you want to review the other Linux distributions available, run the following command: - - ```bash - wsl --list --online - ``` - -4. After the distribution is downloaded, close the terminal. - -5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. - - Restarting the computer is required to start the installation of the Linux distribution. It can take a few minutes for the installation to complete after you restart. - - For more information about setting up WSL as a development environment, see the [Set up a WSL development environment](https://learn.microsoft.com/en-us/windows/wsl/setup/environment){target=\_blank} docs. - -### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } - -To install the Rust toolchain on WSL: - -1. Click the **Start** menu, then select **Ubuntu**. -2. Type a UNIX user name to create a user account. -3. Type a password for your UNIX user, then retype the password to confirm it. -4. Download the latest updates for the Ubuntu distribution using the Ubuntu Advanced Packaging Tool (`apt`) by running the following command: - - ```bash - sudo apt update - ``` - -5. Add the required packages for the Ubuntu distribution by running the following command: - - ```bash - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` - -6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: - - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -7. Follow the prompts displayed to proceed with a default installation. - -8. Update your current shell to include Cargo by running the following command: - - ```bash - source ~/.cargo/env - ``` - -9. Verify your installation by running the following command: - - ```bash - rustc --version - ``` - -10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: - - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` - -11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - -## Build the Polkadot SDK - -After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. - -### Clone the Polkadot SDK - -1. Clone the Polkadot SDK repository: - - ```bash - git clone https://github.com/paritytech/polkadot-sdk.git - ``` - -2. Navigate into the project directory: - - ```bash - cd polkadot-sdk - ``` - -### Compile the Polkadot SDK - -Compile the entire Polkadot SDK repository to ensure your environment is properly configured: - -```bash -cargo build --release --locked -``` - -!!!note - This initial compilation will take significant time, depending on your machine specifications. It compiles all components of the Polkadot SDK to verify your toolchain is correctly configured. - -### Verify the Build - -Once the build completes successfully, verify the installation by checking the compiled binaries: - -```bash -ls target/release -``` - -You should see several binaries, including: - -- `polkadot`: The Polkadot relay chain node. -- `polkadot-parachain`: The parachain collator node. -- `polkadot-omni-node`:The omni node for running parachains. -- `substrate-node`: The kitchensink node with many pre-configured pallets. - -Verify the Polkadot binary works by checking its version: - -```bash -./target/release/polkadot --version -``` - -This should display version information similar to: - -```bash -polkadot 1.16.0-1234abcd567 -``` - -If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! - -## Optional: Run the Kitchensink Node - -The Polkadot SDK includes a feature-rich node called "kitchensink" located at `substrate/bin/node`. This node comes pre-configured with many pallets and features from the Polkadot SDK, making it an excellent reference for exploring capabilities and understanding how different components work together. - -!!!note - If you've already compiled the Polkadot SDK in the previous step, the `substrate-node` binary is already built and ready to use. You can skip directly to running the node. - -### Run the Kitchensink Node in Development Mode - -From the `polkadot-sdk` root directory, start the kitchensink node in development mode: - -```bash -./target/release/substrate-node --dev -``` - -The `--dev` flag enables development mode, which: - -- Runs a single-node development chain. -- Produces and finalizes blocks automatically. -- Uses pre-configured development accounts (Alice, Bob, etc.). -- Deletes all data when stopped, ensuring a clean state on restart. - - -You should see log output indicating the node is running and producing blocks, with increasing block numbers after `finalized`. - -### Interact with the Kitchensink Node - -The kitchensink node is accessible at `ws://localhost:9944`. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your browser to explore its features and connect to the local node. - -1. Click the network icon in the top left corner. -2. Scroll to **Development** and select **Local Node**. -3. Click **Switch** to connect to your local node. - -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) - -Once connected, the interface updates its color scheme to indicate a successful connection to the local node. - -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) - -You can now explore the various pallets and features included in the kitchensink node, making it a valuable reference as you develop your own blockchain applications. - -To stop the node, press `Control-C` in the terminal. - -## Where to Go Next - -
    - -- __Get Started with Parachain Development__ - - --- - - Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. - - [:octicons-arrow-right-24: Get Started](/parachains/get-started/) - -
    - - ---- - -Page Title: Interoperability - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/interoperability/ -- Summary: Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. - -# Interoperability - -## Introduction - -Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions. - -Polkadot’s design ensures that blockchains can transcend their individual limitations by working together as part of a unified system. This cooperative architecture is what sets Polkadot apart in the blockchain landscape. - -## Why Interoperability Matters - -The blockchain ecosystem is inherently fragmented. Different blockchains excel in specialized domains such as finance, gaming, or supply chain management, but these chains function in isolation without interoperability. This lack of connectivity stifles the broader utility of blockchain technology. - -Interoperability solves this problem by enabling blockchains to: - -- **Collaborate across networks**: Chains can interact to share assets, functionality, and data, creating synergies that amplify their individual strengths. -- **Achieve greater scalability**: Specialized chains can offload tasks to others, optimizing performance and resource utilization. -- **Expand use-case potential**: Cross-chain applications can leverage features from multiple blockchains, unlocking novel user experiences and solutions. - -In the Polkadot ecosystem, interoperability transforms a collection of isolated chains into a cohesive, efficient network, pushing the boundaries of what blockchains can achieve together. - -## Key Mechanisms for Interoperability - -At the core of Polkadot's cross-chain collaboration are foundational technologies designed to break down barriers between networks. These mechanisms empower blockchains to communicate, share resources, and operate as a cohesive ecosystem. - -### Cross-Consensus Messaging (XCM): The Backbone of Communication - -Polkadot's Cross-Consensus Messaging (XCM) is the standard framework for interaction between parachains, relay chains, and, eventually, external blockchains. XCM provides a trustless, secure messaging format for exchanging assets, sharing data, and executing cross-chain operations. - -Through XCM, decentralized applications can: - -- Transfer tokens and other assets across chains. -- Coordinate complex workflows that span multiple blockchains. -- Enable seamless user experiences where underlying blockchain differences are invisible. -- XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem. - -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. - -### Bridges: Connecting External Networks - -While XCM enables interoperability within the Polkadot ecosystem, bridges extend this functionality to external blockchains such as Ethereum and Bitcoin. By connecting these networks, bridges allow Polkadot-based chains to access external liquidity, additional functionalities, and broader user bases. - -With bridges, developers and users gain the ability to: - -- Integrate external assets into Polkadot-based applications. -- Combine the strengths of Polkadot’s scalability with the liquidity of other networks. -- Facilitate accurate multi-chain applications that transcend ecosystem boundaries. - -For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. - -## The Polkadot Advantage - -Polkadot was purpose-built for interoperability. Unlike networks that add interoperability as an afterthought, Polkadot integrates it as a fundamental design principle. This approach offers several distinct advantages: - -- **Developer empowerment**: Polkadot’s interoperability tools allow developers to build applications that leverage multiple chains’ capabilities without added complexity. -- **Enhanced ecosystem collaboration**: Chains in Polkadot can focus on their unique strengths while contributing to the ecosystem’s overall growth. -- **Future-proofing blockchain**: By enabling seamless communication, Polkadot ensures its ecosystem can adapt to evolving demands and technologies. - -## Looking Ahead - -Polkadot’s vision of interoperability extends beyond technical functionality, representing a shift towards a more collaborative blockchain landscape. By enabling chains to work together, Polkadot fosters innovation, efficiency, and accessibility, paving the way for a decentralized future where blockchains are not isolated competitors but interconnected collaborators. - - ---- - -Page Title: Introduction to XCM - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ -- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. - -# Introduction to XCM - -## Introduction - -Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. - -With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. - -## Messaging Format - -XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. - -XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. - -## The Four Principles of XCM - -XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: - -- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. -- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. -- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. -- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. - -These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. - -## The XCM Tech Stack - -![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) - -The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. - -## Core Functionalities of XCM - -XCM enhances cross-consensus communication by introducing several powerful features: - -- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. -- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. -- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. - -The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. - -## XCM Example - -The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). - -```rust -let message = Xcm(vec![ - WithdrawAsset((Here, amount).into()), - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } -]); -``` - -The message consists of three instructions described as follows: - -- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. - - ```rust - WithdrawAsset((Here, amount).into()), - ``` - - - **`Here`**: The native parachain token. - - **`amount`**: The number of tokens that are transferred. - - The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. - -- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. - - ```rust - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - ``` - - - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. - - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. - -- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. - - ```rust - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } - ``` - - - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. - -This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - -## Overview - -XCM revolutionizes cross-chain communication by enabling use cases such as: - -- Token transfers between blockchains. -- Asset locking for cross-chain smart contract interactions. -- Remote execution of functions on other blockchains. - -These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - - ---- - -Page Title: JSON-RPC APIs - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ -- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. - -# JSON-RPC APIs - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. - -This guide uses the Polkadot Hub TestNet endpoint: - -```text -https://testnet-passet-hub-eth-rpc.polkadot.io -``` - -## Available Methods - -### eth_accounts - -Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_accounts" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_accounts", - "params":[], - "id":1 -}' -``` - ---- - -### eth_blockNumber - -Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_blockNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_blockNumber", - "params":[], - "id":1 -}' -``` - ---- - -### eth_call - -Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction call object. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_call" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_call", - "params":[{ - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_CALL" - }, "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_chainId - -Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_chainId" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_chainId", - "params":[], - "id":1 -}' -``` - ---- - -### eth_estimateGas - -Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction call object. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_estimateGas" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_estimateGas", - "params":[{ - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_FUNCTION_CALL" - }], - "id":1 -}' -``` - -Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. - ---- - -### eth_gasPrice - -Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_gasPrice" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_gasPrice", - "params":[], - "id":1 -}' -``` - ---- - -### eth_getBalance - -Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_getBalance" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBalance", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getBlockByHash - -Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. - -**Parameters**: - -- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. - -**Example**: - -```bash title="eth_getBlockByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockByHash", - "params":["INSERT_BLOCK_HASH", INSERT_BOOLEAN], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values. - ---- - -### eth_getBlockByNumber - -Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. - -**Parameters**: - -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. - -**Example**: - -```bash title="eth_getBlockByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockByNumber", - "params":["INSERT_BLOCK_VALUE", INSERT_BOOLEAN], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values. - ---- - -### eth_getBlockTransactionCountByNumber - -Returns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\_blank}. - -**Parameters**: - -- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_getBlockTransactionCountByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockTransactionCountByNumber", - "params":["INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getBlockTransactionCountByHash - -Returns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}. - -**Parameters**: - -- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getBlockTransactionCountByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockTransactionCountByHash", - "params":["INSERT_BLOCK_HASH"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. - ---- - -### eth_getCode - -Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - -**Example**: - -```bash title="eth_getCode" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getCode", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getLogs - -Returns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}. - -**Parameters**: - -- **`filter` ++"object"++**: The filter object. - - **`fromBlock` ++"string"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - - **`toBlock` ++"string"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - - **`address` ++"string" or "array of strings"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`topics` ++"array of strings"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string or an array of such strings (meaning OR). - - **`blockhash` ++"string"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getLogs" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getLogs", - "params":[{ - "fromBlock": "latest", - "toBlock": "latest" - }], - "id":1 -}' -``` - ---- - -### eth_getStorageAt - -Returns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`storageKey` ++"string"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - -**Example**: - -```bash title="eth_getStorageAt" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getStorageAt", - "params":["INSERT_ADDRESS", "INSERT_STORAGE_KEY", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getTransactionCount - -Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - -**Example**: - -```bash title="eth_getTransactionCount" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionCount", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getTransactionByHash - -Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. - -**Parameters**: - -- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByHash", - "params":["INSERT_TRANSACTION_HASH"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. - ---- - -### eth_getTransactionByBlockNumberAndIndex - -Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. - -**Parameters**: - -- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionByBlockNumberAndIndex" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByBlockNumberAndIndex", - "params":["INSERT_BLOCK_VALUE", "INSERT_TRANSACTION_INDEX"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. - ---- - -### eth_getTransactionByBlockHashAndIndex - -Returns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}. - -**Parameters**: - -- **`blockHash` ++"string"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionByBlockHashAndIndex" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByBlockHashAndIndex", - "params":["INSERT_BLOCK_HASH", "INSERT_TRANSACTION_INDEX"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. - ---- - -### eth_getTransactionReceipt - -Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. - -**Parameters**: - -- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionReceipt" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionReceipt", - "params":["INSERT_TRANSACTION_HASH"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. - ---- - -### eth_maxPriorityFeePerGas - -Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_maxPriorityFeePerGas" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_maxPriorityFeePerGas", - "params":[], - "id":1 -}' -``` - ---- - -### eth_sendRawTransaction - -Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. - -**Parameters**: - -- **`callData` ++"string"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_sendRawTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_sendRawTransaction", - "params":["INSERT_CALL_DATA"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_CALL_DATA` with the proper values. - ---- - -### eth_sendTransaction - -Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction object. - - **`from` ++"string"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`to` ++"string"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`data` ++"string"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`nonce` ++"string"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_sendTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_sendTransaction", - "params":[{ - "from": "INSERT_SENDER_ADDRESS", - "to": "INSERT_RECIPIENT_ADDRESS", - "gas": "INSERT_GAS_LIMIT", - "gasPrice": "INSERT_GAS_PRICE", - "value": "INSERT_VALUE", - "input": "INSERT_INPUT_DATA", - "nonce": "INSERT_NONCE" - }], - "id":1 -}' -``` - -Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values. - ---- - -### eth_syncing - -Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_syncing" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_syncing", - "params":[], - "id":1 -}' -``` - ---- - -### net_listening - -Returns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="net_listening" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_listening", - "params":[], - "id":1 -}' -``` - ---- - -### net_peerCount - -Returns the number of peers currently connected to the client. - -**Parameters**: - -None. - -**Example**: - -```bash title="net_peerCount" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_peerCount", - "params":[], - "id":1 -}' -``` - ---- - -### net_version - -Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="net_version" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_version", - "params":[], - "id":1 -}' -``` - ---- - -### system_health - -Returns information about the health of the system. - -**Parameters**: - -None. - -**Example**: - -```bash title="system_health" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"system_health", - "params":[], - "id":1 -}' -``` - ---- - -### web3_clientVersion - -Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="web3_clientVersion" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"web3_clientVersion", - "params":[], - "id":1 -}' -``` - ---- - -### debug_traceBlockByNumber - -Traces a block's execution by its number and returns a detailed execution trace for each transaction. - -**Parameters**: - -- **`blockValue` ++"string"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`options` ++"object"++**: (Optional) An object containing tracer options. - - **`tracer` ++"string"++**: The name of the tracer to use (e.g., `"callTracer"`, `"opTracer"`). - - Other tracer-specific options may be supported. - -**Example**: - -```bash title="debug_traceBlockByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceBlockByNumber", - "params":["INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], - "id":1 -}' -``` - -Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. - ---- - -### debug_traceTransaction - -Traces the execution of a single transaction by its hash and returns a detailed execution trace. - -**Parameters**: - -- **`transactionHash` ++"string"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). - -**Example**: - -```bash title="debug_traceTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceTransaction", - "params":["INSERT_TRANSACTION_HASH", {"tracer": "callTracer"}], - "id":1 -}' -``` - -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. - ---- - -### debug_traceCall - -Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction call object, similar to `eth_call` parameters. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). - -**Example**: - -```bash title="debug_traceCall" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceCall", - "params":[{ - "from": "INSERT_SENDER_ADDRESS", - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_CALL" - }, "INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], - "id":1 -}' -``` - -Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value. - ---- - -## Response Format - -All responses follow the standard JSON-RPC 2.0 format: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": ... // The return value varies by method -} -``` - -## Error Handling - -If an error occurs, the response will include an error object: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "error": { - "code": -32000, - "message": "Error message here" - } -} -``` - - ---- - -Page Title: Networks - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/networks/ -- Summary: Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. - -# Networks - -## Introduction - -The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's various networks and explain how they fit into the development workflow. - -## Network Overview - -Polkadot's development process is structured to ensure new features and upgrades are rigorously tested before being deployed on live production networks. The progression follows a well-defined path, starting from local environments and advancing through TestNets, ultimately reaching the Polkadot MainNet. The diagram below outlines the typical progression of the Polkadot development cycle: - -``` mermaid -flowchart LR - id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] - id1[Local] --> id3[Paseo] --> id5[Polkadot] -``` - -This flow ensures developers can thoroughly test and iterate without risking real tokens or affecting production networks. Testing tools like [Chopsticks](#chopsticks) and various TestNets make it easier to experiment safely before releasing to production. - -A typical journey through the Polkadot core protocol development process might look like this: - -1. **Local development node**: Development starts in a local environment, where developers can create, test, and iterate on upgrades or new features using a local development node. This stage allows rapid experimentation in an isolated setup without any external dependencies. - -2. **Westend**: After testing locally, upgrades are deployed to [Westend](#westend), Polkadot's primary TestNet. Westend simulates real-world conditions without using real tokens, making it the ideal place for rigorous feature testing before moving on to production networks. - -3. **Kusama**: Once features have passed extensive testing on Westend, they move to Kusama, Polkadot's experimental and fast-moving "canary" network. Kusama operates as a high-fidelity testing ground with actual economic incentives, giving developers insights into how their features will perform in a real-world environment. - -4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network. - - In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. - -5. **Paseo**: For parachain and dApp developers, Paseo serves as a community-run TestNet that mirrors Polkadot's runtime. Like Westend for core protocol development, Paseo provides a testing ground for parachain development without affecting live networks. - -!!!note - The Rococo TestNet deprecation date was October 14, 2024. Teams should use Westend for Polkadot protocol and feature testing and Paseo for chain development-related testing. - -## Polkadot Development Networks - -Development and testing are crucial to building robust dApps and parachains and performing network upgrades within the Polkadot ecosystem. To achieve this, developers can leverage various networks and tools that provide a risk-free environment for experimentation and validation before deploying features to live networks. These networks help avoid the costs and risks associated with real tokens, enabling testing for functionalities like governance, cross-chain messaging, and runtime upgrades. - -## Kusama Network - -Kusama is the experimental version of Polkadot, designed for developers who want to move quickly and test their applications in a real-world environment with economic incentives. Kusama serves as a production-grade testing ground where developers can deploy features and upgrades with the pressure of game theory and economics in mind. It mirrors Polkadot but operates as a more flexible space for innovation. - -The native token for Kusama is KSM. For more information about KSM, visit the [Native Assets](https://wiki.polkadot.com/kusama/kusama-getting-started/){target=\_blank} page. - -## Test Networks - -The following test networks provide controlled environments for testing upgrades and new features. TestNet tokens are available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}. - -### Westend - -Westend is Polkadot's primary permanent TestNet. Unlike temporary test networks, Westend is not reset to the genesis block, making it an ongoing environment for testing Polkadot core features. Managed by Parity Technologies, Westend ensures that developers can test features in a real-world simulation without using actual tokens. - -The native token for Westend is WND. More details about WND can be found on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_2){target=\_blank} page. - -### Paseo - -[Paseo](https://github.com/paseo-network){target=\_blank} is a community-managed TestNet designed for parachain and dApp developers. It mirrors Polkadot's runtime and is maintained by Polkadot community members. Paseo provides a dedicated space for parachain developers to test their applications in a Polkadot-like environment without the risks associated with live networks. - -The native token for Paseo is PAS. Additional information on PAS is available on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_1){target=\_blank} page. - -## Local Test Networks - -Local test networks are an essential part of the development cycle for blockchain developers using the Polkadot SDK. They allow for fast, iterative testing in controlled, private environments without connecting to public TestNets. Developers can quickly spin up local instances to experiment, debug, and validate their code before deploying to larger TestNets like Westend or Paseo. Two key tools for local network testing are Zombienet and Chopsticks. - -### Zombienet - -[Zombienet](https://github.com/paritytech/zombienet){target=\_blank} is a flexible testing framework for Polkadot SDK-based blockchains. It enables developers to create and manage ephemeral, short-lived networks. This feature makes Zombienet particularly useful for quick iterations, as it allows you to run multiple local networks concurrently, mimicking different runtime conditions. Whether you're developing a parachain or testing your custom blockchain logic, Zombienet gives you the tools to automate local testing. - -Key features of Zombienet include: - -- Creating dynamic, local networks with different configurations. -- Running parachains and relay chains in a simulated environment. -- Efficient testing of network components like cross-chain messaging and governance. - -Zombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets. - -### Chopsticks - -[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\_blank} is a tool designed to create forks of Polkadot SDK-based blockchains, allowing developers to interact with network forks as part of their testing process. This capability makes Chopsticks a powerful option for testing upgrades, runtime changes, or cross-chain applications in a forked network environment. - -Key features of Chopsticks include: - -- Forking live Polkadot SDK-based blockchains for isolated testing. -- Simulating cross-chain messages in a private, controlled setup. -- Debugging network behavior by interacting with the fork in real-time. - -Chopsticks provides a controlled environment for developers to safely explore the effects of runtime changes. It ensures that network behavior is tested and verified before upgrades are deployed to live networks. - - ---- - -Page Title: Node and Runtime - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/node-and-runtime/ -- Summary: Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. - -# Node and Runtime - -## Introduction - -Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network. - -Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. - -If the system were a monolithic protocol, any modification would require updating the entire system. Instead, Polkadot achieves true upgradeability by defining an immutable meta-protocol (the client) and a protocol (the runtime) that can be upgraded independently. - -This separation gives the [Polkadot Relay Chain](/polkadot-protocol/architecture/polkadot-chain){target=\_blank} and all connected [parachains](/polkadot-protocol/architecture/parachains){target=\_blank} an evolutionary advantage over other blockchain platforms. - -## Architectural Principles - -The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: - -- Client (Meta-protocol): - - Handles the foundational infrastructure of the blockchain. - - Manages runtime execution, networking, consensus, and other off-chain components. - - Provides an immutable base layer that ensures network stability. - - Upgradable only through hard forks. - -- Runtime (Protocol): - - Defines the blockchain's state transition logic. - - Determines the specific rules and behaviors of the blockchain. - - Compiled to WebAssembly (Wasm) for platform-independent execution. - - Capable of being upgraded without network-wide forking. - -### Advantages of this Architecture - -- **Forkless upgrades**: Runtime can be updated without disrupting the entire network. -- **Modularity**: Clear separation allows independent development of client and runtime. -- **Flexibility**: Enables rapid iteration and evolution of blockchain logic. -- **Performance**: WebAssembly compilation provides efficient, cross-platform execution. - -## Node (Client) - -The node, also known as the client, is the core component responsible for executing the Wasm runtime and orchestrating various essential blockchain components. It ensures the correct execution of the state transition function and manages multiple critical subsystems, including: - -- **Wasm execution**: Runs the blockchain runtime, which defines the state transition rules. -- **Database management**: Stores blockchain data. -- **Networking**: Facilitates peer-to-peer communication, block propagation, and transaction gossiping. -- **Transaction pool (Mempool)**: Manages pending transactions before they are included in a block. -- **Consensus mechanism**: Ensures agreement on the blockchain state across nodes. -- **RPC services**: Provides external interfaces for applications and users to interact with the node. - -## Runtime - -The runtime is more than just a set of rules. It's the fundamental logic engine that defines a blockchain's entire behavior. In Polkadot SDK-based blockchains, the runtime represents a complete, self-contained description of the blockchain's state transition function. - -### Characteristics - -The runtime is distinguished by three key characteristics: - -- **Business logic**: Defines the complete application-specific blockchain behavior. -- **WebAssembly compilation**: Ensures platform-independent, secure execution. -- **On-chain storage**: Stored within the blockchain's state, allowing dynamic updates. - -### Key Functions - -The runtime performs several critical functions, such as: - -- Define state transition rules. -- Implement blockchain-specific logic. -- Manage account interactions. -- Control transaction processing. -- Define governance mechanisms. -- Handle custom pallets and modules. - -## Communication Between Node and Runtime - -The client and runtime communicate exclusively using [SCALE-encoded](/polkadot-protocol/parachain-basics/data-encoding){target=\_blank} communication. This ensures efficient and compact data exchange between the two components. - -### Runtime APIs - -The Runtime API consists of well-defined functions and constants a client assumes are implemented in the Runtime Wasm blob. These APIs enable the client to interact with the runtime to execute blockchain operations and retrieve information. The client invokes these APIs to: - -- Build, execute, and finalize blocks. -- Access metadata. -- Access consensus related information. -- Handle transaction execution. - -### Host Functions - -During execution, the runtime can access certain external client functionalities via host functions. The specific functions the client exposes allow the runtime to perform operations outside the WebAssembly domain. Host functions enable the runtime to: - -- Perform cryptographic operations. -- Access the current blockchain state. -- Handle storage modifications. -- Allocate memory. - - ---- - -Page Title: On-Chain Governance Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md -- Canonical (HTML): https://docs.polkadot.com/reference/governance/ -- Summary: Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. - -# On-Chain Governance - -## Introduction - -Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model. - -This guide will explain the principles and structure of OpenGov and walk you through its key components, such as Origins, Tracks, and Delegation. You will learn about improvements over earlier governance systems, including streamlined voting processes and enhanced stakeholder participation. - -With OpenGov, Polkadot achieves a flexible, scalable, and democratic governance framework that allows multiple proposals to proceed simultaneously, ensuring the network evolves in alignment with its community's needs. - -## Governance Evolution - -Polkadot’s governance journey began with [Governance V1](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#governance-summary){target=\_blank}, a system that proved effective in managing treasury funds and protocol upgrades. However, it faced limitations, such as: - -- Slow voting cycles, causing delays in decision-making. -- Inflexibility in handling multiple referendums, restricting scalability. - -To address these challenges, Polkadot introduced OpenGov, a governance model designed for greater inclusivity, efficiency, and scalability. OpenGov replaces the centralized structures of Governance V1, such as the Council and Technical Committee, with a fully decentralized and dynamic framework. - -For a full comparison of the historic and current governance models, visit the [Gov1 vs. Polkadot OpenGov](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#gov1-vs-polkadot-opengov){target=\_blank} section of the Polkadot Wiki. - -## OpenGov Key Features - -OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: - -- **Decentralization**: Shifts all decision-making power to the public, ensuring a more democratic process. -- **Enhanced delegation**: Allows users to delegate their votes to trusted experts across specific governance tracks. -- **Simultaneous referendums**: Multiple proposals can progress at once, enabling faster decision-making. -- **Polkadot Technical Fellowship**: A broad, community-driven group replacing the centralized Technical Committee. - -This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. - -## Origins and Tracks - -In OpenGov, origins and tracks are central to managing proposals and votes. - -- **Origin**: Determines the authority level of a proposal (e.g., Treasury, Root) which decides the track of all referendums from that origin. -- **Track**: Define the procedural flow of a proposal, such as voting duration, approval thresholds, and enactment timelines. - -Developers must be aware that referendums from different origins and tracks will take varying amounts of time to reach approval and enactment. The [Polkadot Technical Fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} has the option to shorten this timeline by whitelisting a proposal and allowing it to be enacted through the [Whitelist Caller](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#whitelisted-caller){target=\_blank} origin. - -Visit [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#origins-and-tracks){target=\_blank} for details on current origins and tracks, associated terminology, and parameters. - -## Referendums - -In OpenGov, anyone can submit a referendum, fostering an open and participatory system. The timeline for a referendum depends on the privilege level of the origin with more significant changes offering more time for community voting and participation before enactment. - -The timeline for an individual referendum includes four distinct periods: - -- **Lead-in**: A minimum amount of time to allow for community participation, available room in the origin, and payment of the decision deposit. Voting is open during this period. -- **Decision**: Voting continues. -- **Confirmation**: Referendum must meet [approval and support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} criteria during entire period to avoid rejection. -- **Enactment**: Changes approved by the referendum are executed. - -### Vote on Referendums - -Voters can vote with their tokens on each referendum. Polkadot uses a voluntary token locking mechanism, called conviction voting, as a way for voters to increase their voting power. A token holder signals they have a stronger preference for approving a proposal based upon their willingness to lock up tokens. Longer voluntary token locks are seen as a signal of continual approval and translate to increased voting weight. - -See [Voting on a Referendum](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank} for a deeper look at conviction voting and related token locks. - -### Delegate Voting Power - -The OpenGov system also supports multi-role delegations, allowing token holders to assign their voting power on different tracks to entities with expertise in those areas. - -For example, if a token holder lacks the technical knowledge to evaluate proposals on the [Root track](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#root){target=\_blank}, they can delegate their voting power for that track to an expert they trust to vote in the best interest of the network. This ensures informed decision-making across tracks while maintaining flexibility for token holders. - -Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. - -### Cancel a Referendum - -Polkadot OpenGov has two origins for rejecting ongoing referendums: - -- [**Referendum Canceller**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-canceller){target=\_blank}: Cancels an active referendum when non-malicious errors occur and refunds the deposits to the originators. -- [**Referendum Killer**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-killer){target=\_blank}: Used for urgent, malicious cases this origin instantly terminates an active referendum and slashes deposits. - -See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. - -## Additional Resources - -- **[Democracy pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/democracy/src){target=\_blank}**: Handles administration of general stakeholder voting. -- **[Gov2: Polkadot’s Next Generation of Decentralised Governance](https://medium.com/polkadot-network/gov2-polkadots-next-generation-of-decentralised-governance-4d9ef657d11b){target=\_blank}**: Medium article by Gavin Wood. -- **[Polkadot Direction](https://matrix.to/#/#Polkadot-Direction:parity.io){target=\_blank}**: Matrix Element client. -- **[Polkassembly](https://polkadot.polkassembly.io/){target=\_blank}**: OpenGov dashboard and UI. -- **[Polkadot.js Apps Governance](https://polkadot.js.org/apps/#/referenda){target=\_blank}**: Overview of active referendums. - - ---- - -Page Title: Oracles - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md -- Canonical (HTML): https://docs.polkadot.com/parachains/integrations/oracles/ -- Summary: Learn about blockchain oracles, the essential bridges connecting blockchains with real-world data for decentralized applications in the Polkadot ecosystem. - -# Oracles - -## What is a Blockchain Oracle? - -Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the "blockchain oracle problem." Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain. - -While simple oracle implementations may rely on a single trusted provider, more sophisticated solutions use decentralized networks where multiple providers stake assets and reach consensus on data validity. Typical applications include DeFi price feeds, weather data for insurance contracts, and cross-chain asset verification. - -## Oracle Implementations - -
    - -- __Acurast__ - - --- - - Acurast is a decentralized, serverless cloud platform that uses a distributed network of mobile devices for oracle services, addressing centralized trust and data ownership issues. In the Polkadot ecosystem, it allows developers to define off-chain data and computation needs, which are processed by these devices acting as decentralized oracle nodes, delivering results to Substrate (Wasm) and EVM environments. - - [:octicons-arrow-right-24: Reference](https://acurast.com/){target=\_blank} - -
    - - ---- - -Page Title: Overview of FRAME - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md -- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ -- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. - -# Customize Your Runtime - -## Introduction - -A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. - -This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. - -## Understanding Your Runtime - -The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. - -Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. - -## Runtime Architecture - -The following diagram shows how FRAME components work together to form your runtime: - -![](/images/parachains/customize-runtime/index/frame-overview-01.webp) - -The main components are: - -- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. -- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. -- **`frame_system`**: Provides core runtime primitives and storage. -- **`frame_support`**: Utilities and macros that simplify pallet development. - -## Building Blocks: Pallets - -[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. - -A pallet can implement virtually any blockchain feature you need: - -- Expose new transactions that users can submit. -- Store data on-chain. -- Enforce business rules and validation logic. -- Emit events to notify users of state changes. -- Handle errors gracefully. - -### Pre-Built Pallets vs. Custom Pallets - -FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. - -However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. - -### Pallet Structure - -FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. - -A typical pallet looks like this: - -```rust -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - #[pallet::config] // snip - #[pallet::event] // snip - #[pallet::error] // snip - #[pallet::storage] // snip - #[pallet::call] // snip -} -``` - -Every pallet can implement these core macros: - -- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. -- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. -- **`#[pallet::config]`**: Defines configuration and associated types. -- **`#[pallet::event]`**: Defines events emitted by your pallet. -- **`#[pallet::error]`**: Defines error types your pallet can return. -- **`#[pallet::storage]`**: Defines on-chain storage items. -- **`#[pallet::call]`**: Defines dispatchable functions (transactions). - -For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. - -## How Runtime Customization Works - -Customizing your runtime typically follows these patterns: - -**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. - -**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. - -**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. - -**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. - -The following diagram illustrates how pallets combine to form a complete runtime: - -![](/images/parachains/customize-runtime/index/frame-overview-02.webp) - -## Starting Templates - -The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. - -- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. - -- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. - -- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. - -- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. - -## Key Customization Scenarios - -This section covers the most common customization patterns you'll encounter: - -- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. - -- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. - -- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. - -- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. - -- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. - - ---- - -Page Title: Overview of the Polkadot Relay Chain - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/ -- Summary: Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. - -# Overview - -## Introduction - -Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank}, and cross-chain interactions via its native [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank}. - -This guide covers key aspects of Polkadot’s architecture, including its high-level protocol structure, blockspace commoditization, and the role of its native token, DOT, in governance, staking, and resource allocation. - -## Polkadot 1.0 - -Polkadot 1.0 represents the state of Polkadot as of 2023, coinciding with the release of [Polkadot runtime v1.0.0](https://github.com/paritytech/polkadot/releases/tag/v1.0.0){target=\_blank}. This section will focus on Polkadot 1.0, along with philosophical insights into network resilience and blockspace. - -As a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including: - -- **Application-specific Layer-1 blockchains (parachains)**: Polkadot's sharded network allows for parallel transaction processing, with shards that can have unique state transition functions, enabling custom-built L1 chains optimized for specific applications. - -- **Shared security and scalability**: L1 chains connected to Polkadot benefit from its [Nominated Proof of Stake (NPoS)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#nominated-proof-of-stake){target=\_blank} system, providing security out-of-the-box without the need to bootstrap their own. - -- **Secure interoperability**: Polkadot's native interoperability enables seamless data and value exchange between parachains. This interoperability can also be used outside of the ecosystem for bridging with external networks. - -- **Resilient infrastructure**: Decentralized and scalable, Polkadot ensures ongoing support for development and community initiatives via its on-chain [treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} and governance. - -- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. - -- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. - - - [Polkadot Blockchain Academy](https://polkadot.com/blockchain-academy){target=\_blank} - - [EdX courses](https://www.edx.org/school/web3x){target=\_blank} - - Rust and Substrate courses (coming soon) - -### High-Level Architecture - -Polkadot features a chain that serves as the central component of the system. This chain is depicted as a ring encircled by several parachains that are connected to it. - -According to Polkadot's design, any blockchain that can compile to WebAssembly (Wasm) and adheres to the Parachains Protocol becomes a parachain on the Polkadot network. - -Here’s a high-level overview of the Polkadot protocol architecture: - -![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } - -Parachains propose blocks to Polkadot validators, who check for availability and validity before finalizing them. With the relay chain providing security, collators—full nodes of parachains—can focus on their tasks without needing strong incentives. - -The [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank} allows parachains to exchange messages freely, leveraging the chain's security for trust-free communication. - -In order to interact with chains that want to use their own finalization process (e.g., Bitcoin), Polkadot has [bridges](/reference/parachains/interoperability/#bridges-connecting-external-networks){target=\_blank} that offer two-way compatibility, meaning that transactions can be made between different parachains. - -### Polkadot's Additional Functionalities - -Historically, obtaining core slots on Polkadot chain relied upon crowdloans and auctions. Chain cores were leased through auctions for three-month periods, up to a maximum of two years. Crowdloans enabled users to securely lend funds to teams for lease deposits in exchange for pre-sale tokens, which is the only way to access slots on Polkadot 1.0. Auctions are now deprecated in favor of [coretime](/polkadot-protocol/architecture/system-chains/coretime/){target=\_blank}. - -Additionally, the chain handles [staking](https://wiki.polkadot.com/learn/learn-staking/){target=\_blank}, [accounts](/reference/parachains/accounts/){target=\_blank}, balances, and [governance](/reference/governance/){target=\_blank}. - -#### Agile Coretime - -The new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. - -[Agile coretime](/reference/polkadot-hub/consensus-and-security/agile-coretime/){target=\_blank} improves the efficient use of Polkadot's network resources and offers economic flexibility for developers, extending Polkadot's capabilities far beyond the original vision outlined in the [whitepaper](https://polkadot.com/papers/Polkadot-whitepaper.pdf){target=\_blank}. - -It enables parachains to purchase monthly "bulk" allocations of coretime (the time allocated for utilizing a core, measured in Polkadot relay chain blocks), ensuring heavy-duty parachains that can author a block every six seconds with [Asynchronous Backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} can reliably renew their coretime each month. Although six-second block times are now the default, parachains have the option of producing blocks less frequently. - -Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. - -### Polkadot's Resilience - -Decentralization is a vital component of blockchain networks, but it comes with trade-offs: - -- An overly decentralized network may face challenges in reaching consensus and require significant energy to operate. -- Also, a network that achieves consensus quickly risks centralization, making it easier to manipulate or attack. - -A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. - -Polkadot 1.0 currently achieves resilience through several strategies: - -- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. - -- **Decentralized nodes**: Designed to encourage operators to join the network. This program aims to expand and diversify the validators in the ecosystem who aim to become independent of the program during their term. Feel free to explore more about the program on the official [Decentralized Nodes](https://nodes.web3.foundation/){target=\_blank} page. - -- **On-chain treasury and governance**: Known as [OpenGov](/reference/governance/){target=\_blank}, this system allows every decision to be made through public referenda, enabling any token holder to cast a vote. - -### Polkadot's Blockspace - -Polkadot 1.0’s design allows for the commoditization of blockspace. - -Blockspace is a blockchain's capacity to finalize and commit operations, encompassing its security, computing, and storage capabilities. Its characteristics can vary across different blockchains, affecting security, flexibility, and availability. - -- **Security**: Measures the robustness of blockspace in Proof of Stake (PoS) networks linked to the stake locked on validator nodes, the variance in stake among validators, and the total number of validators. It also considers social centralization (how many validators are owned by single operators) and physical centralization (how many validators run on the same service provider). - -- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes. - -- **Availability**: Indicates how easily users can access blockspace. It should be easily accessible, allowing diverse business models to thrive, ideally regulated by a marketplace based on demand and supplemented by options for "second-hand" blockspace. - -Polkadot is built on core blockspace principles, but there's room for improvement. Tasks like balance transfers, staking, and governance are managed on the relay chain. - -Delegating these responsibilities to [system chains](/polkadot-protocol/architecture/system-chains/){target=\_blank} could enhance flexibility and allow the relay chain to concentrate on providing shared security and interoperability. - -For more information about blockspace, watch [Robert Habermeier’s interview](https://www.youtube.com/watch?v=e1vISppPwe4){target=\_blank} or read his [technical blog post](https://www.rob.tech/blog/polkadot-blockspace-over-blockchains/){target=\_blank}. - -## DOT Token - -DOT is the native token of the Polkadot network, much like BTC for Bitcoin and Ether for the Ethereum blockchain. DOT has 10 decimals, uses the Planck base unit, and has a balance type of `u128`. The same is true for Kusama's KSM token with the exception of having 12 decimals. - -### Redenomination of DOT - -Polkadot conducted a community poll, which ended on 27 July 2020 at block 888,888, to decide whether to redenominate the DOT token. The stakeholders chose to redenominate the token, changing the value of 1 DOT from 1e12 plancks to 1e10 plancks. - -Importantly, this did not affect the network's total number of base units (plancks); it only affects how a single DOT is represented. The redenomination became effective 72 hours after transfers were enabled, occurring at block 1,248,328 on 21 August 2020 around 16:50 UTC. - -### The Planck Unit - -The smallest unit of account balance on Polkadot SDK-based blockchains (such as Polkadot and Kusama) is called _Planck_, named after the Planck length, the smallest measurable distance in the physical universe. - -Similar to how BTC's smallest unit is the Satoshi and ETH's is the Wei, Polkadot's native token DOT equals 1e10 Planck, while Kusama's native token KSM equals 1e12 Planck. - -### Uses for DOT - -DOT serves three primary functions within the Polkadot network: - -- **Governance**: It is used to participate in the governance of the network. -- **Staking**: DOT is staked to support the network's operation and security. -- **Buying coretime**: Used to purchase coretime in-bulk or on-demand and access the chain to benefit from Polkadot's security and interoperability. - -Additionally, DOT can serve as a transferable token. For example, DOT, held in the treasury, can be allocated to teams developing projects that benefit the Polkadot ecosystem. - -## JAM and the Road Ahead - -The Join-Accumulate Machine (JAM) represents a transformative redesign of Polkadot's core architecture, envisioned as the successor to the current relay chain. Unlike traditional blockchain architectures, JAM introduces a unique computational model that processes work through two primary functions: - -- **Join**: Handles data integration. -- **Accumulate**: Folds computations into the chain's state. - -JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: - -- **Permissionless code execution**: JAM is designed to be more generic and flexible, allowing for permissionless code execution through services that can be deployed without governance approval. -- **More effective block time utilization**: JAM's efficient pipeline processing model places the prior state root in block headers instead of the posterior state root, enabling more effective utilization of block time for computations. - -This architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes. - - ---- - -Page Title: Parachains Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/ -- Summary: Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. - -# Parachains Overview - -## Introduction - -A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network. - -Unlike standalone blockchains that must bootstrap their own validator sets and security, parachains leverage Polkadot's pooled security model. This allows parachain developers to focus on their application-specific functionality rather than consensus and security infrastructure. Parachains can communicate with each other through Cross-Consensus Messaging (XCM), enabling seamless interoperability across the Polkadot ecosystem. - -Key capabilities that parachains provide include: - -- **Shared security**: Inherit security from Polkadot's validator set without maintaining your own. -- **Interoperability**: Communicate trustlessly with other parachains via XCM. -- **Scalability**: Process transactions in parallel with other parachains. -- **Customization**: Build application-specific logic tailored to your use case. -- **Upgradeability**: Upgrade runtime logic without hard forks. - -## Polkadot SDK: Parachain Architecture - -Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: - -![](/images/reference/parachains/index/overview-01.webp) - -- **[Substrate](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html){target=\_blank}**: The foundation providing core blockchain primitives and libraries. -- **[FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank}**: A modular framework for building your parachain's runtime logic. -- **[Cumulus](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html){target=\_blank}**: Essential libraries and pallets that enable parachain functionality. -- **[XCM (Cross Consensus Messaging)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/xcm/index.html){target=\_blank}**: The messaging format for communicating with other parachains and the relay chain. -- **[Polkadot](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/polkadot/index.html){target=\_blank}**: The relay chain that provides security and coordination. - -### Substrate: The Foundation - -Substrate provides the core infrastructure that every parachain is built upon. It handles the low-level blockchain functionality, allowing you to focus on your application's unique features. Substrate includes implementations for networking, database management, consensus participation, and the execution environment for your runtime. - -Every Polkadot SDK node consists of two main components: - -- **Client (Host)**: Handles infrastructure services. - - - Native binary that runs on validator and collator nodes. - - Executes the Wasm-compiled runtime. - - Manages networking, database, mempool, and block production. - - Interfaces with the relay chain for validation. - -- **Runtime (State Transition Function)**: Contains your business logic. - - - Defines how your Polkadot SDK node processes transactions. - - Compiled to [Wasm](https://webassembly.org/){target=\_blank} for deterministic execution. - - Stored on-chain and upgradeable via governance. - -```mermaid -%%{init: {'flowchart': {'padding': 5, 'nodeSpacing': 50, 'rankSpacing': 10}}}%% -graph TB - classDef title font-size:20px,font-weight:bold,stroke-width:0px - classDef clientStyle font-size:16px,font-weight:bold - classDef clientSubNodeStyle margin-top:10px - classDef runtimeCallExecutorStyle padding-top:10px - - subgraph sg1[Parachain
    Node] - direction TB - - I[RuntimeCall Executor] - B[Wasm Runtime - STF] - - subgraph sg2[Client] - direction TB - C[Network and Blockchain
    Infrastructure Services
    + Relay Chain Interface] - end - - I --> B - end - - class sg1 title - class sg2 clientStyle - class C clientSubNodeStyle - class I runtimeCallExecutorStyle - -``` - -### FRAME: Building Blocks for Your Runtime - -FRAME provides modular components called [pallets](/reference/glossary#pallet){target=\_blank} that you can compose to build your parachain's runtime. Each pallet provides specific functionality that you can customize and configure for your needs. This modular approach allows you to quickly assemble complex functionality without writing everything from scratch. - -```mermaid -graph LR - subgraph SP["Parachain Runtime"] - direction LR - Timestamp ~~~ Aura ~~~ ParachainSystem - Balances ~~~ TransactionPayment ~~~ Sudo - subgraph Timestamp["Timestamp"] - SS1[Custom Config] - end - subgraph Aura["Aura"] - SS2[Custom Config] - end - subgraph ParachainSystem["Parachain System"] - SS3[Custom Config] - end - subgraph Balances["Balances"] - SS4[Custom Config] - end - subgraph TransactionPayment["Transaction Payment"] - SS5[Custom Config] - end - subgraph Sudo["Sudo"] - SS6[Custom Config] - end - style Timestamp stroke:#FF69B4 - style Aura stroke:#FF69B4 - style ParachainSystem stroke:#FF69B4 - style Balances stroke:#FF69B4 - style TransactionPayment stroke:#FF69B4 - style Sudo stroke:#FF69B4 - style SS1 stroke-dasharray: 5 - style SS2 stroke-dasharray: 5 - style SS3 stroke-dasharray: 5 - style SS4 stroke-dasharray: 5 - style SS5 stroke-dasharray: 5 - style SS6 stroke-dasharray: 5 - - end - subgraph AP["Available FRAME Pallets"] - direction LR - A1[Aura]~~~A2[Parachain
    System]~~~A3[Transaction
    Payment]~~~A4[Sudo] - B1[Identity]~~~B2[Balances]~~~B3[Assets]~~~B4[EVM] - C1[Timestamp]~~~C2[Staking]~~~C3[Contracts]~~~C4[and more...] - end - AP --> SP -``` - -### Cumulus: Parachain-Specific Functionality - -Cumulus is what transforms a Polkadot SDK-based runtime into a parachain-capable runtime. It provides the essential components for communicating with the relay chain, participating in Polkadot's consensus, and handling parachain-specific operations like block validation and collation. - -Key Cumulus components include: - -- **Parachain system pallet**: Core parachain functionality and relay chain communication. -- **Collator consensus**: Block production logic for parachain collators. -- **Relay chain interface**: APIs for interacting with the Polkadot relay chain. -- **Validation data**: Handling proof-of-validity data required by relay chain validators. - -## Where to Go Next - -Building a parachain requires understanding the relationship between your chain and the Polkadot relay chain. The Polkadot SDK provides all the tools needed to design custom runtime logic, enable cross-chain communication, and deploy your parachain to production. - -The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. - -
    - -- Guide __Launch a Simple Parachain__ - - --- - - Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. - - [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) - - -- Guide __Customize Your Runtime__ - - --- - - Design your parachain's runtime logic and choose appropriate pallets for your use case. - - [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) - -- Guide __Interoperability__ - - --- + Ensure to replace `"INSERT_LOCAL_PRIVATE_KEY"` with a private key available in the local environment (you can get them from this [file](https://github.com/paritytech/hardhat-polkadot/blob/main/packages/hardhat-polkadot-node/src/constants.ts#L22){target=\_blank}). And `"INSERT_AH_PRIVATE_KEY"` with the account's private key you want to use to deploy the contracts. You can get this by exporting the private key from your wallet (e.g., MetaMask). - Implement XCM for trustless cross-chain communication with other parachains. + !!!warning + Keep your private key safe, and never share it with anyone. If it is compromised, your funds can be stolen. - [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/) +5. Compile the contracts: -- Guide __Runtime Upgrades__ + ```bash + npx hardhat compile + ``` - --- +If the compilation is successful, you should see the following output: - Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. +
    + npx hardhat compile + Compiling 12 Solidity files + Successfully compiled 12 Solidity files +
    - [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) +After running the above command, you should see the compiled contracts in the `artifacts-pvm` directory. This directory contains the ABI and bytecode of your contracts. -
    +## Understanding Uniswap V2 Architecture +Before interacting with the contracts, it's essential to understand the core architecture that powers Uniswap V2. This model forms the basis of nearly every modern DEX implementation and operates under automated market making, token pair liquidity pools, and deterministic pricing principles. ---- +At the heart of Uniswap V2 lies a simple but powerful system composed of two major smart contracts: -Page Title: Polkadart +- **Factory contract**: The factory acts as a registry and creator of new trading pairs. When two ERC-20 tokens are to be traded, the Factory contract is responsible for generating a new Pair contract that will manage that specific token pair’s liquidity pool. It keeps track of all deployed pairs and ensures uniqueness—no duplicate pools can exist for the same token combination. +- **Pair contract**: Each pair contract is a decentralized liquidity pool that holds reserves of two ERC-20 tokens. These contracts implement the core logic of the AMM, maintaining a constant product invariant (x \* y = k) to facilitate swaps and price determination. Users can contribute tokens to these pools in return for LP (liquidity provider) tokens, which represent their proportional share of the reserves. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/polkadart/ -- Summary: Polkadart is a type-safe, native Dart, SDK for Polkadot and any compatible Polkadot-SDK blockchain network. +This minimal architecture enables Uniswap to be highly modular, trustless, and extensible. By distributing responsibilities across these components, developers, and users can engage with the protocol in a composable and predictable manner, making it an ideal foundation for DEX functionality across ecosystems, including Polkadot Hub. -# Polkadart +The project scaffolding is as follows: -Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications. +```bash +uniswap-V2-polkadot +├── bin/ +├── contracts/ +│ ├── interfaces/ +│ │ ├── IERC20.sol +│ │ ├── IUniswapV2Callee.sol +│ │ ├── IUniswapV2ERC20.sol +│ │ ├── IUniswapV2Factory.sol +│ │ └── IUniswapV2Pair.sol +│ ├── libraries/ +│ │ ├── Math.sol +│ │ ├── SafeMath.sol +│ │ └── UQ112x112.sol +│ ├── test/ +│ │ └── ERC20.sol +│ ├── UniswapV2ERC20.sol +│ ├── UniswapV2Factory.sol +│ └── UniswapV2Pair.sol +├── ignition/ +├── scripts/ +│ └── deploy.js +├── node_modules/ +├── test/ +│ ├── shared/ +│ │ ├── fixtures.js +│ │ └── utilities.js +│ ├── UniswapV2ERC20.js +│ ├── UniswapV2Factory.js +│ └── UniswapV2Pair.js +├── .env.example +├── .gitignore +├── hardhat.config.js +├── package.json +└── README.md +``` -This page will outline some of the core components of Polkadart. For more details, refer to the [official documentation](https://polkadart.dev){target=\_blank}. +## Test the Contracts -## Installation +You can run the provided test suite to ensure the contracts are working as expected. The tests cover various scenarios, including creating pairs, adding liquidity, and executing swaps. -Add Polkadart to your `pubspec.yaml`: +To test it locally, you can run the following commands: -=== "All packages" +1. Spawn a local node for testing: ```bash - dart pub add polkadart polkadart_cli polkadart_keyring polkadart_scale_codec secp256k1_ecdsa sr25519 ss58 substrate_bip39 substrate_metadata + npx hardhat node ``` -=== "Core only" + This command will spawn a local Substrate node along with the ETH-RPC adapter. The node will be available at `ws://127.0.0.1:8000` and the ETH-RPC adapter at `http://localhost:8545`. + +2. In a new terminal, run the tests: ```bash - dart pub add polkadart polkadart_cli polkadart_keyring + npx hardhat test --network localNode ``` -For type-safe API generation, add the following to your `pubspec.yaml`: - -{% raw %} -```yaml title="pubspec.yaml" -polkadart: - output_dir: lib/generated - chains: - polkadot: wss://rpc.polkadot.io - kusama: wss://kusama-rpc.polkadot.io - custom: wss://your-node.example.com -``` -{% endraw %} +The result should look like this: -## Get Started +
    + npx hardhat test --network localNode + Compiling 12 Solidity files + Successfully compiled 12 Solidity files + + UniswapV2ERC20 + ✔ name, symbol, decimals, totalSupply, balanceOf, DOMAIN_SEPARATOR, PERMIT_TYPEHASH (44ms) + ✔ approve (5128ms) + ✔ transfer (5133ms) + ✔ transfer:fail + ✔ transferFrom (6270ms) + ✔ transferFrom:max (6306ms) + + UniswapV2Factory + ✔ feeTo, feeToSetter, allPairsLength + ✔ createPair (176ms) + ✔ createPair:reverse (1224ms) + ✔ setFeeTo (1138ms) + ✔ setFeeToSetter (1125ms) + + UniswapV2Pair + ✔ mint (11425ms) + ✔ getInputPrice:0 (12590ms) + ✔ getInputPrice:1 (17600ms) + ✔ getInputPrice:2 (17618ms) + ✔ getInputPrice:3 (17704ms) + ✔ getInputPrice:4 (17649ms) + ✔ getInputPrice:5 (17594ms) + ✔ getInputPrice:6 (13643ms) + ✔ optimistic:0 (17647ms) + ✔ optimistic:1 (17946ms) + ✔ optimistic:2 (17657ms) + ✔ optimistic:3 (21625ms) + ✔ swap:token0 (12665ms) + ✔ swap:token1 (17631ms) + ✔ burn (17690ms) + ✔ feeTo:off (23900ms) + ✔ feeTo:on (24991ms) + + 28 passing (12m) +
    -### Type Generation +## Deploy the Contracts -Polkadart provides a CLI tool to generate type definitions from any Polkadot-SDK compatible blockchain network. This allows you to build type-safe Dart applications without dealing with the low-level details of the blockchain. +After successfully testing the contracts, you can deploy them to the local node or Polkadot Hub. The deployment script is located in the `scripts` directory and is named `deploy.js`. This script deploys the `Factory` and `Pair` contracts to the network. -### Run Generator +To deploy the contracts, run the following command: ```bash -dart run polkadart_cli:generate -v -``` - -### Use Generated Types - -```dart -import 'package:your_app/generated/polkadot/polkadot.dart'; -import 'package:polkadart/polkadart.dart'; -import 'package:ss58/ss58.dart'; - -final provider = Provider.fromUri(Uri.parse('wss://rpc.polkadot.io')); -final polkadot = Polkadot(provider); - -// Account from SS58 address -final account = Address.decode('19t9Q2ay58hMDaeg6eeBhqmHsRnc2jDMV3cYYw9zbc59HLj'); - -// Retrieve Account Balance -final accountInfo = await polkadot.query.system.account(account.pubkey); -print('Balance: ${accountInfo.data.free}') +npx hardhat run scripts/deploy.js --network localNode ``` -### Creating an API Instance - -An API instance is required to interact with the blockchain. Polkadart provides a `Provider` class that allows you to connect to any network. - -```dart -import 'package:demo/generated/polkadot/polkadot.dart'; -import 'package:polkadart/provider.dart'; +This command deploys the contracts to your local blockchain for development and testing. If you want to deploy to Polkadot Hub, you can use the following command: -Future main(List arguments) async { - final provider = Provider.fromUri(Uri.parse('wss://rpc.polkadot.io')); - final polkadot = Polkadot(provider); -} +```bash +npx hardhat run scripts/deploy.js --network passetHub ``` -### Reading Chain Data - -Besides querying the data using the `query` from the generated API, you can also use the State API for querying storage data, metadata, runtime information, and other chain information. - -```dart -final stateApi = StateApi(provider); - -// Get current runtime version -final runtimeVersion = await stateApi.getRuntimeVersion(); -print(runtimeVersion.toJson()); +The command above deploys to the actual Polkadot TestNet. It requires PAS test tokens, persists on the network, and operates under real network conditions. -// Get metadata -final metadata = await stateApi.getMetadata(); -print('Metadata version: ${metadata.version}'); -``` +The deployment script will output the addresses of the deployed contracts. Save these addresses, as you will need them to interact with the contracts. For example, the output should look like this: -### Subscribe to New Blocks +
    + npx hardhat run scripts/deploy.js --network localNode + Successfully compiled 12 Solidity files + Deploying contracts using 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac + Deploying UniswapV2ERC20... + ETH deployed to : 0x7acc1aC65892CF3547b1b0590066FB93199b430D + Deploying UniswapV2Factory... + Factory deployed to : 0x85b108660f47caDfAB9e0503104C08C1c96e0DA9 + Deploying UniswapV2Pair with JsonRpcProvider workaround... + Pair deployed to : 0xF0e46847c8bFD122C4b5EEE1D4494FF7C5FC5104 +
    -You can subscribe to new blocks on the blockchain using the `subscribe` method. +## Conclusion -```dart -final subscription = await provider.subscribe('chain_subscribeNewHeads', []); +This tutorial guided you through deploying Uniswap V2 contracts to Polkadot Hub. This implementation brings the powerful AMM architecture to the Polkadot ecosystem, laying the foundation for the decentralized trading of ERC-20 token pairs. -subscription.stream.forEach((response) { - print('New head: ${response.result}'); -}); -``` +By following this guide, you've gained practical experience with: -### Send a Transaction - -Perhaps the most common operation done in any blockchain is transferring funds. Here you can see how that can be done using Polkadart: - -```dart -final wallet = await KeyPair.sr25519.fromUri("//Alice"); -print('Alice\' wallet: ${wallet.address}'); - -// Get information necessary to build a proper extrinsic -final runtimeVersion = await polkadot.rpc.state.getRuntimeVersion(); -final currentBlockNumber = (await polkadot.query.system.number()) - 1; -final currentBlockHash = await polkadot.query.system.blockHash(currentBlockNumber); -final genesisHash = await polkadot.query.system.blockHash(0); -final nonce = await polkadot.rpc.system.accountNextIndex(wallet.address); - -// Make the encoded call -final multiAddress = $MultiAddress().id(wallet.publicKey.bytes); -final transferCall = polkadot.tx.balances.transferKeepAlive(dest: multiAddress, value: BigInt.one).encode(); - -// Make the payload -final payload = SigningPayload( - method: transferCall, - specVersion: runtimeVersion.specVersion, - transactionVersion: runtimeVersion.transactionVersion, - genesisHash: encodeHex(genesisHash), - blockHash: encodeHex(currentBlockHash), - blockNumber: currentBlockNumber, - eraPeriod: 64, - nonce: nonce, - tip: 0, -).encode(polkadot.registry); - -// Sign the payload and build the final extrinsic -final signature = wallet.sign(payload); -final extrinsic = ExtrinsicPayload( - signer: wallet.bytes(), - method: transferCall, - signature: signature, - eraPeriod: 64, - blockNumber: currentBlockNumber, - nonce: nonce, - tip: 0, -).encode(polkadot.registry, SignatureType.sr25519); - -// Send the extrinsic to the blockchain -final author = AuthorApi(provider); -await author.submitAndWatchExtrinsic(extrinsic, (data) { - print(data); -}); -``` +- Setting up a Hardhat project for deploying to Polkadot Hub. +- Understanding the Uniswap V2 architecture. +- Testing Uniswap V2 contracts in a local environment. +- Deploying contracts to both local and testnet environments. -## Where to Go Next +To build on this foundation, you could extend this project by implementing functionality to create liquidity pools, execute token swaps, and build a user interface for interacting with your deployment. -To dive deeper into Polkadart, refer to the [official Polkadart documentation](https://polkadart.dev/){target=\_blank}, where you can find comprehensive guides for common use cases and advanced usage. +This knowledge can be leveraged to build more complex DeFi applications or to integrate Uniswap V2 functionality into your existing projects on Polkadot. --- -Page Title: Polkadot SDK Accounts +Page Title: Dual Virtual Machine Stack -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/accounts/ -- Summary: Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/ +- Summary: Compare Polkadot’s dual smart contract VMs—REVM for EVM compatibility and PolkaVM for RISC-V performance, flexibility, and efficiency. -# Accounts +# Dual Virtual Machine Stack +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains. - -This page will guide you through the essential aspects of accounts, including their data structure, balance types, reference counters, and address formats. You’ll learn how accounts are managed within the runtime, how balances are categorized, and how addresses are encoded and validated. - -## Account Data Structure - -Accounts are foundational to any blockchain, and the Polkadot SDK provides a flexible management system. This section explains how the Polkadot SDK defines accounts and manages their lifecycle through data structures within the runtime. - -### Account - -The [`Account` data type](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/type.Account.html){target=\_blank} is a storage map within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank} that links an account ID to its corresponding data. This structure is fundamental for mapping account-related information within the chain. - -The code snippet below shows how accounts are defined: - -```rs - /// The full account information for a particular account ID. - #[pallet::storage] - #[pallet::getter(fn account)] - pub type Account = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - AccountInfo, - ValueQuery, - >; -``` - -The preceding code block defines a storage map named `Account`. The `StorageMap` is a type of on-chain storage that maps keys to values. In the `Account` map, the key is an account ID, and the value is the account's information. Here, `T` represents the generic parameter for the runtime configuration, which is defined by the pallet's configuration trait (`Config`). - -The `StorageMap` consists of the following parameters: - -- **`_`**: Used in macro expansion and acts as a placeholder for the storage prefix type. Tells the macro to insert the default prefix during expansion. -- **`Blake2_128Concat`**: The hashing function applied to keys in the storage map. -- **`T: :AccountId`**: Represents the key type, which corresponds to the account’s unique ID. -- **`AccountInfo`**: The value type stored in the map. For each account ID, the map stores an `AccountInfo` struct containing: - - - **`T::Nonce`**: A nonce for the account, which is incremented with each transaction to ensure transaction uniqueness. - - **`T: :AccountData`**: Custom account data defined by the runtime configuration, which could include balances, locked funds, or other relevant information. - -- **`ValueQuery`**: Defines how queries to the storage map behave when no value is found; returns a default value instead of `None`. - -For a detailed explanation of storage maps, see the [`StorageMap`](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/struct.StorageMap.html){target=\_blank} entry in the Rust docs. - -### Account Info - -The `AccountInfo` structure is another key element within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank}, providing more granular details about each account's state. This structure tracks vital data, such as the number of transactions and the account’s relationships with other modules. - -```rs -/// Information of an account. -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct AccountInfo { - /// The number of transactions this account has sent. - pub nonce: Nonce, - /// The number of other modules that currently depend on this account's existence. The account - /// cannot be reaped until this is zero. - pub consumers: RefCount, - /// The number of other modules that allow this account to exist. The account may not be reaped - /// until this and `sufficients` are both zero. - pub providers: RefCount, - /// The number of modules that allow this account to exist for their own purposes only. The - /// account may not be reaped until this and `providers` are both zero. - pub sufficients: RefCount, - /// The additional data that belongs to this account. Used to store the balance(s) in a lot of - /// chains. - pub data: AccountData, -} -``` - -The `AccountInfo` structure includes the following components: - -- **`nonce`**: Tracks the number of transactions initiated by the account, which ensures transaction uniqueness and prevents replay attacks. -- **`consumers`**: Counts how many other modules or pallets rely on this account’s existence. The account cannot be removed from the chain (reaped) until this count reaches zero. -- **`providers`**: Tracks how many modules permit this account’s existence. An account can only be reaped once both `providers` and `sufficients` are zero. -- **`sufficients`**: Represents the number of modules that allow the account to exist for internal purposes, independent of any other modules. -- **`AccountData`**: A flexible data structure that can be customized in the runtime configuration, usually containing balances or other user-specific data. - -This structure helps manage an account's state and prevents its premature removal while it is still referenced by other on-chain data or modules. The [`AccountInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.AccountInfo.html){target=\_blank} structure can vary as long as it satisfies the trait bounds defined by the `AccountData` associated type in the [`frame-system::pallet::Config`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/trait.Config.html){target=\_blank} trait. - -### Account Reference Counters - -Polkadot SDK uses reference counters to track an account’s dependencies across different runtime modules. These counters ensure that accounts remain active while data is associated with them. - -The reference counters include: - -- **`consumers`**: Prevents account removal while other pallets still rely on the account. -- **`providers`**: Ensures an account is active before other pallets store data related to it. -- **`sufficients`**: Indicates the account’s independence, ensuring it can exist even without a native token balance, such as when holding sufficient alternative assets. - -#### Providers Reference Counters - -The `providers` counter ensures that an account is ready to be depended upon by other runtime modules. For example, it is incremented when an account has a balance above the existential deposit, which marks the account as active. - -The system requires this reference counter to be greater than zero for the `consumers` counter to be incremented, ensuring the account is stable before any dependencies are added. - -#### Consumers Reference Counters - -The `consumers` counter ensures that the account cannot be reaped until all references to it across the runtime have been removed. This check prevents the accidental deletion of accounts that still have active on-chain data. - -It is the user’s responsibility to clear out any data from other runtime modules if they wish to remove their account and reclaim their existential deposit. - -#### Sufficients Reference Counter - -The `sufficients` counter tracks accounts that can exist independently without relying on a native account balance. This is useful for accounts holding other types of assets, like tokens, without needing a minimum balance in the native token. - -For instance, the [Assets pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank}, may increment this counter for an account holding sufficient tokens. - -#### Account Deactivation - -In Polkadot SDK-based chains, an account is deactivated when its reference counters (such as `providers`, `consumers`, and `sufficient`) reach zero. These counters ensure the account remains active as long as other runtime modules or pallets reference it. +Polkadot's smart contract platform supports two distinct virtual machine (VM) architectures, providing developers with flexibility in selecting the optimal execution backend for their specific needs. This approach strikes a balance between immediate Ethereum compatibility and long-term innovation, enabling developers to deploy either unmodified (Ethereum Virtual Machine) EVM contracts using Rust Ethereum Virtual Machine (REVM) or optimize for higher performance using PolkaVM (PVM). -When all dependencies are cleared and the counters drop to zero, the account becomes deactivated and may be removed from the chain (reaped). This is particularly important in Polkadot SDK-based blockchains, where accounts with balances below the existential deposit threshold are pruned from storage to conserve state resources. +Both VM options share common infrastructure, including RPC interfaces, tooling support, and precompiles. The following sections compare architectures and guide you in selecting the best VM for your project's needs. -Each pallet that references an account has cleanup functions that decrement these counters when the pallet no longer depends on the account. Once these counters reach zero, the account is marked for deactivation. +## Migrate from EVM -#### Updating Counters +The [REVM backend](https://github.com/bluealloy/revm){target=\_blank} integrates a complete Rust implementation of the EVM, enabling Solidity contracts to run unchanged on Polkadot's smart contract platform. -The Polkadot SDK provides runtime developers with various methods to manage account lifecycle events, such as deactivation or incrementing reference counters. These methods ensure that accounts cannot be reaped while still in use. +REVM allows developers to use their existing Ethereum tooling and infrastructure to build on Polkadot. Choose REVM to: -The following helper functions manage these counters: +- Migrate existing Ethereum contracts without modifications. +- Retain exact EVM behavior for audit tools. +- Use developer tools that rely upon inspecting EVM bytecode. +- Prioritize rapid deployment over optimization. +- Work with established Ethereum infrastructure and tooling to build on Polkadot. -- **`inc_consumers()`**: Increments the `consumer` reference counter for an account, signaling that another pallet depends on it. -- **`dec_consumers()`**: Decrements the `consumer` reference counter, signaling that a pallet no longer relies on the account. -- **`inc_providers()`**: Increments the `provider` reference counter, ensuring the account remains active. -- **`dec_providers()`**: Decrements the `provider` reference counter, allowing for account deactivation when no longer in use. -- **`inc_sufficients()`**: Increments the `sufficient` reference counter for accounts that hold sufficient assets. -- **`dec_sufficients()`**: Decrements the `sufficient` reference counter. +REVM enables Ethereum developers to seamlessly migrate to Polkadot, achieving performance and fee improvements without modifying their existing contracts or developer tooling stack. -To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. +## Upgrade to PolkaVM -The `System` pallet offers three query functions to assist developers in tracking account states: +[**PolkaVM**](https://github.com/paritytech/polkavm){target=\_blank} is a custom virtual machine optimized for performance with [RISC-V-based](https://en.wikipedia.org/wiki/RISC-V){target=\_blank} architecture, supporting Solidity and additional high-performance languages. It serves as the core execution environment, integrated directly within the runtime. Choose the PolkaVM for: -- **[`can_inc_consumer()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_inc_consumer){target=\_blank}**: Checks if the account can safely increment the consumer reference. -- **[`can_dec_provider()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_dec_provider){target=\_blank}**: Ensures that no consumers exist before allowing the decrement of the provider counter. -- **[`is_provider_required()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.is_provider_required){target=\_blank}**: Verifies whether the account still has any active consumer references. +- An efficient interpreter for immediate code execution. +- A planned [Just In Time (JIT)](https://en.wikipedia.org/wiki/Just-in-time_compilation){target=\_blank} compiler for optimized performance. +- Dual-mode execution capability, allowing selection of the most appropriate backend for specific workloads. +- Optimized performance for short-running contract calls through the interpreter. -This modular and flexible system of reference counters tightly controls the lifecycle of accounts in Polkadot SDK-based blockchains, preventing the accidental removal or retention of unneeded accounts. You can refer to the [System pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html){target=\_blank} for more details. - +The interpreter remains particularly beneficial for contracts with minimal code execution, as it enables immediate code execution through lazy interpretation. -## Account Balance Types +## Architecture -In the Polkadot ecosystem, account balances are categorized into different types based on how the funds are utilized and their availability. These balance types determine the actions that can be performed, such as transferring tokens, paying transaction fees, or participating in governance activities. Understanding these balance types helps developers manage user accounts and implement balance-dependent logic. +The following key components of PolkaVM work together to enable Ethereum compatibility on Polkadot-based chains. -!!! note "A more efficient distribution of account balance types is in development" - Soon, pallets in the Polkadot SDK will implement the [`Fungible` trait](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} (see the [tracking issue](https://github.com/paritytech/polkadot-sdk/issues/226){target=\_blank} for more details). For example, the [`transaction-storage`](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_storage/index.html){target=\_blank} pallet changed the implementation of the [`Currency`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/currency/index.html){target=\_blank} trait (see the [Refactor transaction storage pallet to use fungible traits](https://github.com/paritytech/polkadot-sdk/pull/1800){target=\_blank} PR for further details): +### Revive Pallet - ```rust - type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - ``` - - To the [`Fungible`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} trait: +[**`pallet_revive`**](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/index.html){target=\_blank} is a runtime module that executes smart contracts by adding extrinsics, runtime APIs, and logic to convert Ethereum-style transactions into formats compatible with Polkadot SDK-based blockchains. It processes Ethereum-style transactions through the following workflow: - ```rust - type BalanceOf = <::Currency as FnInspect<::AccountId>>::Balance; - ``` +```mermaid +sequenceDiagram + participant User as User/dApp + participant Proxy as Ethereum JSON RPC Proxy + participant Chain as Blockchain Node + participant Pallet as pallet_revive - This update will enable more efficient use of account balances, allowing the free balance to be utilized for on-chain activities such as setting proxies and managing identities. - -### Balance Types + User->>Proxy: Submit Ethereum Transaction + Proxy->>Chain: Repackage as Polkadot Compatible Transaction + Chain->>Pallet: Process Transaction + Pallet->>Pallet: Decode Ethereum Transaction + Pallet->>Pallet: Execute Contract via PolkaVM + Pallet->>Chain: Return Results + Chain->>Proxy: Forward Results + Proxy->>User: Return Ethereum-compatible Response +``` -The five main balance types are: +This proxy-based approach eliminates the need for node binary modifications, maintaining compatibility across different client implementations. Preserving the original Ethereum transaction payload simplifies the adaptation of existing tools, which can continue processing familiar transaction formats. -- **Free balance**: Represents the total tokens available to the account for any on-chain activity, including staking, governance, and voting. However, it may not be fully spendable or transferrable if portions of it are locked or reserved. -- **Locked balance**: Portions of the free balance that cannot be spent or transferred because they are tied up in specific activities like [staking](https://wiki.polkadot.com/learn/learn-staking/#nominating-validators){target=\_blank}, [vesting](https://wiki.polkadot.com/learn/learn-guides-transfers/#vested-transfers-with-the-polkadot-js-ui){target=\_blank}, or participating in [governance](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank}. While the tokens remain part of the free balance, they are non-transferable for the duration of the lock. -- **Reserved balance**: Funds locked by specific system actions, such as setting up an [identity](https://wiki.polkadot.com/learn/learn-identity/){target=\_blank}, creating [proxies](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}, or submitting [deposits for governance proposals](https://wiki.polkadot.com/learn/learn-guides-polkadot-opengov/#claiming-opengov-deposits){target=\_blank}. These tokens are not part of the free balance and cannot be spent unless they are unreserved. -- **Spendable balance**: The portion of the free balance that is available for immediate spending or transfers. It is calculated by subtracting the maximum of locked or reserved amounts from the free balance, ensuring that existential deposit limits are met. -- **Untouchable balance**: Funds that cannot be directly spent or transferred but may still be utilized for on-chain activities, such as governance participation or staking. These tokens are typically tied to certain actions or locked for a specific period. +### PolkaVM Design Fundamentals -The spendable balance is calculated as follows: +PolkaVM differs from the EVM in two key ways that make it faster, more hardware-efficient, and easier to extend: -```text -spendable = free - max(locked - reserved, ED) -``` +- **Register-based design**: Instead of a stack machine, PolkaVM uses a RISC-V–style register model. This design: -Here, `free`, `locked`, and `reserved` are defined above. The `ED` represents the [existential deposit](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank}, the minimum balance required to keep an account active and prevent it from being reaped. You may find you can't see all balance types when looking at your account via a wallet. Wallet providers often display only spendable, locked, and reserved balances. + - Uses a fixed set of registers to pass arguments, not an infinite stack. + - Maps cleanly to real hardware like x86-64. + - Simplifies compilation and boosts runtime efficiency. + - Enables tighter control over register allocation and performance tuning. -### Locks +- **64-bit word size**: PolkaVM runs on a native 64-bit word size, aligning directly with modern CPUs. This design: -Locks are applied to an account's free balance, preventing that portion from being spent or transferred. Locks are automatically placed when an account participates in specific on-chain activities, such as staking or governance. Although multiple locks may be applied simultaneously, they do not stack. Instead, the largest lock determines the total amount of locked tokens. + - Executes arithmetic operations with direct hardware support. + - Maintains compatibility with Solidity’s 256-bit types via YUL translation. + - Accelerates computation-heavy workloads through native word alignment. + - Integrates easily with low-level, performance-focused components. -Locks follow these basic rules: +## Where To Go Next -- If different locks apply to varying amounts, the largest lock amount takes precedence. -- If multiple locks apply to the same amount, the lock with the longest duration governs when the balance can be unlocked. +
    -#### Locks Example +- Learn __Contract Deployment__ -Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: + --- -- 80 DOT is staked with a 28-day lock period. -- 24 DOT is locked for governance with a 1x conviction and a 7-day lock period. -- 4 DOT is locked for governance with a 6x conviction and a 224-day lock period. + Learn how REVM and PVM compare for compiling and deploying smart contracts. -In this case, the total locked amount is 80 DOT because only the largest lock (80 DOT from staking) governs the locked balance. These 80 DOT will be released at different times based on the lock durations. In this example, the 24 DOT locked for governance will be released first since the shortest lock period is seven days. The 80 DOT stake with a 28-day lock period is released next. Now, all that remains locked is the 4 DOT for governance. After 224 days, all 80 DOT (minus the existential deposit) will be free and transferable. + [:octicons-arrow-right-24: Reference](/smart-contracts/for-eth-devs/contract-deployment/) -![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) +
    -#### Edge Cases for Locks -In scenarios where multiple convictions and lock periods are active, the lock duration and amount are determined by the longest period and largest amount. For example, if you delegate with different convictions and attempt to undelegate during an active lock period, the lock may be extended for the full amount of tokens. For a detailed discussion on edge case lock behavior, see this [Stack Exchange post](https://substrate.stackexchange.com/questions/5067/delegating-and-undelegating-during-the-lock-period-extends-it-for-the-initial-am){target=\_blank}. +--- -### Balance Types on Polkadot.js +Page Title: Get Started with Parachain Development -Polkadot.js provides a user-friendly interface for managing and visualizing various account balances on Polkadot and Kusama networks. When interacting with Polkadot.js, you will encounter multiple balance types that are critical for understanding how your funds are distributed and restricted. This section explains how different balances are displayed in the Polkadot.js UI and what each type represents. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/get-started/ +- Summary: Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. -![](/images/reference/parachains/accounts/accounts-02.webp) +# Get Started -The most common balance types displayed on Polkadot.js are: +The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. -- **Total balance**: The total number of tokens available in the account. This includes all tokens, whether they are transferable, locked, reserved, or vested. However, the total balance does not always reflect what can be spent immediately. In this example, the total balance is 0.6274 KSM. +## Quick Start Guides -- **Transferable balance**: Shows how many tokens are immediately available for transfer. It is calculated by subtracting the locked and reserved balances from the total balance. For example, if an account has a total balance of 0.6274 KSM and a transferable balance of 0.0106 KSM, only the latter amount can be sent or spent freely. +Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. -- **Vested balance**: Tokens that allocated to the account but released according to a specific schedule. Vested tokens remain locked and cannot be transferred until fully vested. For example, an account with a vested balance of 0.2500 KSM means that this amount is owned but not yet transferable. +| Tutorial | Tools | Description | +| :--------------------------------------------------------------------------------------------: | :----------------------------: | :---------------------------------------------------------------------: | +| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | Learn how to set up and run the Polkadot SDK Parachain Template locally | +| [Launch a Local Parachain](/parachains/testing/run-a-parachain-network/) | Zombienet, Chopsticks | Set up a local development environment for testing | +| [Connect to Polkadot](/chain-interactions/query-on-chain-data/query-sdks/) | Polkadot.js, Substrate Connect | Connect your application to Polkadot networks | +| [Fork an Existing Parachain](/parachains/testing/fork-a-parachain/) | Chopsticks | Create a local fork of a live parachain for testing | -- **Locked balance**: Tokens that are temporarily restricted from being transferred or spent. These locks typically result from participating in staking, governance, or vested transfers. In Polkadot.js, locked balances do not stack—only the largest lock is applied. For instance, if an account has 0.5500 KSM locked for governance and staking, the locked balance would display 0.5500 KSM, not the sum of all locked amounts. +## Launch a Simple Parachain -- **Reserved balance**: Refers to tokens locked for specific on-chain actions, such as setting an identity, creating a proxy, or making governance deposits. Reserved tokens are not part of the free balance, but can be freed by performing certain actions. For example, removing an identity would unreserve those funds. +Learn the fundamentals of launching and deploying a parachain to the Polkadot network. -- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period. +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------: | +| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | +| [Deploy to Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/) | Step-by-step tutorial to deploying your parachain to Polkadot | +| [Obtain Coretime](/parachains/launch-a-parachain/obtain-coretime/) | Learn how to acquire blockspace using Polkadot's coretime model (RegionX) | -- **Redeemable balance**: The number of tokens that have completed the unbonding period and are ready to be unlocked and transferred again. For example, if an account has a redeemable balance of 0.1000 KSM, those tokens are now available for spending. +## Customize Your Runtime -- **Democracy balance**: Reflects the number of tokens locked for governance activities, such as voting on referenda. These tokens are locked for the duration of the governance action and are only released after the lock period ends. +Build custom functionality for your parachain by composing and creating pallets. -By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. +| Tutorial | Description | +| :-------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------: | +| [Add Existing Pallets to the Runtime](/parachains/customize-runtime/add-existing-pallets/) | Integrate pre-built pallets from the FRAME ecosystem | +| [Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/) | Configure and use multiple instances of the same pallet | +| [Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/) | Enable smart contract capabilities using Contracts or EVM pallets | -## Address Formats +### Pallet Development -The SS58 address format is a core component of the Polkadot SDK that enables accounts to be uniquely identified across Polkadot-based networks. This format is a modified version of Bitcoin's Base58Check encoding, specifically designed to accommodate the multi-chain nature of the Polkadot ecosystem. SS58 encoding allows each chain to define its own set of addresses while maintaining compatibility and checksum validation for security. +Deep dive into creating and managing custom pallets for your parachain. -### Basic Format +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------: | +| [Create a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/) | Build a pallet from scratch with custom logic | +| [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/) | Set up a mock runtime environment for testing | +| [Pallet Unit Testing](/parachains/customize-runtime/pallet-development/pallet-testing/) | Write comprehensive tests for your pallet logic | +| [Add Your Custom Pallet to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/) | Integrate your custom pallet into your parachain runtime | +| [Benchmark the Custom Pallet](/parachains/customize-runtime/pallet-development/benchmark-pallet/) | Measure and optimize pallet performance with benchmarking | -SS58 addresses consist of three main components: +## Testing -```text -base58encode(concat(,
    , )) -``` +Test your parachain in various environments before production deployment. -- **Address type**: A byte or set of bytes that define the network (or chain) for which the address is intended. This ensures that addresses are unique across different Polkadot SDK-based chains. -- **Address**: The public key of the account encoded as bytes. -- **Checksum**: A hash-based checksum which ensures that addresses are valid and unaltered. The checksum is derived from the concatenated address type and address components, ensuring integrity. +| Tutorial | Description | +| :---------------------------------------------------------------------: | :-----------------------------------------------------: | +| [Fork a Parachain](/parachains/testing/fork-a-parachain/) | Use Chopsticks to create a local fork for testing | +| [Run a Parachain Network](/parachains/testing/run-a-parachain-network/) | Launch a complete parachain test network with Zombienet | -The encoding process transforms the concatenated components into a Base58 string, providing a compact and human-readable format that avoids easily confused characters (e.g., zero '0', capital 'O', lowercase 'l'). This encoding function ([`encode`](https://docs.rs/bs58/latest/bs58/fn.encode.html){target=\_blank}) is implemented exactly as defined in Bitcoin and IPFS specifications, using the same alphabet as both implementations. +## Runtime Upgrades and Maintenance -For more details about the SS58 address format implementation, see the [`Ss58Codec`](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Ss58Codec.html){target=\_blank} trait in the Rust Docs. +Manage your parachain's lifecycle with forkless upgrades and maintenance operations. -### Address Type +| Tutorial | Description | +| :-----------------------------------------------------------------------: | :--------------------------------------------------: | +| [Runtime Upgrades](/parachains/runtime-maintenance/runtime-upgrades/) | Perform forkless runtime upgrades via governance | +| [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/) | Safely migrate storage when updating runtime logic | +| [Unlock Parachains](/parachains/runtime-maintenance/unlock-parachains/) | Understand parachain lifecycle and unlock mechanisms | -The address type defines how an address is interpreted and to which network it belongs. Polkadot SDK uses different prefixes to distinguish between various chains and address formats: +## Interoperability -- **Address types `0-63`**: Simple addresses, commonly used for network identifiers. -- **Address types `64-127`**: Full addresses that support a wider range of network identifiers. -- **Address types `128-255`**: Reserved for future address format extensions. +Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). -For example, Polkadot’s main network uses an address type of 0, while Kusama uses 2. This ensures that addresses can be used without confusion between networks. +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: | +| [Open HRMP Channels Between Parachains](/parachains/interoperability/channels-between-parachains/) | Establish communication channels with other parachains | +| [Open HRMP Channels with System Parachains](/parachains/interoperability/channels-with-system-parachains/) | Connect with Asset Hub and other system parachains | -The address type is always encoded as part of the SS58 address, making it easy to quickly identify the network. Refer to the [SS58 registry](https://github.com/paritytech/ss58-registry){target=\_blank} for the canonical listing of all address type identifiers and how they map to Polkadot SDK-based networks. +## Integrations -### Address Length +Integrate your parachain with essential ecosystem tools and services. -SS58 addresses can have different lengths depending on the specific format. Address lengths range from as short as 3 to 35 bytes, depending on the complexity of the address and network requirements. This flexibility allows SS58 addresses to adapt to different chains while providing a secure encoding mechanism. +| Tutorial | Description | +| :--------------------------------------------: | :----------------------------------------------------: | +| [Wallets](/parachains/integrations/wallets/) | Integrate wallet support for user interactions | +| [Indexers](/parachains/integrations/indexers/) | Set up indexing solutions for querying blockchain data | +| [Oracles](/parachains/integrations/oracles/) | Connect your parachain to off-chain data sources | -| Total | Type | Raw account | Checksum | -|-------|------|-------------|----------| -| 3 | 1 | 1 | 1 | -| 4 | 1 | 2 | 1 | -| 5 | 1 | 2 | 2 | -| 6 | 1 | 4 | 1 | -| 7 | 1 | 4 | 2 | -| 8 | 1 | 4 | 3 | -| 9 | 1 | 4 | 4 | -| 10 | 1 | 8 | 1 | -| 11 | 1 | 8 | 2 | -| 12 | 1 | 8 | 3 | -| 13 | 1 | 8 | 4 | -| 14 | 1 | 8 | 5 | -| 15 | 1 | 8 | 6 | -| 16 | 1 | 8 | 7 | -| 17 | 1 | 8 | 8 | -| 35 | 1 | 32 | 2 | +## Additional Resources -SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. +- [Polkadot SDK Documentation](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/index.html) +- [Polkadot Wiki - Parachains](https://wiki.polkadot.network/docs/learn-parachains/) -### Checksum Types -A checksum is applied to validate SS58 addresses. Polkadot SDK uses a Blake2b-512 hash function to calculate the checksum, which is appended to the address before encoding. The checksum length can vary depending on the address format (e.g., 1-byte, 2-byte, or longer), providing varying levels of validation strength. +--- -The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. +Page Title: Get Started with Smart Contracts -### Validating Addresses +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/get-started/ +- Summary: Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. -SS58 addresses can be validated using the subkey command-line interface or the Polkadot.js API. These tools help ensure an address is correctly formatted and valid for the intended network. The following sections will provide an overview of how validation works with these tools. +# Get Started -#### Using Subkey +This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need. -[Subkey](https://paritytech.github.io/polkadot-sdk/master/subkey/index.html){target=\_blank} is a CLI tool provided by Polkadot SDK for generating and managing keys. It can inspect and validate SS58 addresses. +## Quick Starts -The `inspect` command gets a public key and an SS58 address from the provided secret URI. The basic syntax for the `subkey inspect` command is: +Kick off development fast with curated links for connecting, funding, exploring, and deploying your first contract. -```bash -subkey inspect [flags] [options] uri -``` +| Quick Start | Tools | Description | +|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:| +| [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer | +| [Get Test Tokens](/smart-contracts/faucets/){target=\_blank} | - | Request test funds to deploy and interact with contracts | +| [Explore Transactions](/smart-contracts/explorers/){target=\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state | +| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} | Remix | One‑click browser deployment to Polkadot Hub | +| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\_blank} | Foundry | Scripted deployments and testing from the CLI | +| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} | Hardhat | Project scaffolding, testing, and deployments | -For the `uri` command-line argument, you can specify the secret seed phrase, a hex-encoded private key, or an SS58 address. If the input is a valid address, the `subkey` program displays the corresponding hex-encoded public key, account identifier, and SS58 addresses. +## Build and Test Locally -For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: +Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. -```bash -subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" -``` +| Build and Test Locally | Tools | Description | +|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:| +| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\_blank} | Polkadot SDK node | Spin up a local node for iterative development | +| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts | +| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\_blank} | Remix | Publish verified source on explorers | +| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\_blank} | Foundry | Install toolchain and configure networks | +| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\_blank} | Foundry | Write and run Solidity tests locally | +| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\_blank} | Foundry | Verify deployed bytecode and metadata | +| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} | Hardhat | Initialize a project and configure networks | +| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} | Hardhat | Unit test contracts and run scripts | +| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\_blank} | Hardhat | Verify deployments on explorers | -The command displays output similar to the following: +## Ethereum Developer Resources -
    - subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" - Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account: - Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849 - Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR - Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - SS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR -
    +Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. -The `subkey` program assumes an address is based on a public/private key pair. If you inspect an address, the command returns the 32-byte account identifier. +| Ethereum Developer Guides | Description | +|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:| +| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts | +| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\_blank} | Transaction types, fees, and multi‑dimensional metering | +| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} | Gas vs. weight, proof size, and storage deposits | +| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\_blank} | Deployment patterns and best practices on Polkadot Hub | +| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank} | Supported Ethereum JSON‑RPC methods and examples | +| [Migration](/smart-contracts/for-eth-devs/migration/){target=\_blank} | Port existing apps and tooling to Polkadot Hub | +| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} | Overview of EVM and native execution on the Hub | -However, not all addresses in Polkadot SDK-based networks are based on keys. +## Cookbook: Hands‑on Tutorials -Depending on the command-line options you specify and the input you provided, the command output might also display the network for which the address has been encoded. For example: +Follow step‑by‑step guides that walk through common tasks and complete dApp examples. -```bash -subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" -``` +| Tutorial | Tools | Description | +|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:| +| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} | Remix | Minimal deployment walkthrough | +| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token | +| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection | +| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\_blank} | Hardhat | Full dApp project: compile, test, deploy | +| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\_blank} | Multiple | End‑to‑end dApp patterns and practices | -The command displays output similar to the following: +## Libraries -
    - subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" - Public Key URI `12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU` is account: - Network ID/Version: polkadot - Public key (hex): 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Account ID: 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Public key (SS58): 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU - SS58 Address: 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU -
    +Choose the client libraries that fit your stack for connecting wallets and calling contracts. -#### Using Polkadot.js API +| Library | Description | +|:------------------------------------------------------------------:|:-------------------------------------------------------:| +| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank} | Connect, sign, and interact with contracts using Ethers | +| [viem](/smart-contracts/libraries/viem/){target=\_blank} | Type‑safe EVM interactions and utilities | +| [Wagmi](/smart-contracts/libraries/wagmi/){target=\_blank} | React hooks for wallet connections and contract calls | +| [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank} | Web3 provider and contract APIs | +| [Web3.py](/smart-contracts/libraries/web3-py/){target=\_blank} | Python toolkit for on‑chain interactions and scripts | -To verify an address in JavaScript or TypeScript projects, you can use the functions built into the [Polkadot.js API](https://polkadot.js.org/docs/){target=\_blank}. For example: +## Integrations -```js -// Import Polkadot.js API dependencies -const { decodeAddress, encodeAddress } = require('@polkadot/keyring'); -const { hexToU8a, isHex } = require('@polkadot/util'); +Integrate essential services like wallets, indexers, and oracles to round out your dApp. -// Specify an address to test. -const address = 'INSERT_ADDRESS_TO_TEST'; +| Integration | Description | +|:-------------------------------------------------------------------:|:-----------------------------------------:| +| [Wallets](/smart-contracts/integrations/wallets/){target=\_blank} | Supported wallets and configuration notes | +| [Indexers](/smart-contracts/integrations/indexers/){target=\_blank} | Index and query blockchain data | +| [Oracles](/smart-contracts/integrations/oracles/){target=\_blank} | Bring external data on‑chain | -// Check address -const isValidSubstrateAddress = () => { - try { - encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); +## Precompiles - return true; - } catch (error) { - return false; - } -}; +Discover precompiled system contracts available on the Hub and how to use them. -// Query result -const isValid = isValidSubstrateAddress(); -console.log(isValid); +| Topic | Description | +|:------------------------------------------------------------------------:|:---------------------------------------------------:| +| [Overview of Precompiles](/smart-contracts/precompiles/){target=\_blank} | What precompiles are available on the Hub | +| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\_blank} | EVM precompiles and interfaces | +| [Staking](/smart-contracts/precompiles/staking/){target=\_blank} | Interact with staking functionality via precompiles | +| [XCM](/smart-contracts/precompiles/xcm/){target=\_blank} | Cross‑chain messaging helpers for contracts | -``` +From here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\_blank} or reach out in the community channels. -If the function returns `true`, the specified address is a valid address. -#### Other SS58 Implementations +--- -Support for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries. +Page Title: Get Started with XCM -- **Crystal**: [`wyhaines/base58.cr`](https://github.com/wyhaines/base58.cr){target=\_blank} -- **Go**: [`itering/subscan-plugin`](https://github.com/itering/subscan-plugin){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **TypeScript**: [`subsquid/squid-sdk`](https://github.com/subsquid/squid-sdk){target=\_blank} +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ +- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. +# Get Started with XCM ---- +## Introduction -Page Title: Polkadot-API +Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/papi/ -- Summary: Polkadot-API (PAPI) is a modular, composable library set designed for efficient interaction with Polkadot chains, prioritizing a "light-client first" approach. +With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. -# Polkadot-API +## Messaging Format -## Introduction +XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. -[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications. +XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. -PAPI is optimized for light-client functionality, using the new JSON-RPC spec to support decentralized interactions fully. It provides strong TypeScript support with types and documentation generated directly from on-chain metadata, and it offers seamless access to storage reads, constants, transactions, events, and runtime calls. Developers can connect to multiple chains simultaneously and prepare for runtime updates through multi-descriptor generation and compatibility checks. PAPI is lightweight and performant, leveraging native BigInt, dynamic imports, and modular subpaths to avoid bundling unnecessary assets. It supports promise-based and observable-based APIs, integrates easily with Polkadot.js extensions, and offers signing options through browser extensions or private keys. +## The Four Principles of XCM -## Get Started +XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: -### API Instantiation +- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. +- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. +- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. +- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. -To instantiate the API, you can install the package by using the following command: +These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. -=== "npm" +## The XCM Tech Stack - ```bash - npm i polkadot-api@1.17.2 - ``` +![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) -=== "pnpm" +The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. - ```bash - pnpm add polkadot-api@1.17.2 - ``` +## Core Functionalities of XCM -=== "yarn" +XCM enhances cross-consensus communication by introducing several powerful features: - ```bash - yarn add polkadot-api@1.17.2 - ``` +- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. +- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. +- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. -Then, obtain the latest metadata from the target chain and generate the necessary types: +The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. -```bash -# Add the target chain -npx papi add dot -n polkadot -``` +## XCM Example -The `papi add` command initializes the library by generating the corresponding types needed for the chain used. It assigns the chain a custom name and specifies downloading metadata from the Polkadot chain. You can replace `dot` with the name you prefer or with another chain if you want to add a different one. Once the latest metadata is downloaded, generate the required types: +The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). -```bash -# Generate the necessary types -npx papi +```rust +let message = Xcm(vec![ + WithdrawAsset((Here, amount).into()), + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } +]); ``` -You can now set up a [`PolkadotClient`](https://github.com/polkadot-api/polkadot-api/blob/main/packages/client/src/types.ts#L153){target=\_blank} with your chosen provider to begin interacting with the API. Choose from Smoldot via WebWorker, Node.js, or direct usage, or connect through the WSS provider. The examples below show how to configure each option for your setup. +The message consists of three instructions described as follows: -=== "Smoldot (WebWorker)" +- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. - ```typescript - // `dot` is the identifier assigned during `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - import { getSmProvider } from 'polkadot-api/sm-provider'; - import { chainSpec } from 'polkadot-api/chains/polkadot'; - import { startFromWorker } from 'polkadot-api/smoldot/from-worker'; - import SmWorker from 'polkadot-api/smoldot/worker?worker'; + ```rust + WithdrawAsset((Here, amount).into()), + ``` - const worker = new SmWorker(); - const smoldot = startFromWorker(worker); - const chain = await smoldot.addChain({ chainSpec }); + - **`Here`**: The native parachain token. + - **`amount`**: The number of tokens that are transferred. - // Establish connection to the Polkadot relay chain - const client = createClient(getSmProvider(chain)); + The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. - // To interact with the chain, obtain the `TypedApi`, which provides - // the necessary types for every API call on this chain - const dotApi = client.getTypedApi(dot); +- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. + ```rust + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, ``` -=== "Smoldot (Node.js)" - - ```typescript - // `dot` is the alias assigned during `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - import { getSmProvider } from 'polkadot-api/sm-provider'; - import { chainSpec } from 'polkadot-api/chains/polkadot'; - import { startFromWorker } from 'polkadot-api/smoldot/from-node-worker'; - import { fileURLToPath } from 'url'; - import { Worker } from 'worker_threads'; - - // Get the path for the worker file in ESM - const workerPath = fileURLToPath( - import.meta.resolve('polkadot-api/smoldot/node-worker'), - ); + - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. + - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. - const worker = new Worker(workerPath); - const smoldot = startFromWorker(worker); - const chain = await smoldot.addChain({ chainSpec }); +- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. - // Set up a client to connect to the Polkadot relay chain - const client = createClient(getSmProvider(chain)); + ```rust + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } + ``` - // To interact with the chain's API, use `TypedApi` for access to - // all the necessary types and calls associated with this chain - const dotApi = client.getTypedApi(dot); + - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. + +This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - ``` +## Overview -=== "Smoldot" +XCM revolutionizes cross-chain communication by enabling use cases such as: - ```typescript - // `dot` is the alias assigned when running `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - import { getSmProvider } from 'polkadot-api/sm-provider'; - import { chainSpec } from 'polkadot-api/chains/polkadot'; - import { start } from 'polkadot-api/smoldot'; +- Token transfers between blockchains. +- Asset locking for cross-chain smart contract interactions. +- Remote execution of functions on other blockchains. - // Initialize Smoldot client - const smoldot = start(); - const chain = await smoldot.addChain({ chainSpec }); +These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - // Set up a client to connect to the Polkadot relay chain - const client = createClient(getSmProvider(chain)); - // Access the `TypedApi` to interact with all available chain calls and types - const dotApi = client.getTypedApi(dot); +--- - ``` +Page Title: Indexers -=== "WSS" +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md +- Canonical (HTML): https://docs.polkadot.com/parachains/integrations/indexers/ +- Summary: Discover blockchain indexers. Enhance data access, enable fast and complex queries, and optimize blockchain data for seamless app performance. - ```typescript - // `dot` is the identifier assigned when executing `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - // Use this import for Node.js environments - import { getWsProvider } from 'polkadot-api/ws-provider/web'; - import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat'; +# Indexers - // Establish a connection to the Polkadot relay chain - const client = createClient( - // The Polkadot SDK nodes may have compatibility issues; using this enhancer is recommended. - // Refer to the Requirements page for additional details - withPolkadotSdkCompat(getWsProvider('wss://dot-rpc.stakeworld.io')), - ); +## The Challenge of Blockchain Data Access - // To interact with the chain, obtain the `TypedApi`, which provides - // the types for all available calls in that chain - const dotApi = client.getTypedApi(dot); +Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges: - ``` +- Data is scattered and unorganized across the blockchain. +- Retrieving large datasets can take days or weeks to sync. +- Complex operations (like aggregations, averages, or cross-chain queries) require additional processing. +- Direct blockchain queries can impact dApp performance and responsiveness. -Now that you have set up the client, you can interact with the chain by reading and sending transactions. +## What is a Blockchain Indexer? -### Reading Chain Data +A blockchain indexer is a specialized infrastructure tool that processes, organizes, and stores blockchain data in an optimized format for efficient querying. Think of it as a search engine for blockchain data that: -The `TypedApi` provides a streamlined way to read blockchain data through three main interfaces, each designed for specific data access patterns: +- Continuously monitors the blockchain for new blocks and transactions. +- Processes and categorizes this data according to predefined schemas. +- Stores the processed data in an easily queryable database. +- Provides efficient APIs (typically [GraphQL](https://graphql.org/){target=\_blank}) for data retrieval. -- **Constants**: Access fixed values or configurations on the blockchain using the `constants` interface. +## Indexer Implementations - ```typescript - const version = await typedApi.constants.System.Version(); - ``` +
    -- **Storage queries**: Retrieve stored values by querying the blockchain’s storage via the `query` interface. +- __Subsquid__ - ```typescript - const asset = await api.query.ForeignAssets.Asset.getValue( - token.location, - { at: 'best' }, - ); - ``` + --- -- **Runtime APIs**: Interact directly with runtime APIs using the `apis` interface. + Subsquid is a data network that allows rapid and cost-efficient retrieval of blockchain data from 100+ chains using Subsquid's decentralized data lake and open-source SDK. In simple terms, Subsquid can be considered an ETL (extract, transform, and load) tool with a GraphQL server included. It enables comprehensive filtering, pagination, and even full-text search capabilities. Subsquid has native and full support for EVM and Substrate data, even within the same project. - ```typescript - const metadata = await typedApi.apis.Metadata.metadata(); - ``` + [:octicons-arrow-right-24: Reference](https://www.sqd.ai/){target=\_blank} -To learn more about the different actions you can perform with the `TypedApi`, refer to the [TypedApi reference](https://papi.how/typed){target=\_blank}. +- __Subquery__ -### Sending Transactions + --- -In PAPI, the `TypedApi` provides the `tx` and `txFromCallData` methods to send transactions. + SubQuery is a fast, flexible, and reliable open-source data decentralised infrastructure network that provides both RPC and indexed data to consumers worldwide. + It provides custom APIs for your web3 project across multiple supported chains. -- The `tx` method allows you to directly send a transaction with the specified parameters by using the `typedApi.tx.Pallet.Call` pattern: + [:octicons-arrow-right-24: Reference](https://subquery.network/){target=\_blank} - ```typescript - const tx: Transaction = typedApi.tx.Pallet.Call({arg1, arg2, arg3}); - ``` +
    - For instance, to execute the `balances.transferKeepAlive` call, you can use the following snippet: - ```typescript - import { MultiAddress } from '@polkadot-api/descriptors'; +--- - const tx: Transaction = typedApi.tx.Balances.transfer_keep_alive({ - dest: MultiAddress.Id('INSERT_DESTINATION_ADDRESS'), - value: BigInt(INSERT_VALUE), - }); +Page Title: Install Polkadot SDK - ``` +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md +- Canonical (HTML): https://docs.polkadot.com/parachains/install-polkadot-sdk/ +- Summary: Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. - Ensure you replace `INSERT_DESTINATION_ADDRESS` and `INSERT_VALUE` with the actual destination address and value, respectively. +# Install Polkadot SDK -- The `txFromCallData` method allows you to send a transaction using the call data. This option accepts binary call data and constructs the transaction from it. It validates the input upon creation and will throw an error if invalid data is provided. The pattern is as follows: +This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts: - ```typescript - const callData = Binary.fromHex('0x...'); - const tx: Transaction = typedApi.txFromCallData(callData); - ``` +- **Installing dependencies**: Setting up Rust, required system packages, and development tools. +- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. - For instance, to execute a transaction using the call data, you can use the following snippet: +Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. - ```typescript - const callData = Binary.fromHex('0x00002470617065726d6f6f6e'); - const tx: Transaction = typedApi.txFromCallData(callData); - ``` +## Install Dependencies: macOS -For more information about sending transactions, refer to the [Transactions](https://papi.how/typed/tx#transactions){target=\_blank} page. +You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. -## Where to Go Next +### Before You Begin {: #before-you-begin-mac-os } -For an in-depth guide on how to use PAPI, refer to the official [PAPI](https://papi.how/){target=\_blank} documentation. +Before you install Rust and set up your development environment on macOS, verify that your computer meets the following basic requirements: +- Operating system version is 10.7 Lion or later. +- Processor speed of at least 2 GHz. Note that 3 GHz is recommended. +- Memory of at least 8 GB RAM. Note that 16 GB is recommended. +- Storage of at least 10 GB of available space. +- Broadband Internet connection. ---- +### Install Homebrew -Page Title: Polkadot.js API +In most cases, you should use Homebrew to install and manage packages on macOS computers. If you don't already have Homebrew installed on your local computer, you should download and install it before continuing. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/polkadot-js-api/ -- Summary: Interact with Polkadot SDK-based chains easily using the Polkadot.js API. Query chain data, submit transactions, and more via JavaScript or Typescript. +To install Homebrew: -# Polkadot.js API +1. Open the Terminal application. +2. Download and install Homebrew by running the following command: -!!! warning "Maintenance Mode Only" - The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\_blank} (modern, type-safe API) as actively maintained alternatives. + ```bash + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + ``` -## Introduction +3. Verify Homebrew has been successfully installed by running the following command: -The [Polkadot.js API](https://github.com/polkadot-js/api){target=\_blank} uses JavaScript/TypeScript to interact with Polkadot SDK-based chains. It allows you to query nodes, read chain state, and submit transactions through a dynamic, auto-generated API interface. + ```bash + brew --version + ``` -### Dynamic API Generation + The command displays output similar to the following: -Unlike traditional static APIs, the Polkadot.js API generates its interfaces automatically when connecting to a node. Here's what happens when you connect: +
    + brew --version + Homebrew 4.3.15 +
    -1. The API connects to your node. -2. It retrieves the chain's metadata. -3. Based on this metadata, it creates specific endpoints in this format: `api...
    `. +### Support for Apple Silicon -### Available API Categories +Protobuf must be installed before the build process can begin. To install it, run the following command: -You can access three main categories of chain interactions: +```bash +brew install protobuf +``` -- **[Runtime constants](https://polkadot.js.org/docs/api/start/api.consts){target=\_blank}** (`api.consts`): +### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } - - Access runtime constants directly. - - Returns values immediately without function calls. - - **Example**: `api.consts.balances.existentialDeposit` +Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `openssl`. -- **[State queries](https://polkadot.js.org/docs/api/start/api.query/){target=\_blank}** (`api.query`): +To install `openssl` and the Rust toolchain on macOS: - - Read chain state. - - **Example**: `api.query.system.account(accountId)` +1. Open the Terminal application. +2. Ensure you have an updated version of Homebrew by running the following command: -- **[Transactions](https://polkadot.js.org/docs/api/start/api.tx/){target=\_blank}** (`api.tx`): - - Submit extrinsics (transactions). - - **Example**: `api.tx.balances.transfer(accountId, value)` + ```bash + brew update + ``` -The available methods and interfaces will automatically reflect what's possible on your connected chain. +3. Install the `openssl` package by running the following command: -## Installation + ```bash + brew install openssl + ``` -To add the Polkadot.js API to your project, use the following command to install the version `16.4.7` which supports any Polkadot SDK-based chain: +4. Download the `rustup` installation program and use it to install Rust by running the following command: -=== "npm" ```bash - npm i @polkadot/api@16.4.7 + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -=== "pnpm" +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: + ```bash - pnpm add @polkadot/api@16.4.7 + source ~/.cargo/env ``` -=== "yarn" +7. Configure the Rust toolchain to default to the latest stable version by running the following commands: + ```bash - yarn add @polkadot/api@16.4.7 + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src ``` -For more detailed information about installation, see the [Installation](https://polkadot.js.org/docs/api/start/install/){target=\_blank} section in the official Polkadot.js API documentation. +8. Install `cmake` using the following command: -## Get Started + ```bash + brew install cmake + ``` -### Creating an API Instance +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -To interact with a Polkadot SDK-based chain, you must establish a connection through an API instance. The API provides methods for querying chain state, sending transactions, and subscribing to updates. +## Install Dependencies: Linux -To create an API connection: +Rust supports most Linux distributions. Depending on the specific distribution and version of the operating system you use, you might need to add some software dependencies to your environment. In general, your development environment should include a linker or a C-compatible compiler, such as `clang`, and an appropriate integrated development environment (IDE). -```js -import { ApiPromise, WsProvider } from '@polkadot/api'; +### Before You Begin {: #before-you-begin-linux } -// Create a WebSocket provider -const wsProvider = new WsProvider('wss://rpc.polkadot.io'); +Check the documentation for your operating system for information about the installed packages and how to download and install any additional packages you might need. For example, if you use Ubuntu, you can use the Ubuntu Advanced Packaging Tool (`apt`) to install the `build-essential` package: -// Initialize the API -const api = await ApiPromise.create({ provider: wsProvider }); +```bash +sudo apt install build-essential +``` -// Verify the connection by getting the chain's genesis hash -console.log('Genesis Hash:', api.genesisHash.toHex()); +At a minimum, you need the following packages before you install Rust: +```text +clang curl git make ``` -!!!warning - All `await` operations must be wrapped in an async function or block since the API uses promises for asynchronous operations. +Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `libssl-dev` or `openssl-devel`. + +### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } -### Reading Chain Data +To install the Rust toolchain on Linux: -The API provides several ways to read data from the chain. You can access: +1. Open a terminal shell. +2. Check the packages installed on the local computer by running the appropriate package management command for your Linux distribution. +3. Add any package dependencies you are missing to your local development environment by running the appropriate package management command for your Linux distribution: -- **Constants**: Values that are fixed in the runtime and don't change without a runtime upgrade. + === "Ubuntu" - ```js - // Get the minimum balance required for a new account - const minBalance = api.consts.balances.existentialDeposit.toNumber(); + ```bash + sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler + ``` - ``` + === "Debian" -- **State**: Current chain state that updates with each block. + ```sh + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler + ``` - ```js - // Example address - const address = '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE'; + === "Arch" - // Get current timestamp - const timestamp = await api.query.timestamp.now(); + ```sh + pacman -Syu --needed --noconfirm curl git clang make protobuf + ``` - // Get account information - const { nonce, data: balance } = await api.query.system.account(address); + === "Fedora" - console.log(` - Timestamp: ${timestamp} - Free Balance: ${balance.free} - Nonce: ${nonce} - `); + ```sh + sudo dnf update + sudo dnf install clang curl git openssl-devel make protobuf-compiler + ``` - ``` + === "OpenSUSE" -### Sending Transactions + ```sh + sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf + ``` -Transactions (also called extrinsics) modify the chain state. Before sending a transaction, you need: + Remember that different distributions might use different package managers and bundle packages in different ways. For example, depending on your installation selections, Ubuntu Desktop and Ubuntu Server might have different packages and different requirements. However, the packages listed in the command-line examples are applicable to many common Linux distributions, including Debian, Linux Mint, MX Linux, and Elementary OS. -- A funded account with sufficient balance to pay transaction fees. -- The account's keypair for signing. +4. Download the `rustup` installation program and use it to install Rust by running the following command: -To make a transfer: + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -```js -// Assuming you have an `alice` keypair from the Keyring -const recipient = 'INSERT_RECIPIENT_ADDRESS'; -const amount = 'INSERT_VALUE'; // Amount in the smallest unit (e.g., Planck for DOT) +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: -// Sign and send a transfer -const txHash = await api.tx.balances - .transfer(recipient, amount) - .signAndSend(alice); + ```bash + source $HOME/.cargo/env + ``` -console.log('Transaction Hash:', txHash); +7. Verify your installation by running the following command: -``` + ```bash + rustc --version + ``` -The `alice` keypair in the example comes from a `Keyring` object. For more details about managing keypairs, see the [Keyring documentation](https://polkadot.js.org/docs/keyring){target=\_blank}. +8. Configure the Rust toolchain to default to the latest stable version by running the following commands: -## Where to Go Next + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -For more detailed information about the Polkadot.js API, check the [official documentation](https://polkadot.js.org/docs/){target=\_blank}. +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). +## Install Dependencies: Windows (WSL) ---- +In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. -Page Title: Python Substrate Interface +However, suppose your local computer uses Microsoft Windows instead of a UNIX-based operating system. In that case, you can configure it with additional software to make it a suitable development environment for building Substrate-based blockchains. To prepare a development environment on a Microsoft Windows computer, you can use Windows Subsystem for Linux (WSL) to emulate a UNIX operating environment. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/py-substrate-interface/ -- Summary: Learn how to connect to Polkadot SDK-based nodes, query data, submit transactions, and manage blockchain interactions using the Python Substrate Interface. +### Before You Begin {: #before-you-begin-windows-wls } -# Python Substrate Interface +Before installing on Microsoft Windows, verify the following basic requirements: -## Introduction +- You have a computer running a supported Microsoft Windows operating system: + - **For Windows desktop**: You must be running Microsoft Windows 10, version 2004 or later, or Microsoft Windows 11 to install WSL. + - **For Windows server**: You must be running Microsoft Windows Server 2019, or later, to install WSL on a server operating system. +- You have a good internet connection and access to a shell terminal on your local computer. -The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for: +### Set Up Windows Subsystem for Linux -- Querying on-chain storage. -- Composing and submitting extrinsics. -- SCALE encoding/decoding. -- Interacting with Substrate runtime metadata. -- Managing blockchain interactions through convenient utility methods. +WSL enables you to emulate a Linux environment on a computer that uses the Windows operating system. The primary advantage of this approach for Substrate development is that you can use all of the code and command-line examples as described in the Substrate documentation. For example, you can run common commands—such as `ls` and `ps`—unmodified. By using WSL, you can avoid configuring a virtual machine image or a dual-boot operating system. -## Installation +To prepare a development environment using WSL: -Install the library using `pip`: +1. Check your Windows version and build number to see if WSL is enabled by default. -```py -pip install substrate-interface -``` + If you have Microsoft Windows 10, version 2004 (Build 19041 and higher), or Microsoft Windows 11, WSL is available by default and you can continue to the next step. -For more installation details, see the [Installation](https://jamdottech.github.io/py-polkadot-sdk/getting-started/installation/){target=\_blank} section in the official Python Substrate Interface documentation. + If you have an older version of Microsoft Windows installed, see the [WSL manual installation steps for older versions](https://learn.microsoft.com/en-us/windows/wsl/install-manual){target=\_blank}. If you are installing on an older version of Microsoft Windows, you can download and install WLS 2 if your computer has Windows 10, version 1903 or higher. -## Get Started +2. Select **Windows PowerShell** or **Command Prompt** from the **Start** menu, right-click, then **Run as administrator**. -This guide will walk you through the basic operations with the Python Substrate Interface: connecting to a node, reading chain state, and submitting transactions. +3. In the PowerShell or Command Prompt terminal, run the following command: -### Establishing Connection + ```bash + wsl --install + ``` -The first step is to establish a connection to a Polkadot SDK-based node. You can connect to either a local or remote node: + This command enables the required WSL 2 components that are part of the Windows operating system, downloads the latest Linux kernel, and installs the Ubuntu Linux distribution by default. -```py -from substrateinterface import SubstrateInterface + If you want to review the other Linux distributions available, run the following command: -# Connect to a node using websocket -substrate = SubstrateInterface( - # For local node: "ws://127.0.0.1:9944" - # For Polkadot: "wss://rpc.polkadot.io" - # For Kusama: "wss://kusama-rpc.polkadot.io" - url="INSERT_WS_URL" -) + ```bash + wsl --list --online + ``` -# Verify connection -print(f"Connected to chain: {substrate.chain}") +4. After the distribution is downloaded, close the terminal. -``` +5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. -### Reading Chain State + Restarting the computer is required to start the installation of the Linux distribution. It can take a few minutes for the installation to complete after you restart. -You can query various on-chain storage items. To retrieve data, you need to specify three key pieces of information: + For more information about setting up WSL as a development environment, see the [Set up a WSL development environment](https://learn.microsoft.com/en-us/windows/wsl/setup/environment){target=\_blank} docs. -- **Pallet name**: Module or pallet that contains the storage item you want to access. -- **Storage item**: Specific storage entry you want to query within the pallet. -- **Required parameters**: Any parameters needed to retrieve the desired data. +### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } -Here's an example of how to check an account's balance and other details: +To install the Rust toolchain on WSL: -```py -# ... +1. Click the **Start** menu, then select **Ubuntu**. +2. Type a UNIX user name to create a user account. +3. Type a password for your UNIX user, then retype the password to confirm it. +4. Download the latest updates for the Ubuntu distribution using the Ubuntu Advanced Packaging Tool (`apt`) by running the following command: -# Query account balance and info -account_info = substrate.query( - module="System", # The pallet name - storage_function="Account", # The storage item - params=["INSERT_ADDRESS"], # Account address in SS58 format -) + ```bash + sudo apt update + ``` -# Access account details from the result -free_balance = account_info.value["data"]["free"] -reserved = account_info.value["data"]["reserved"] -nonce = account_info.value["nonce"] +5. Add the required packages for the Ubuntu distribution by running the following command: -print( - f""" - Account Details: - - Free Balance: {free_balance} - - Reserved: {reserved} - - Nonce: {nonce} - """ -) + ```bash + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler + ``` -``` +6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: -### Submitting Transactions + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -To modify the chain state, you need to submit transactions (extrinsics). Before proceeding, ensure you have: +7. Follow the prompts displayed to proceed with a default installation. -- A funded account with sufficient balance to pay transaction fees. -- Access to the account's keypair. +8. Update your current shell to include Cargo by running the following command: -Here's how to create and submit a balance transfer: + ```bash + source ~/.cargo/env + ``` -```py -#... +9. Verify your installation by running the following command: -# Compose the transfer call -call = substrate.compose_call( - call_module="Balances", # The pallet name - call_function="transfer_keep_alive", # The extrinsic function - call_params={ - 'dest': 'INSERT_ADDRESS', # Recipient's address - 'value': 'INSERT_VALUE' # Amount in smallest unit (e.g., Planck for DOT) - } -) - -# Create a signed extrinsic -extrinsic = substrate.create_signed_extrinsic( - call=call, keypair=keypair # Your keypair for signing -) - -# Submit and wait for inclusion -receipt = substrate.submit_extrinsic( - extrinsic, wait_for_inclusion=True # Wait until the transaction is in a block -) - -if receipt.is_success: - print( - f""" - Transaction successful: - - Extrinsic Hash: {receipt.extrinsic_hash} - - Block Hash: {receipt.block_hash} - """ - ) -else: - print(f"Transaction failed: {receipt.error_message}") + ```bash + rustc --version + ``` -``` +10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: -The `keypair` object is essential for signing transactions. See the [Keypair](https://jamdottech.github.io/py-polkadot-sdk/reference/keypair/){target=\_blank} documentation for more details. + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -## Where to Go Next +11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -Now that you understand the basics, you can: +## Build the Polkadot SDK -- Explore more complex queries and transactions. -- Learn about batch transactions and utility functions. -- Discover how to work with custom pallets and types. +After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. -For comprehensive reference materials and advanced features, see the [Python Substrate Interface](https://jamdottech.github.io/py-polkadot-sdk/){target=\_blank} documentation. +### Clone the Polkadot SDK +1. Clone the Polkadot SDK repository: ---- + ```bash + git clone https://github.com/paritytech/polkadot-sdk.git + ``` -Page Title: Randomness +2. Navigate into the project directory: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/randomness/ -- Summary: Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. + ```bash + cd polkadot-sdk + ``` -# Randomness +### Compile the Polkadot SDK -## Introduction +Compile the entire Polkadot SDK repository to ensure your environment is properly configured: -Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as "random" numbers on a computer are actually pseudo-random. These numbers rely on an initial "seed," which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\_blank}, [heart rates](https://mdpi.altmetric.com/details/47574324){target=\_blank}, or even [lava lamps](https://en.wikipedia.org/wiki/Lavarand){target=\_blank}. While this may seem random, given the same "seed," the same sequence of numbers will always be generated. +```bash +cargo build --release --locked +``` -In a global blockchain network, relying on real-world entropy for randomness isn’t feasible because these inputs vary by time and location. If nodes use different inputs, blockchains can fork. Hence, real-world randomness isn't suitable for use as a seed in blockchain systems. +!!!note + This initial compilation will take significant time, depending on your machine specifications. It compiles all components of the Polkadot SDK to verify your toolchain is correctly configured. -Currently, two primary methods for generating randomness in blockchains are used: [`RANDAO`](#randao) and [`VRF`](#vrf) (Verifiable Random Function). Polkadot adopts the `VRF` approach for its randomness. +### Verify the Build -## VRF +Once the build completes successfully, verify the installation by checking the compiled binaries: -A Verifiable Random Function (VRF) is a cryptographic function that generates a random number and proof that ensures the submitter produced the number. This proof allows anyone to verify the validity of the random number. +```bash +ls target/release +``` -Polkadot's VRF is similar to the one used in [**Ouroboros Praos**](https://eprint.iacr.org/2017/573.pdf){target=\_blank}, which secures randomness for block production in systems like [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe){target=\_blank} (Polkadot’s block production mechanism). +You should see several binaries, including: -The key difference is that Polkadot's VRF doesn’t rely on a central clock—avoiding the issue of whose clock to trust. Instead, it uses its own past results and slot numbers to simulate time and determine future outcomes. +- `polkadot`: The Polkadot relay chain node. +- `polkadot-parachain`: The parachain collator node. +- `polkadot-omni-node`:The omni node for running parachains. +- `substrate-node`: The kitchensink node with many pre-configured pallets. -### How VRF Works +Verify the Polkadot binary works by checking its version: -Slots on Polkadot are discrete units of time, each lasting six seconds, and can potentially hold a block. Multiple slots form an epoch, with 2400 slots making up one four-hour epoch. +```bash +./target/release/polkadot --version +``` -In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: +This should display version information similar to: -1. A "secret key," unique to each validator, is used for the die roll. -2. An epoch randomness value, derived from the hash of VRF outputs from blocks two epochs ago (N-2), so past randomness influences the current epoch (N). -3. The current slot number. +```bash +polkadot 1.16.0-1234abcd567 +``` -This process helps maintain fair randomness across the network. +If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! -Here is a graphical representation: +## Optional: Run the Kitchensink Node -![](/images/reference/parachains/randomness/randomness-01.webp) +The Polkadot SDK includes a feature-rich node called "kitchensink" located at `substrate/bin/node`. This node comes pre-configured with many pallets and features from the Polkadot SDK, making it an excellent reference for exploring capabilities and understanding how different components work together. -The VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). +!!!note + If you've already compiled the Polkadot SDK in the previous step, the `substrate-node` binary is already built and ready to use. You can skip directly to running the node. -The result is checked by the validator against a protocol threshold. If it's below the threshold, the validator becomes a candidate for block production in that slot. +### Run the Kitchensink Node in Development Mode -The validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`. +From the `polkadot-sdk` root directory, start the kitchensink node in development mode: -So, VRF can be expressed like: +```bash +./target/release/substrate-node --dev +``` -`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)` +The `--dev` flag enables development mode, which: -Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. +- Runs a single-node development chain. +- Produces and finalizes blocks automatically. +- Uses pre-configured development accounts (Alice, Bob, etc.). +- Deletes all data when stopped, ensuring a clean state on restart. -After executing the VRF, the `RESULT` is compared to a protocol-defined `THRESHOLD`. If the `RESULT` is below the `THRESHOLD`, the validator becomes a valid candidate to propose a block for that slot. Otherwise, the validator skips the slot. -As a result, there may be multiple validators eligible to propose a block for a slot. In this case, the block accepted by other nodes will prevail, provided it is on the chain with the latest finalized block as determined by the GRANDPA finality gadget. It's also possible for no block producers to be available for a slot, in which case the AURA consensus takes over. AURA is a fallback mechanism that randomly selects a validator to produce a block, running in parallel with BABE and only stepping in when no block producers exist for a slot. Otherwise, it remains inactive. +You should see log output indicating the node is running and producing blocks, with increasing block numbers after `finalized`. -Because validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. +### Interact with the Kitchensink Node -To verify resolution of this issue and that Polkadot block times remain near constant-time, see the [PoS Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} page of this documentation. +The kitchensink node is accessible at `ws://localhost:9944`. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your browser to explore its features and connect to the local node. -## RANDAO +1. Click the network icon in the top left corner. +2. Scroll to **Development** and select **Local Node**. +3. Click **Switch** to connect to your local node. -An alternative on-chain randomness method is Ethereum's RANDAO, where validators perform thousands of hashes on a seed and publish the final hash during a round. The collective input from all validators forms the random number, and as long as one honest validator participates, the randomness is secure. +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) -To enhance security, RANDAO can optionally be combined with a Verifiable Delay Function (VDF), ensuring that randomness can't be predicted or manipulated during computation. +Once connected, the interface updates its color scheme to indicate a successful connection to the local node. -For more information about RANDAO, see the [Randomness - RANDAO](https://eth2book.info/capella/part2/building_blocks/randomness/){target=\_blank} section of the Upgrading Ethereum documentation. +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) -## VDFs +You can now explore the various pallets and features included in the kitchensink node, making it a valuable reference as you develop your own blockchain applications. -Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. +To stop the node, press `Control-C` in the terminal. -They produce a unique result that can be quickly verified publicly. When combined with RANDAO, feeding RANDAO's output into a VDF introduces a delay that nullifies an attacker's chance to influence the randomness. +## Where to Go Next -However, VDF likely requires specialized ASIC devices to run separately from standard nodes. +
    -!!!warning - While only one is needed to secure the system, and they will be open-source and inexpensive, running VDF devices involves significant costs without direct incentives, adding friction for blockchain users. +- __Get Started with Parachain Development__ -## Additional Resources + --- -For more information about the reasoning for choices made along with proofs, see Polkadot's research on blockchain randomness and sortition in the [Block production](https://research.web3.foundation/Polkadot/protocols/block-production){target=\_blank} entry of the Polkadot Wiki. + Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. -For a discussion with Web3 Foundation researchers about when and under what conditions Polkadot's randomness can be utilized, see the [Discussion on Randomness used in Polkadot](https://github.com/use-ink/ink/issues/57){target=\_blank} issue on GitHub. + [:octicons-arrow-right-24: Get Started](/parachains/get-started/) + +
    --- -Page Title: Register a Foreign Asset on Asset Hub +Page Title: JSON-RPC APIs -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-foreign-asset.md -- Canonical (HTML): https://docs.polkadot.com/chain-interactions/token-operations/register-foreign-asset/ -- Summary: An in-depth guide to registering a foreign asset on the Asset Hub parachain, providing clear, step-by-step instructions. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ +- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. -# Register a Foreign Asset on Asset Hub +# JSON-RPC APIs +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -As outlined in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank}, Asset Hub supports two categories of assets: local and foreign. Local assets are created on the Asset Hub system parachain and are identified by integer IDs. On the other hand, foreign assets, which originate outside of Asset Hub, are recognized by [Multilocations](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank}. - -When registering a foreign asset on Asset Hub, it's essential to notice that the process involves communication between two parachains. The Asset Hub parachain will be the destination of the foreign asset, while the source parachain will be the origin of the asset. The communication between the two parachains is facilitated by the [Cross-Chain Message Passing (XCMP)](/parachains/interoperability/get-started/){target=\_blank} protocol. +Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. -This guide will take you through the process of registering a foreign asset on the Asset Hub parachain. +This guide uses the Polkadot Hub TestNet endpoint: -## Prerequisites +```text +https://testnet-passet-hub-eth-rpc.polkadot.io +``` -The Asset Hub parachain is one of the system parachains on a relay chain, such as [Polkadot](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot.api.onfinality.io%2Fpublic-ws#/explorer){target=\_blank} or [Kusama](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama.api.onfinality.io%2Fpublic-ws#/explorer){target=\_blank}. To interact with these parachains, you can use the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} interface for: +## Available Methods -- [Polkadot Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/explorer){target=\_blank} -- [Kusama Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.ibp.network%2Fstatemine#/explorer){target=\_blank} +### eth_accounts -For testing purposes, you can also interact with the Asset Hub instance on the following test networks: +Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. -- [Paseo Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpas-rpc.stakeworld.io%2Fassethub#/explorer){target=\_blank} +**Parameters**: -Before you start, ensure that you have: +None. -- Access to the Polkadot.js Apps interface, and you are connected to the desired chain. -- A parachain that supports the XCMP protocol to interact with the Asset Hub parachain. -- A funded wallet to pay for the transaction fees and subsequent registration of the foreign asset. +**Example**: -This guide will use Polkadot, its local Asset Hub instance, and the [Astar](https://astar.network/){target=\_blank} parachain (`ID` 2006), as stated in the [Test Environment Setup](#test-environment-setup) section. However, the process is the same for other relay chains and their respective Asset Hub parachain, regardless of the network you are using and the parachain owner of the foreign asset. +```bash title="eth_accounts" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_accounts", + "params":[], + "id":1 +}' +``` -## Steps to Register a Foreign Asset +--- -### Asset Hub +### eth_blockNumber -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. +Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. - - Testing foreign asset registration is recommended on TestNet before proceeding to MainNet. If you haven't set up a local testing environment yet, consult the [Environment setup](#test-environment-setup) guide. After setting up, connect to the Local Node (Chopsticks) at `ws://127.0.0.1:8000`. - - For live network operations, connect to the Asset Hub parachain. You can choose either Polkadot or Kusama Asset Hub from the dropdown menu, selecting your preferred RPC provider. +**Parameters**: -2. Navigate to the **Extrinsics** page: +None. - 1. Click on the **Developer** tab from the top navigation bar. - 2. Select **Extrinsics** from the dropdown. +**Example**: - ![Access to Developer Extrinsics section](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-01.webp) +```bash title="eth_blockNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_blockNumber", + "params":[], + "id":1 +}' +``` -3. Select the Foreign Assets pallet: +--- - 3. Select the **`foreignAssets`** pallet from the dropdown list. - 4. Choose the **`create`** extrinsic. +### eth_call - ![Select the Foreign Asset pallet](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-02.webp) +Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. -3. Fill out the required fields and click on the copy icon to copy the **encoded call data** to your clipboard. The fields to be filled are: +**Parameters**: - - **id**: As this is a foreign asset, the ID will be represented by a Multilocation that reflects its origin. For this case, the Multilocation of the asset will be from the source parachain perspective. - - ```javascript - { parents: 1, interior: { X1: [{ Parachain: 2006 }] } } - ``` +- **`transaction` ++"object"++**: The transaction call object. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - - **admin**: Refers to the account that will be the admin of this asset. This account will be able to manage the asset, including updating its metadata. As the registered asset corresponds to a native asset of the source parachain, the admin account should be the sovereign account of the source parachain. - - The sovereign account can be obtained through [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/){target=\_blank}. +**Example**: - Ensure that **Sibling** is selected and that the **Para ID** corresponds to the source parachain. In this case, since the guide follows the test setup stated in the [Test Environment Setup](#test-environment-setup) section, the **Para ID** is `2006`. +```bash title="eth_call" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_call", + "params":[{ + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_CALL" + }, "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` - ![Get parachain sovereign account](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-03.webp) +Ensure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values. +--- - - **`minBalance`**: The minimum balance required to hold this asset. +### eth_chainId - ![Fill out the required fields](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-04.webp) +Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}. - !!! tip - If you need an example of the encoded call data, you can copy the following: - ``` - 0x3500010100591f007369626cd6070000000000000000000000000000000000000000000000000000a0860100000000000000000000000000 - ``` +**Parameters**: -### Source Parachain +None. -1. Navigate to the **Developer > Extrinsics** section. -2. Create the extrinsic to register the foreign asset through XCM: +**Example**: - 1. Paste the **encoded call data** copied in the previous step. - 2. Click the **Submit Transaction** button. +```bash title="eth_chainId" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_chainId", + "params":[], + "id":1 +}' +``` - ![Register foreign asset through XCM](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-05.webp) +--- - This XCM call involves withdrawing DOT from the sibling account of the parachain, using it to initiate an execution. The transaction will be carried out with XCM as the origin kind, and will be a hex-encoded call to create a foreign asset on Asset Hub for the specified parachain asset multilocation. Any surplus will be refunded, and the asset will be deposited into the sibling account. +### eth_estimateGas - !!! warning - Note that the sovereign account on the Asset Hub parachain must have a sufficient balance to cover the XCM `BuyExecution` instruction. If the account does not have enough balance, the transaction will fail. +Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}. - If you want to have the whole XCM call ready to be copied, go to the **Developer > Extrinsics > Decode** section and paste the following hex-encoded call data: +**Parameters**: - ```text - 0x6300330003010100a10f030c000400010000070010a5d4e81300010000070010a5d4e80006030700b4f13501419ce03500010100591f007369626cd607000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - ``` +- **`transaction` ++"object"++**: The transaction call object. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - Be sure to replace the encoded call data with the one you copied in the previous step. +**Example**: -After the transaction is successfully executed, the foreign asset will be registered on the Asset Hub parachain. +```bash title="eth_estimateGas" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_estimateGas", + "params":[{ + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_FUNCTION_CALL" + }], + "id":1 +}' +``` -## Asset Registration Verification +Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. -To confirm that a foreign asset has been successfully accepted and registered on the Asset Hub parachain, you can navigate to the `Network > Explorer` section of the Polkadot.js Apps interface for Asset Hub. You should be able to see an event that includes the following details: +--- -![Asset registration event](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-06.webp) +### eth_gasPrice -In the image above, the **success** field indicates whether the asset registration was successful. +Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. -## Test Environment Setup +**Parameters**: -To test the foreign asset registration process before deploying it on a live network, you can set up a local parachain environment. This guide uses Chopsticks to simulate that process. For more information on using Chopsticks, please refer to the [Chopsticks documentation](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank}. +None. -To set up a test environment, run the following command: +**Example**: -```bash -npx @acala-network/chopsticks xcm \ ---r polkadot \ ---p polkadot-asset-hub \ ---p astar +```bash title="eth_gasPrice" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_gasPrice", + "params":[], + "id":1 +}' ``` -The preceding command will create a lazy fork of Polkadot as the relay chain, its Asset Hub instance, and the Astar parachain. The `xcm` parameter enables communication through the XCMP protocol between the relay chain and the parachains, allowing the registration of foreign assets on Asset Hub. For further information on the chopsticks usage of the XCMP protocol, refer to the [XCM Testing](/tutorials/polkadot-sdk/testing/fork-live-chains/#xcm-testing){target=\_blank} section of the Chopsticks documentation. - -After executing the command, the terminal will display output indicating the Polkadot relay chain, the Polkadot Asset Hub, and the Astar parachain are running locally and connected through XCM. You can access them individually via the Polkadot.js Apps interface. - -- [Polkadot Relay Chain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8002#/explorer){target=\_blank} -- [Polkadot Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8000#/explorer){target=\_blank} -- [Astar Parachain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8001#/explorer){target=\_blank} - - --- -Page Title: Register a Local Asset +### eth_getBalance + +Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md -- Canonical (HTML): https://docs.polkadot.com/chain-interactions/token-operations/register-local-asset/ -- Summary: Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. +**Parameters**: -# Register a Local Asset on Asset Hub +- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -## Introduction +**Example**: -As detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation. +```bash title="eth_getBalance" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBalance", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -This guide will take you through the steps of registering a local asset on the Asset Hub parachain. +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -## Prerequisites +--- -Before you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and a funded wallet with DOT or KSM. +### eth_getBlockByHash -- For Polkadot Asset Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata. -- For Kusama Asset Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata. +Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. -You need to ensure that your Asset Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees. +**Parameters**: -## Steps to Register a Local Asset +- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. -To register a local asset on the Asset Hub parachain, follow these steps: +**Example**: -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. +```bash title="eth_getBlockByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockByHash", + "params":["INSERT_BLOCK_HASH", INSERT_BOOLEAN], + "id":1 +}' +``` - - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`. - - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider. +Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values. -2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. +--- - ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) +### eth_getBlockByNumber -3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column. +Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. - ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) +**Parameters**: -4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. - ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) +**Example**: -5. Fill in the required fields in the **Create Asset** form: +```bash title="eth_getBlockByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockByNumber", + "params":["INSERT_BLOCK_VALUE", INSERT_BOOLEAN], + "id":1 +}' +``` - 1. **creator account**: The account to be used for creating this asset and setting up the initial metadata. - 2. **asset name**: The descriptive name of the asset you are registering. - 3. **asset symbol**: The symbol that will be used to represent the asset. - 4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface. - 5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested. - 6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id. - 7. Click on the **Next** button. - - ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp) +Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values. -6. Choose the accounts for the roles listed below: +--- - 1. **admin account**: The account designated for continuous administration of the token. - 2. **issuer account**: The account that will be used for issuing this token. - 3. **freezer account**: The account that will be used for performing token freezing operations. - 4. Click on the **Create** button. +### eth_getBlockTransactionCountByNumber - ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp) +Returns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\_blank}. -7. Click on the **Sign and Submit** button to complete the asset registration process. +**Parameters**: - ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) +- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -## Verify Asset Registration +**Example**: -After completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets){target=\_blank} section of the Polkadot.js Apps interface. +```bash title="eth_getBlockTransactionCountByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockTransactionCountByNumber", + "params":["INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp) +Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. -!!! tip - Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field. +--- -In this way, you have successfully registered a local asset on the Asset Hub parachain. +### eth_getBlockTransactionCountByHash -For an in-depth explanation about Asset Hub and its features, see the [Asset Hub](/chain-interactions/token-operations/convert-assets/){target=\_blank} entry in the Polkadot Wiki. +Returns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}. -## Test Setup Environment +**Parameters**: -You can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank} documentation. +- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -To set up a test environment, execute the following command: +**Example**: -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml +```bash title="eth_getBlockTransactionCountByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockTransactionCountByHash", + "params":["INSERT_BLOCK_HASH"], + "id":1 +}' ``` -The above command will spawn a lazy fork of Polkadot Asset Hub with the latest block data from the network. If you need to test Kusama Asset Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. - -An Asset Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet. - +Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. --- -Page Title: Set Up the Polkadot SDK Parachain Template - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md -- Canonical (HTML): https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/ -- Summary: Learn how to set up and run the Polkadot SDK Parachain Template locally, creating a ready-to-customize foundation for your parachain. - -# Set Up the Polkadot SDK Parachain Template - -## Introduction - -The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs. +### eth_getCode -Among these, the [Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a preconfigured runtime with commonly used pallets, making it an ideal starting point for most parachain development projects. +Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. -This guide walks you through the full process of working with this template. You will: +**Parameters**: -- Set up the Polkadot SDK Parachain Template. -- Understand the project structure and key components. -- Verify your template is ready for development. -- Run the parachain template locally in development mode. +- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). -By the end of this guide, you'll have a working template ready to customize and deploy as a parachain. +**Example**: -## Prerequisites +```bash title="eth_getCode" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getCode", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -Before getting started, ensure you have done the following: +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -- Completed the [Install Polkadot SDK](/parachains/install-polkadot-sdk/){target=\_blank} guide and successfully installed [Rust](https://www.rust-lang.org/){target=\_blank} and the required packages to set up your development environment. +--- -For this tutorial series, you need to use Rust `1.86`. Newer versions of the compiler may not work with this parachain template version. +### eth_getLogs -Run the following commands to set up the correct Rust version: +Returns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}. -=== "macOS" +**Parameters**: - ```bash - rustup install 1.86 - rustup default 1.86 - rustup target add wasm32-unknown-unknown --toolchain 1.86-aarch64-apple-darwin - rustup component add rust-src --toolchain 1.86-aarch64-apple-darwin - ``` +- **`filter` ++"object"++**: The filter object. + - **`fromBlock` ++"string"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + - **`toBlock` ++"string"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + - **`address` ++"string" or "array of strings"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`topics` ++"array of strings"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string or an array of such strings (meaning OR). + - **`blockhash` ++"string"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -=== "Ubuntu" +**Example**: - ```bash - rustup toolchain install 1.86.0 - rustup default 1.86.0 - rustup target add wasm32-unknown-unknown --toolchain 1.86.0 - rustup component add rust-src --toolchain 1.86.0 - ``` +```bash title="eth_getLogs" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getLogs", + "params":[{ + "fromBlock": "latest", + "toBlock": "latest" + }], + "id":1 +}' +``` -## Polkadot SDK Utility Tools +--- -This tutorial requires two essential tools: +### eth_getStorageAt -- [**Chain spec builder**](https://crates.io/crates/staging-chain-spec-builder/10.0.0){target=\_blank}: A Polkadot SDK utility for generating chain specifications. Refer to the [Generate Chain Specs](/develop/parachains/deployment/generate-chain-specs/){target=\_blank} documentation for detailed usage. - - Install it by executing the following command: - - ```bash - cargo install --locked staging-chain-spec-builder@10.0.0 - ``` +Returns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}. - This command installs the `chain-spec-builder` binary. +**Parameters**: -- [**Polkadot Omni Node**](https://crates.io/crates/polkadot-omni-node/0.5.0){target=\_blank}: A white-labeled binary, released as a part of Polkadot SDK that can act as the collator of a parachain in production, with all the related auxiliary functionalities that a normal collator node has: RPC server, archiving state, etc. Moreover, it can also run the Wasm blob of the parachain locally for testing and development. +- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`storageKey` ++"string"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - To install it, run the following command: +**Example**: - ```bash - cargo install --locked polkadot-omni-node@0.5.0 - ``` +```bash title="eth_getStorageAt" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getStorageAt", + "params":["INSERT_ADDRESS", "INSERT_STORAGE_KEY", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` - This command installs the `polkadot-omni-node` binary. +Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. -## Clone the Template +--- -The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a ready-to-use development environment for building with the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. Follow these steps to set up the template: +### eth_getTransactionCount -1. Clone the template repository: +Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}. - ```bash - git clone https://github.com/paritytech/polkadot-sdk-parachain-template.git parachain-template - ``` +**Parameters**: -2. Navigate into the project directory: +- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - ```bash - cd parachain-template - ``` +**Example**: -## Explore the Project Structure +```bash title="eth_getTransactionCount" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionCount", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -Before building the template, take a moment to familiarize yourself with its structure. Understanding this organization will help you navigate the codebase as you develop your parachain. +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -The template follows a standard Polkadot SDK project layout: +--- -```text -parachain-template/ -├── node/ # Node implementation and client -├── pallets/ # Custom pallets for your parachain -├── runtime/ # Runtime configuration and logic -├── Cargo.toml # Workspace configuration -└── README.md # Documentation -``` +### eth_getTransactionByHash -Key directories explained: +Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. -- **runtime/**: Contains your parachain's state transition function and pallet configuration. This is where you'll define what your blockchain can do. -- **node/**: Houses the client implementation that runs your blockchain, handles networking, and manages the database. -- **pallets/**: Where you'll create custom business logic modules (pallets) for your specific use case. -- **Cargo.toml**: The workspace configuration that ties all components together. +**Parameters**: -!!!note - The runtime is compiled to WebAssembly (Wasm), enabling forkless upgrades. The node binary remains constant while the runtime can be updated on-chain. +- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -## Compile the Runtime +**Example**: -Now that you understand the template structure, let's compile the runtime to ensure everything is working correctly. +```bash title="eth_getTransactionByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByHash", + "params":["INSERT_TRANSACTION_HASH"], + "id":1 +}' +``` -1. Compile the runtime: +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. - ```bash - cargo build --release --locked - ``` +--- - !!!tip - Initial compilation may take several minutes, depending on your machine specifications. Use the `--release` flag for improved runtime performance compared to the default `--debug` build. If you need to troubleshoot issues, the `--debug` build provides better diagnostics. - - For production deployments, consider using a dedicated `--profile production` flag - this can provide an additional 15-30% performance improvement over the standard `--release` profile. +### eth_getTransactionByBlockNumberAndIndex -2. Upon successful compilation, you should see output indicating the build was successful. The compiled runtime will be located at: - - `./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm` +Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. -## Verify the Build +**Parameters**: -After compilation completes, verify that the runtime was created successfully by checking for the Wasm blob: +- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -```bash -ls -la ./target/release/wbuild/parachain-template-runtime/ +**Example**: + +```bash title="eth_getTransactionByBlockNumberAndIndex" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByBlockNumberAndIndex", + "params":["INSERT_BLOCK_VALUE", "INSERT_TRANSACTION_INDEX"], + "id":1 +}' ``` -You should see the `parachain_template_runtime.compact.compressed.wasm` file in the output, confirming the build was successful. +Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. -## Run the Node Locally +--- -After successfully compiling your runtime, you can spin up a local chain and produce blocks. This process will start your local parachain using the Polkadot Omni Node and allow you to interact with it. You'll first need to generate a chain specification that defines your network's identity, initial connections, and genesis state, providing the foundational configuration for how your nodes connect and what initial state they agree upon. +### eth_getTransactionByBlockHashAndIndex -Follow these steps to launch your node in development mode: +Returns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}. -1. Generate the chain specification file of your parachain: +**Parameters**: - ```bash - chain-spec-builder create -t development \ - --relay-chain paseo \ - --para-id 1000 \ - --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ - named-preset development - ``` +- **`blockHash` ++"string"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -2. Start the Omni Node with the generated chain spec. You'll start it in development mode (without a relay chain config), producing and finalizing blocks: +**Example**: - ```bash - polkadot-omni-node --chain ./chain_spec.json --dev - ``` +```bash title="eth_getTransactionByBlockHashAndIndex" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByBlockHashAndIndex", + "params":["INSERT_BLOCK_HASH", "INSERT_TRANSACTION_INDEX"], + "id":1 +}' +``` - The `--dev` option does the following: +Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. - - Deletes all active data (keys, blockchain database, networking information) when stopped. - - Ensures a clean working state each time you restart the node. +--- -3. Verify that your node is running by reviewing the terminal output. You should see log messages indicating block production and finalization. +### eth_getTransactionReceipt -4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output. +Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. -The details of the log output will be explored in a later tutorial. For now, knowing that your node is running and producing blocks is sufficient. +**Parameters**: -## Interact with the Node +- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -When running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} interface, follow these steps: +**Example**: -1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner: - - ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp) +```bash title="eth_getTransactionReceipt" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionReceipt", + "params":["INSERT_TRANSACTION_HASH"], + "id":1 +}' +``` -2. Connect to your local node: +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. - 1. Scroll to the bottom and select **Development**. - 2. Choose **Custom**. - 3. Enter `ws://localhost:9944` in the **custom endpoint** input field. - 4. Click the **Switch** button. - - ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp) +--- -3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain. - - ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp) +### eth_maxPriorityFeePerGas -You are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\_blank} available on the Polkadot Wiki. +Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. -## Stop the Node +**Parameters**: -When you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time. +None. -To stop the local node: +**Example**: -1. Return to the terminal window where the node output is displayed. -2. Press `Control-C` to stop the running process. -3. Verify that your terminal returns to the prompt in the `parachain-template` directory. +```bash title="eth_maxPriorityFeePerGas" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_maxPriorityFeePerGas", + "params":[], + "id":1 +}' +``` -## Where to Go Next +--- -
    +### eth_sendRawTransaction -- Tutorial __Deploy to Polkadot__ +Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. - --- +**Parameters**: - Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks. +- **`callData` ++"string"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md) +**Example**: -
    +```bash title="eth_sendRawTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_sendRawTransaction", + "params":["INSERT_CALL_DATA"], + "id":1 +}' +``` +Ensure to replace the `INSERT_CALL_DATA` with the proper values. --- -Page Title: Sidecar REST API - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/sidecar/ -- Summary: Learn about Substrate API Sidecar, a REST service that provides endpoints for interacting with Polkadot SDK-based chains and simplifies blockchain interactions. +### eth_sendTransaction -# Sidecar API +Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. -## Introduction +**Parameters**: -The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more. +- **`transaction` ++"object"++**: The transaction object. + - **`from` ++"string"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`to` ++"string"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`data` ++"string"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`nonce` ++"string"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -Sidecar functions as a caching layer between your application and a Polkadot SDK-based node, offering standardized REST endpoints that simplify interactions without requiring complex, direct RPC calls. This approach is especially valuable for developers who prefer REST APIs or build applications in languages with limited WebSocket support. +**Example**: -Some of the key features of the Sidecar API include: +```bash title="eth_sendTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_sendTransaction", + "params":[{ + "from": "INSERT_SENDER_ADDRESS", + "to": "INSERT_RECIPIENT_ADDRESS", + "gas": "INSERT_GAS_LIMIT", + "gasPrice": "INSERT_GAS_PRICE", + "value": "INSERT_VALUE", + "input": "INSERT_INPUT_DATA", + "nonce": "INSERT_NONCE" + }], + "id":1 +}' +``` -- **REST API interface**: Provides a familiar REST API interface for interacting with Polkadot SDK-based chains. -- **Standardized endpoints**: Offers consistent endpoint formats across different chain implementations. -- **Caching layer**: Acts as a caching layer to improve performance and reduce direct node requests. -- **Multiple chain support**: Works with any Polkadot SDK-based chain, including Polkadot, Kusama, and custom chains. +Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values. -## Prerequisites +--- -Sidecar API requires Node.js version 18.14 LTS or higher. Verify your Node.js version: +### eth_syncing -```bash -node --version -``` +Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. -If you need to install or update Node.js, visit the [official Node.js website](https://nodejs.org/){target=\_blank} to download and install the latest LTS version. +**Parameters**: -## Installation +None. -To install Substrate API Sidecar, use one of the following commands: +**Example**: -=== "npm" +```bash title="eth_syncing" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_syncing", + "params":[], + "id":1 +}' +``` - ```bash - npm install -g @substrate/api-sidecar - ``` +--- -=== "pnpm" +### net_listening - ```bash - pnpm install -g @substrate/api-sidecar - ``` +Returns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\_blank}. -=== "yarn" +**Parameters**: - ```bash - yarn global add @substrate/api-sidecar - ``` +None. -You can confirm the installation by running: +**Example**: -```bash -substrate-api-sidecar --version +```bash title="net_listening" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_listening", + "params":[], + "id":1 +}' ``` -For more information about the Sidecar API installation, see the [installation and usage](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#npm-package-installation-and-usage){target=\_blank} section of the Sidecar API README. +--- -## Usage +### net_peerCount -To use the Sidecar API, you have two options: +Returns the number of peers currently connected to the client. -- **Local node**: Run a node locally, which Sidecar will connect to by default, requiring no additional configuration. To start, run the following: +**Parameters**: - ```bash - substrate-api-sidecar - ``` +None. -- **Remote node**: Connect Sidecar to a remote node by specifying the RPC endpoint for that chain. For example, to gain access to the Polkadot Asset Hub associated endpoints. +**Example**: - ```bash - SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io substrate-api-sidecar - ``` +```bash title="net_peerCount" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_peerCount", + "params":[], + "id":1 +}' +``` - For more configuration details, see the [Configuration](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#configuration){target=\_blank} section of the Sidecar API documentation. +--- -Once the Sidecar API is running, you’ll see output similar to this: +### net_version -
    - SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io substrate-api-sidecar -
    - SAS: - 📦 LOG: - ✅ LEVEL: "info" - ✅ JSON: false - ✅ FILTER_RPC: false - ✅ STRIP_ANSI: false - ✅ WRITE: false - ✅ WRITE_PATH: "/opt/homebrew/lib/node_modules/@substrate/api-sidecar/build/src/logs" - ✅ WRITE_MAX_FILE_SIZE: 5242880 - ✅ WRITE_MAX_FILES: 5 - 📦 SUBSTRATE: - ✅ URL: "wss://polkadot-asset-hub-rpc.polkadot.io" - ✅ TYPES_BUNDLE: undefined - ✅ TYPES_CHAIN: undefined - ✅ TYPES_SPEC: undefined - ✅ TYPES: undefined - ✅ CACHE_CAPACITY: undefined - 📦 EXPRESS: - ✅ BIND_HOST: "127.0.0.1" - ✅ PORT: 8080 - ✅ KEEP_ALIVE_TIMEOUT: 5000 - 📦 METRICS: - ✅ ENABLED: false - ✅ PROM_HOST: "127.0.0.1" - ✅ PROM_PORT: 9100 - ✅ LOKI_HOST: "127.0.0.1" - ✅ LOKI_PORT: 3100 - ✅ INCLUDE_QUERYPARAMS: false -
    - 2024-11-06 08:06:01 info: Version: 19.3.0 - 2024-11-06 08:06:02 warn: API/INIT: RPC methods not decorated: chainHead_v1_body, chainHead_v1_call, chainHead_v1_continue, chainHead_v1_follow, chainHead_v1_header, chainHead_v1_stopOperation, chainHead_v1_storage, chainHead_v1_unfollow, chainHead_v1_unpin, chainSpec_v1_chainName, chainSpec_v1_genesisHash, chainSpec_v1_properties, transactionWatch_v1_submitAndWatch, transactionWatch_v1_unwatch, transaction_v1_broadcast, transaction_v1_stop - 2024-11-06 08:06:02 info: Connected to chain Polkadot Asset Hub on the statemint client at wss://polkadot-asset-hub-rpc.polkadot.io - 2024-11-06 08:06:02 info: Listening on http://127.0.0.1:8080/ - 2024-11-06 08:06:02 info: Check the root endpoint (http://127.0.0.1:8080/) to see the available endpoints for the current node -
    -With Sidecar running, you can access the exposed endpoints via a browser, [`Postman`](https://www.postman.com/){target=\_blank}, [`curl`](https://curl.se/){target=\_blank}, or your preferred tool. +Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. -### Endpoints +**Parameters**: -Sidecar API provides a set of REST endpoints that allow you to query different aspects of the chain, including blocks, accounts, and transactions. Each endpoint offers specific insights into the chain’s state and activities. +None. -For example, to retrieve the version of the node, use the `/node/version` endpoint: +**Example**: -```bash -curl -X 'GET' \ - 'http://127.0.0.1:8080/node/version' \ - -H 'accept: application/json' +```bash title="net_version" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_version", + "params":[], + "id":1 +}' ``` -Alternatively, you can access `http://127.0.0.1:8080/node/version` directly in a browser since it’s a `GET` request. +--- + +### system_health -In response, you’ll see output similar to this (assuming you’re connected to Polkadot Asset Hub): +Returns information about the health of the system. -
    - curl -X 'GET' 'http://127.0.0.1:8080/node/version' -H 'accept: application/json' -
    - { - "clientVersion": "1.16.1-835e0767fe8", - "clientImplName": "statemint", - "chain": "Polkadot Asset Hub" - } -
    -For a complete list of available endpoints and their documentation, visit the [Sidecar API list endpoints](https://paritytech.github.io/substrate-api-sidecar/dist/){target=\_blank}. You can learn about the endpoints and how to use them in your applications. +**Parameters**: -## Where to Go Next +None. -To dive deeper, refer to the [official Sidecar documentation](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#substrateapi-sidecar){target=\_blank}. This provides a comprehensive guide to the available configurations and advanced usage. +**Example**: +```bash title="system_health" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"system_health", + "params":[], + "id":1 +}' +``` --- -Page Title: Smart Contracts Cookbook Index - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/ -- Summary: Explore our full collection of tutorials and guides to learn step-by-step how to build, deploy, and work with smart contracts on Polkadot. +### web3_clientVersion -# Smart Contracts Cookbook +Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. -Welcome to the Polkadot smart contracts cookbook index. +**Parameters**: -This page contains a list of all relevant tutorials and guides to help you get started coding smart contracts and dApps in Polkadot. +None. +**Example**: +```bash title="web3_clientVersion" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"web3_clientVersion", + "params":[], + "id":1 +}' +``` +--- -## Get Tokens from the Faucet +### debug_traceBlockByNumber -| Title | Difficulty | Tools | Description | -|------------------------------------|:-----------:|-------|-----------------------------------------------------------------------------------------------------------------------| -| [Faucet](/smart-contracts/faucet/) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. | +Traces a block's execution by its number and returns a detailed execution trace for each transaction. -## EVM/PVM Smart Contracts +**Parameters**: -| Title | Difficulty | Tools | Description | -|---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. | -| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | +- **`blockValue` ++"string"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`options` ++"object"++**: (Optional) An object containing tracer options. + - **`tracer` ++"string"++**: The name of the tracer to use (e.g., `"callTracer"`, `"opTracer"`). + - Other tracer-specific options may be supported. -## Port Ethereum DApps +**Example**: -| Title | Difficulty | Tools | Description | -|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| -| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | +```bash title="debug_traceBlockByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceBlockByNumber", + "params":["INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "id":1 +}' +``` +Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. --- -Page Title: Smart Contracts Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ -- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. - -# Smart Contracts on Polkadot +### debug_traceTransaction -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction +Traces the execution of a single transaction by its hash and returns a detailed execution trace. -Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. +**Parameters**: -Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. +- **`transactionHash` ++"string"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). -These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. +**Example**: -## Native Smart Contracts +```bash title="debug_traceTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceTransaction", + "params":["INSERT_TRANSACTION_HASH", {"tracer": "callTracer"}], + "id":1 +}' +``` -### Introduction +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. -Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. +--- -### Smart Contract Development +### debug_traceCall -The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. +Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. -Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. +**Parameters**: -### Technical Architecture +- **`transaction` ++"object"++**: The transaction call object, similar to `eth_call` parameters. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). -PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: +**Example**: -- Enhanced performance for smart contract execution. -- Improved gas efficiency for complex operations. -- Native compatibility with Polkadot's runtime environment. -- Optimized storage and state management. +```bash title="debug_traceCall" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceCall", + "params":[{ + "from": "INSERT_SENDER_ADDRESS", + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_CALL" + }, "INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "id":1 +}' +``` -### Development Tools and Resources +Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value. -Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: +--- -- Contract development in Solidity or Rust. -- Support for standard Ethereum development libraries. -- Integration with widely used development environments. -- Access to blockchain explorers and indexing solutions. -- Compatibility with contract monitoring and management tools. +## Response Format -### Cross-Chain Capabilities +All responses follow the standard JSON-RPC 2.0 format: -Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": ... // The return value varies by method +} +``` -### Use Cases +## Error Handling -Polkadot Hub's smart contract platform is suitable for a wide range of applications: +If an error occurs, the response will include an error object: -- DeFi protocols leveraging _cross-chain capabilities_. -- NFT platforms utilizing Polkadot's native token standards. -- Governance systems integrated with Polkadot's democracy mechanisms. -- Cross-chain bridges and asset management solutions. +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32000, + "message": "Error message here" + } +} +``` -## Other Smart Contract Environments -Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: +--- -- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). +Page Title: Oracles -- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md +- Canonical (HTML): https://docs.polkadot.com/parachains/integrations/oracles/ +- Summary: Learn about blockchain oracles, the essential bridges connecting blockchains with real-world data for decentralized applications in the Polkadot ecosystem. +# Oracles -Each environment provides unique advantages based on developer preferences and application requirements. +## What is a Blockchain Oracle? -## Where to Go Next +Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the "blockchain oracle problem." Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain. -Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. +While simple oracle implementations may rely on a single trusted provider, more sophisticated solutions use decentralized networks where multiple providers stake assets and reach consensus on data validity. Typical applications include DeFi price feeds, weather data for insurance contracts, and cross-chain asset verification. -Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. +## Oracle Implementations
    -- Guide __Libraries__ - - --- - - Explore essential libraries to optimize smart contract development and interaction. - - [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) - -- Guide __Dev Environments__ +- __Acurast__ --- - Set up your development environment for seamless contract deployment and testing. + Acurast is a decentralized, serverless cloud platform that uses a distributed network of mobile devices for oracle services, addressing centralized trust and data ownership issues. In the Polkadot ecosystem, it allows developers to define off-chain data and computation needs, which are processed by these devices acting as decentralized oracle nodes, delivering results to Substrate (Wasm) and EVM environments. - [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) + [:octicons-arrow-right-24: Reference](https://acurast.com/){target=\_blank}
    --- -Page Title: Subxt Rust API +Page Title: Overview of FRAME -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/subxt/ -- Summary: Subxt is a Rust library for type-safe interaction with Polkadot SDK blockchains, enabling transactions, state queries, runtime API access, and more. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md +- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ +- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. -# Subxt Rust API +# Customize Your Runtime ## Introduction -Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability. - -## Prerequisites - -Before using subxt, ensure you have the following requirements: - -- Rust and Cargo installed on your system. You can install them using [Rustup](https://rustup.rs/){target=\_blank}. -- A Rust project initialized. If you don't have one, create it with: - ```bash - cargo new my_project && cd my_project - ``` - -## Installation - -To use subxt in your project, you must install the necessary dependencies. Each plays a specific role in enabling interaction with the blockchain: - -1. **Install the subxt CLI**: [`subxt-cli`](https://crates.io/crates/subxt-cli){target=\_blank} is a command-line tool that provides utilities for working with Polkadot SDK metadata. In the context of subxt, it is essential to download chain metadata, which is required to generate type-safe Rust interfaces for interacting with the blockchain. Install it using the following: - - ```bash - cargo install subxt-cli@0.44.0 - ``` - -2. **Add core dependencies**: These dependencies are essential for interacting with the blockchain. - - - **[subxt](https://crates.io/crates/subxt){target=\_blank}**: The main library for communicating with Polkadot SDK nodes. It handles RPC requests, encoding/decoding, and type generation. - - ```bash - cargo add subxt@0.44.0 - ``` - - - **[subxt-signer](https://crates.io/crates/subxt-signer){target=\_blank}**: Provides cryptographic functionality for signing transactions. Without this, you can only read data but cannot submit transactions. +A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. - ```bash - cargo add subxt-signer@0.44.0 - ``` +This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. - - **[tokio](https://crates.io/crates/tokio){target=\_blank}**: An asynchronous runtime for Rust. Since blockchain operations are async, Tokio enables the efficient handling of network requests. The `rt` feature enables Tokio's runtime, including the current-thread single-threaded scheduler, which is necessary for async execution. The `macros` feature provides procedural macros like `#[tokio::main]` to simplify runtime setup. +## Understanding Your Runtime - ```bash - cargo add tokio@1.44.2 --features rt,macros - ``` +The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. - After adding the dependencies, your `Cargo.toml` should look like this: +Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. - ```toml - [package] - name = "my_project" - version = "0.1.0" - edition = "2021" +## Runtime Architecture - [dependencies] - subxt = "0.41.0" - subxt-signer = "0.41.0" - tokio = { version = "1.44.2", features = ["rt", "macros"] } +The following diagram shows how FRAME components work together to form your runtime: - ``` +![](/images/parachains/customize-runtime/index/frame-overview-01.webp) -## Get Started +The main components are: -This guide will walk you through the fundamental operations of subxt, from setting up your environment to executing transactions and querying blockchain state. +- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. +- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. +- **`frame_system`**: Provides core runtime primitives and storage. +- **`frame_support`**: Utilities and macros that simplify pallet development. -### Download Chain Metadata +## Building Blocks: Pallets -Before interacting with a blockchain, you need to retrieve its metadata. This metadata defines storage structures, extrinsics, and other runtime details. Use the `subxt-cli` tool to download the metadata, replacing `INSERT_NODE_URL` with the URL of the node you want to interact with: +[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. -```bash -subxt metadata --url INSERT_NODE_URL > polkadot_metadata.scale -``` +A pallet can implement virtually any blockchain feature you need: -### Generate Type-Safe Interfaces +- Expose new transactions that users can submit. +- Store data on-chain. +- Enforce business rules and validation logic. +- Emit events to notify users of state changes. +- Handle errors gracefully. -Use the `#[subxt::subxt]` macro to generate a type-safe Rust interface from the downloaded metadata: +### Pre-Built Pallets vs. Custom Pallets -```rust -// Generate an interface that we can use from the node's metadata. -#[subxt::subxt(runtime_metadata_path = "./polkadot_metadata.scale")] -pub mod polkadot {} -``` +FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. -Once subxt interfaces are generated, you can interact with your node in the following ways. You can use the links below to view the related subxt documentation: +However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. -- **[Transactions](https://docs.rs/subxt/latest/subxt/book/usage/transactions/index.html){target=\_blank}**: Builds and submits transactions, monitors their inclusion in blocks, and retrieves associated events. -- **[Storage](https://docs.rs/subxt/latest/subxt/book/usage/storage/index.html){target=\_blank}**: Enables querying of node storage data. -- **[Events](https://docs.rs/subxt/latest/subxt/book/usage/events/index.html){target=\_blank}**: Retrieves events emitted from recent blocks. -- **[Constants](https://docs.rs/subxt/latest/subxt/book/usage/constants/index.html){target=\_blank}**: Accesses constant values stored in nodes that remain unchanged across a specific runtime version. -- **[Blocks](https://docs.rs/subxt/latest/subxt/book/usage/blocks/index.html){target=\_blank}**: Loads recent blocks or subscribes to new/finalized blocks, allowing examination of extrinsics, events, and storage at those blocks. -- **[Runtime APIs](https://docs.rs/subxt/latest/subxt/book/usage/runtime_apis/index.html){target=\_blank}**: Makes calls into pallet runtime APIs to fetch data. -- **[Custom values](https://docs.rs/subxt/latest/subxt/book/usage/custom_values/index.html){target=\_blank}**: Accesses "custom values" contained within metadata. -- **[Raw RPC calls](https://docs.rs/subxt/latest/subxt/book/usage/rpc/index.html){target=\_blank}**: Facilitates raw RPC requests to compatible nodes. +### Pallet Structure -### Initialize the Subxt Client +FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. -To interact with a blockchain node using subxt, create an asynchronous main function and initialize the client. Replace `INSERT_NODE_URL` with the URL of your target node: +A typical pallet looks like this: ```rust -use std::str::FromStr; -use subxt::utils::AccountId32; -use subxt::{OnlineClient, PolkadotConfig}; -use subxt_signer::{bip39::Mnemonic,sr25519::Keypair}; - -// Generate an interface that we can use from the node's metadata. -#[subxt::subxt(runtime_metadata_path = "./polkadot_metadata.scale")] -pub mod polkadot {} - -#[tokio::main(flavor = "current_thread")] -async fn main() -> Result<(), Box> { - // Define the node URL. - const NODE_URL: &str = "INSERT_NODE_URL"; +pub use pallet::*; - // Initialize the Subxt client to interact with the blockchain. - let api = OnlineClient::::from_url(NODE_URL).await?; +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; - // Your code here... + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); - Ok(()) + #[pallet::config] // snip + #[pallet::event] // snip + #[pallet::error] // snip + #[pallet::storage] // snip + #[pallet::call] // snip } ``` -### Read Chain Data - -subxt provides multiple ways to access on-chain data: - -- **Constants**: Constants are predefined values in the runtime that remain unchanged unless modified by a runtime upgrade. - - For example, to retrieve the existential deposit, use: - - ```rust - // A query to obtain some constant. - let constant_query = polkadot::constants().balances().existential_deposit(); - - // Obtain the value. - let value = api.constants().at(&constant_query)?; - - println!("Existential deposit: {:?}", value); - ``` - -- **State**: State refers to the current chain data, which updates with each block. +Every pallet can implement these core macros: - To fetch account information, replace `INSERT_ADDRESS` with the address you want to fetch data from and use: +- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. +- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. +- **`#[pallet::config]`**: Defines configuration and associated types. +- **`#[pallet::event]`**: Defines events emitted by your pallet. +- **`#[pallet::error]`**: Defines error types your pallet can return. +- **`#[pallet::storage]`**: Defines on-chain storage items. +- **`#[pallet::call]`**: Defines dispatchable functions (transactions). - ```rust - // Define the target account address. - const ADDRESS: &str = "INSERT_ADDRESS"; - let account = AccountId32::from_str(ADDRESS).unwrap(); - - // Build a storage query to access account information. - let storage_query = polkadot::storage().system().account(&account.into()); - - // Fetch the latest state for the account. - let result = api - .storage() - .at_latest() - .await? - .fetch(&storage_query) - .await? - .unwrap(); - - println!("Account info: {:?}", result); - ``` +For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. -### Submit Transactions +## How Runtime Customization Works -To submit a transaction, you must construct an extrinsic, sign it with your private key, and send it to the blockchain. Replace `INSERT_DEST_ADDRESS` with the recipient's address, `INSERT_AMOUNT` with the amount to transfer, and `INSERT_SECRET_PHRASE` with the sender's mnemonic phrase: +Customizing your runtime typically follows these patterns: -```rust - // Define the recipient address and transfer amount. - const DEST_ADDRESS: &str = "INSERT_DEST_ADDRESS"; - const AMOUNT: u128 = INSERT_AMOUNT; - - // Convert the recipient address into an `AccountId32`. - let dest = AccountId32::from_str(DEST_ADDRESS).unwrap(); - - // Build the balance transfer extrinsic. - let balance_transfer_tx = polkadot::tx() - .balances() - .transfer_allow_death(dest.into(), AMOUNT); - - // Load the sender's keypair from a mnemonic phrase. - const SECRET_PHRASE: &str = "INSERT_SECRET_PHRASE"; - let mnemonic = Mnemonic::parse(SECRET_PHRASE).unwrap(); - let sender_keypair = Keypair::from_phrase(&mnemonic, None).unwrap(); - - // Sign and submit the extrinsic, then wait for it to be finalized. - let events = api - .tx() - .sign_and_submit_then_watch_default(&balance_transfer_tx, &sender_keypair) - .await? - .wait_for_finalized_success() - .await?; - - // Check for a successful transfer event. - if let Some(event) = events.find_first::()? { - println!("Balance transfer successful: {:?}", event); - } -``` +**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. -## Where to Go Next +**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. -Now that you've covered the basics dive into the official [subxt documentation](https://docs.rs/subxt/latest/subxt/book/index.html){target=\_blank} for comprehensive reference materials and advanced features. +**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. +**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. ---- +The following diagram illustrates how pallets combine to form a complete runtime: -Page Title: Technical Reference Overview +![](/images/parachains/customize-runtime/index/frame-overview-02.webp) -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md -- Canonical (HTML): https://docs.polkadot.com/reference/ -- Summary: Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. +## Starting Templates -## Introduction +The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. -The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need. +- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. -Polkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\_blank} to the [governance](/reference/glossary#governance){target=\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants. +- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. -This guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem. +- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. -## Polkadot Hub +- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. -[Polkadot Hub](/reference/polkadot-hub/){target=\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain. +## Key Customization Scenarios -The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: +This section covers the most common customization patterns you'll encounter: -- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications. -- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem. -- **Staking**: Participate in network security and earn rewards by staking DOT. -- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov. -- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities. -- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem. -- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations. +- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. -## Parachains +- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. -[Parachains](/reference/parachains/){target=\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers: +- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. -- **Accounts**: Deep dive into account types, storage, and management on parachains. -- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms. -- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus. -- **Chain data**: Explore data structures, storage layouts, and state management. -- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains. -- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility. -- **Networks**: Learn about networking protocols and peer-to-peer communication. -- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\_blank}, the standard for cross-chain communication. -- **Randomness**: Understand how randomness is generated and used in Polkadot chains. -- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. +- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. -## On-Chain Governance +- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. -[On-Chain governance](/reference/governance/){target=\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details: -- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums. -- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity. -- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance. -- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system. +--- -## Glossary +Page Title: Set Up the Polkadot SDK Parachain Template -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md +- Canonical (HTML): https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/ +- Summary: Learn how to set up and run the Polkadot SDK Parachain Template locally, creating a ready-to-customize foundation for your parachain. -- Blockchain concepts (blocks, transactions, state) -- Consensus mechanisms (validators, collators, finality) -- Polkadot-specific terms (relay chain, parachain, XCM, FRAME) -- Network components (nodes, runtimes, storage) -- Governance terminology (origins, tracks, referendums) +# Set Up the Polkadot SDK Parachain Template -## Tools +## Introduction -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: +The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs. -- **Light clients**: Lightweight solutions for interacting with the network without running full nodes. -- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\_blank} and [PAPI](/reference/tools/papi/){target=\_blank} for building applications. -- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\_blank} and other Rust-based libraries for SDK development. -- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\_blank} for Python developers. -- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\_blank}, and [Omninode](/reference/tools/omninode/){target=\_blank} for smart contract and parachain testing. -- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\_blank} for substrate interaction. -- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\_blank} for XCM integration and asset transfers. +Among these, the [Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a preconfigured runtime with commonly used pallets, making it an ideal starting point for most parachain development projects. -## Where to Go Next +This guide walks you through the full process of working with this template. You will: -For detailed exploration of specific areas, proceed to any of the main sections: +- Set up the Polkadot SDK Parachain Template. +- Understand the project structure and key components. +- Verify your template is ready for development. +- Run the parachain template locally in development mode. -
    +By the end of this guide, you'll have a working template ready to customize and deploy as a parachain. -- Learn **Polkadot Hub** +## Prerequisites - --- +Before getting started, ensure you have done the following: - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. +- Completed the [Install Polkadot SDK](/parachains/install-polkadot-sdk/){target=\_blank} guide and successfully installed [Rust](https://www.rust-lang.org/){target=\_blank} and the required packages to set up your development environment. - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) +For this tutorial series, you need to use Rust `1.86`. Newer versions of the compiler may not work with this parachain template version. -- Learn **Parachains** +Run the following commands to set up the correct Rust version: - --- +=== "macOS" - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. + ```bash + rustup install 1.86 + rustup default 1.86 + rustup target add wasm32-unknown-unknown --toolchain 1.86-aarch64-apple-darwin + rustup component add rust-src --toolchain 1.86-aarch64-apple-darwin + ``` - [:octicons-arrow-right-24: Reference](/reference/parachains/) +=== "Ubuntu" -- Learn **On-Chain Governance** + ```bash + rustup toolchain install 1.86.0 + rustup default 1.86.0 + rustup target add wasm32-unknown-unknown --toolchain 1.86.0 + rustup component add rust-src --toolchain 1.86.0 + ``` - --- +## Polkadot SDK Utility Tools - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. +This tutorial requires two essential tools: - [:octicons-arrow-right-24: Reference](/reference/governance/) +- [**Chain spec builder**](https://crates.io/crates/staging-chain-spec-builder/10.0.0){target=\_blank}: A Polkadot SDK utility for generating chain specifications. Refer to the [Generate Chain Specs](/develop/parachains/deployment/generate-chain-specs/){target=\_blank} documentation for detailed usage. + + Install it by executing the following command: + + ```bash + cargo install --locked staging-chain-spec-builder@10.0.0 + ``` -- Guide **Glossary** + This command installs the `chain-spec-builder` binary. - --- +- [**Polkadot Omni Node**](https://crates.io/crates/polkadot-omni-node/0.5.0){target=\_blank}: A white-labeled binary, released as a part of Polkadot SDK that can act as the collator of a parachain in production, with all the related auxiliary functionalities that a normal collator node has: RPC server, archiving state, etc. Moreover, it can also run the Wasm blob of the parachain locally for testing and development. - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. + To install it, run the following command: - [:octicons-arrow-right-24: Reference](/reference/glossary/) + ```bash + cargo install --locked polkadot-omni-node@0.5.0 + ``` -- Guide **Tools** + This command installs the `polkadot-omni-node` binary. - --- +## Clone the Template - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. +The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a ready-to-use development environment for building with the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. Follow these steps to set up the template: - [:octicons-arrow-right-24: Reference](/reference/tools/) +1. Clone the template repository: -
    + ```bash + git clone https://github.com/paritytech/polkadot-sdk-parachain-template.git parachain-template + ``` +2. Navigate into the project directory: ---- + ```bash + cd parachain-template + ``` -Page Title: Transactions +## Explore the Project Structure -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/ -- Summary: Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. +Before building the template, take a moment to familiarize yourself with its structure. Understanding this organization will help you navigate the codebase as you develop your parachain. -# Transactions +The template follows a standard Polkadot SDK project layout: -## Introduction +```text +parachain-template/ +├── node/ # Node implementation and client +├── pallets/ # Custom pallets for your parachain +├── runtime/ # Runtime configuration and logic +├── Cargo.toml # Workspace configuration +└── README.md # Documentation +``` -Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions. +Key directories explained: -This guide walks you through the different transaction types and how they're formatted, validated, and processed within the Polkadot ecosystem. You'll also learn how to customize transaction formats and construct transactions for FRAME-based runtimes, ensuring a complete understanding of how transactions are built and executed in Polkadot SDK-based chains. +- **runtime/**: Contains your parachain's state transition function and pallet configuration. This is where you'll define what your blockchain can do. +- **node/**: Houses the client implementation that runs your blockchain, handles networking, and manages the database. +- **pallets/**: Where you'll create custom business logic modules (pallets) for your specific use case. +- **Cargo.toml**: The workspace configuration that ties all components together. -## What Is a Transaction? +!!!note + The runtime is compiled to WebAssembly (Wasm), enabling forkless upgrades. The node binary remains constant while the runtime can be updated on-chain. -In the Polkadot SDK, transactions represent operations that modify the chain's state, bundled into blocks for execution. The term extrinsic is often used to refer to any data that originates outside the runtime and is included in the chain. While other blockchain systems typically refer to these operations as "transactions," the Polkadot SDK adopts the broader term "extrinsic" to capture the wide variety of data types that can be added to a block. +## Compile the Runtime -There are three primary types of transactions (extrinsics) in the Polkadot SDK: +Now that you understand the template structure, let's compile the runtime to ensure everything is working correctly. -- **Signed transactions**: Signed by the submitting account, often carrying transaction fees. -- **Unsigned transactions**: Submitted without a signature, often requiring custom validation logic. -- **Inherent transactions**: Typically inserted directly into blocks by block authoring nodes, without gossiping between peers. +1. Compile the runtime: -Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. + ```bash + cargo build --release --locked + ``` -### Signed Transactions + !!!tip + Initial compilation may take several minutes, depending on your machine specifications. Use the `--release` flag for improved runtime performance compared to the default `--debug` build. If you need to troubleshoot issues, the `--debug` build provides better diagnostics. + + For production deployments, consider using a dedicated `--profile production` flag - this can provide an additional 15-30% performance improvement over the standard `--release` profile. -Signed transactions require an account's signature and typically involve submitting a request to execute a runtime call. The signature serves as a form of cryptographic proof that the sender has authorized the action, using their private key. These transactions often involve a transaction fee to cover the cost of execution and incentivize block producers. +2. Upon successful compilation, you should see output indicating the build was successful. The compiled runtime will be located at: + + `./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm` -Signed transactions are the most common type of transaction and are integral to user-driven actions, such as token transfers. For instance, when you transfer tokens from one account to another, the sending account must sign the transaction to authorize the operation. +## Verify the Build -For example, the [`pallet_balances::Call::transfer_allow_death`](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/pallet/struct.Pallet.html#method.transfer_allow_death){target=\_blank} extrinsic in the Balances pallet allows you to transfer tokens. Since your account initiates this transaction, your account key is used to sign it. You'll also be responsible for paying the associated transaction fee, with the option to include an additional tip to incentivize faster inclusion in the block. +After compilation completes, verify that the runtime was created successfully by checking for the Wasm blob: -### Unsigned Transactions +```bash +ls -la ./target/release/wbuild/parachain-template-runtime/ +``` -Unsigned transactions do not require a signature or account-specific data from the sender. Unlike signed transactions, they do not come with any form of economic deterrent, such as fees, which makes them susceptible to spam or replay attacks. Custom validation logic must be implemented to mitigate these risks and ensure these transactions are secure. +You should see the `parachain_template_runtime.compact.compressed.wasm` file in the output, confirming the build was successful. -Unsigned transactions typically involve scenarios where including a fee or signature is unnecessary or counterproductive. However, due to the absence of fees, they require careful validation to protect the network. For example, [`pallet_im_online::Call::heartbeat`](https://paritytech.github.io/polkadot-sdk/master/pallet_im_online/pallet/struct.Pallet.html#method.heartbeat){target=\_blank} extrinsic allows validators to send a heartbeat signal, indicating they are active. Since only validators can make this call, the logic embedded in the transaction ensures that the sender is a validator, making the need for a signature or fee redundant. +## Run the Node Locally -Unsigned transactions are more resource-intensive than signed ones because custom validation is required, but they play a crucial role in certain operational scenarios, especially when regular user accounts aren't involved. +After successfully compiling your runtime, you can spin up a local chain and produce blocks. This process will start your local parachain using the Polkadot Omni Node and allow you to interact with it. You'll first need to generate a chain specification that defines your network's identity, initial connections, and genesis state, providing the foundational configuration for how your nodes connect and what initial state they agree upon. -### Inherent Transactions +Follow these steps to launch your node in development mode: -Inherent transactions are a specialized type of unsigned transaction that is used primarily for block authoring. Unlike signed or other unsigned transactions, inherent transactions are added directly by block producers and are not broadcasted to the network or stored in the transaction queue. They don't require signatures or the usual validation steps and are generally used to insert system-critical data directly into blocks. +1. Generate the chain specification file of your parachain: -A key example of an inherent transaction is inserting a timestamp into each block. The [`pallet_timestamp::Call::now`](https://paritytech.github.io/polkadot-sdk/master/pallet_timestamp/pallet/struct.Pallet.html#method.now-1){target=\_blank} extrinsic allows block authors to include the current time in the block they are producing. Since the block producer adds this information, there is no need for transaction validation, like signature verification. The validation in this case is done indirectly by the validators, who check whether the timestamp is within an acceptable range before finalizing the block. + ```bash + chain-spec-builder create -t development \ + --relay-chain paseo \ + --para-id 1000 \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ + named-preset development + ``` -Another example is the [`paras_inherent::Call::enter`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/paras_inherent/pallet/struct.Pallet.html#method.enter){target=\_blank} extrinsic, which enables parachain collator nodes to send validation data to the relay chain. This inherent transaction ensures that the necessary parachain data is included in each block without the overhead of gossiped transactions. +2. Start the Omni Node with the generated chain spec. You'll start it in development mode (without a relay chain config), producing and finalizing blocks: -Inherent transactions serve a critical role in block authoring by allowing important operational data to be added directly to the chain without needing the validation processes required for standard transactions. + ```bash + polkadot-omni-node --chain ./chain_spec.json --dev + ``` -## Transaction Formats + The `--dev` option does the following: -Understanding the structure of signed and unsigned transactions is crucial for developers building on Polkadot SDK-based chains. Whether you're optimizing transaction processing, customizing formats, or interacting with the transaction pool, knowing the format of extrinsics, Polkadot's term for transactions, is essential. + - Deletes all active data (keys, blockchain database, networking information) when stopped. + - Ensures a clean working state each time you restart the node. -### Types of Transaction Formats +3. Verify that your node is running by reviewing the terminal output. You should see log messages indicating block production and finalization. -In Polkadot SDK-based chains, extrinsics can fall into three main categories: +4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output. -- **Unchecked extrinsics**: Typically used for signed transactions that require validation. They contain a signature and additional data, such as a nonce and information for fee calculation. Unchecked extrinsics are named as such because they require validation checks before being accepted into the transaction pool. -- **Checked extrinsics**: Typically used for inherent extrinsics (unsigned transactions); these don't require signature verification. Instead, they carry information such as where the extrinsic originates and any additional data required for the block authoring process. -- **Opaque extrinsics**: Used when the format of an extrinsic is not yet fully committed or finalized. They are still decodable, but their structure can be flexible depending on the context. +The details of the log output will be explored in a later tutorial. For now, knowing that your node is running and producing blocks is sufficient. -### Signed Transaction Data Structure +## Interact with the Node -A signed transaction typically includes the following components: +When running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} interface, follow these steps: -- **Signature**: Verifies the authenticity of the transaction sender. -- **Call**: The actual function or method call the transaction is requesting (for example, transferring funds). -- **Nonce**: Tracks the number of prior transactions sent from the account, helping to prevent replay attacks. -- **Tip**: An optional incentive to prioritize the transaction in block inclusion. -- **Additional data**: Includes details such as spec version, block hash, and genesis hash to ensure the transaction is valid within the correct runtime and chain context. +1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner: + + ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp) -Here's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime: +2. Connect to your local node: -``` code - + + -``` + 1. Scroll to the bottom and select **Development**. + 2. Choose **Custom**. + 3. Enter `ws://localhost:9944` in the **custom endpoint** input field. + 4. Click the **Switch** button. + + ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp) -Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. +3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain. + + ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp) -### Signed Extensions +You are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\_blank} available on the Polkadot Wiki. -Polkadot SDK also provides the concept of [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}, which allow developers to extend extrinsics with additional data or validation logic before they are included in a block. The [`SignedExtension`](https://paritytech.github.io/try-runtime-cli/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} set helps enforce custom rules or protections, such as ensuring the transaction's validity or calculating priority. +## Stop the Node -The transaction queue regularly calls signed extensions to verify a transaction's validity before placing it in the ready queue. This safeguard ensures transactions won't fail in a block. Signed extensions are commonly used to enforce validation logic and protect the transaction pool from spam and replay attacks. +When you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time. -In FRAME, a signed extension can hold any of the following types by default: +To stop the local node: -- **[`AccountId`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/types_common/type.AccountId.html){target=\_blank}**: To encode the sender's identity. -- **[`Call`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Call){target=\_blank}**: To encode the pallet call to be dispatched. This data is used to calculate transaction fees. -- **[`AdditionalSigned`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.AdditionalSigned){target=\_blank}**: To handle any additional data to go into the signed payload allowing you to attach any custom logic prior to dispatching a transaction. -- **[`Pre`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Pre){target=\_blank}**: To encode the information that can be passed from before a call is dispatched to after it gets dispatched. +1. Return to the terminal window where the node output is displayed. +2. Press `Control-C` to stop the running process. +3. Verify that your terminal returns to the prompt in the `parachain-template` directory. -Signed extensions can enforce checks like: +## Where to Go Next -- **[`CheckSpecVersion`](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/extensions/check_spec_version.rs.html){target=\_blank}**: Ensures the transaction is compatible with the runtime's current version. -- **[`CheckWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.CheckWeight.html){target=\_blank}**: Calculates the weight (or computational cost) of the transaction, ensuring the block doesn't exceed the maximum allowed weight. +
    -These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. +- Tutorial __Deploy to Polkadot__ -## Transaction Construction + --- -Building transactions in the Polkadot SDK involves constructing a payload that can be verified, signed, and submitted for inclusion in a block. Each runtime in the Polkadot SDK has its own rules for validating and executing transactions, but there are common patterns for constructing a signed transaction. + Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks. -### Construct a Signed Transaction + [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md) -A signed transaction in the Polkadot SDK includes various pieces of data to ensure security, prevent replay attacks, and prioritize processing. Here's an overview of how to construct one: +
    -1. **Construct the unsigned payload**: Gather the necessary information for the call, including: - - **Pallet index**: Identifies the pallet where the runtime function resides. - - **Function index**: Specifies the particular function to call in the pallet. - - **Parameters**: Any additional arguments required by the function call. +--- -2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: +Page Title: Smart Contracts Cookbook Index - - **Transaction nonce**: Unique identifier to prevent replay attacks. - - **Era information**: Defines how long the transaction is valid before it's dropped from the pool. - - **Block hash**: Ensures the transaction doesn't execute on the wrong chain or fork. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/ +- Summary: Explore our full collection of tutorials and guides to learn step-by-step how to build, deploy, and work with smart contracts on Polkadot. -3. **Sign the payload**: Using the sender's private key, sign the payload to ensure that the transaction can only be executed by the account holder. -4. **Serialize the signed payload**: Once signed, the transaction must be serialized into a binary format, ensuring the data is compact and easy to transmit over the network. -5. **Submit the serialized transaction**: Finally, submit the serialized transaction to the network, where it will enter the transaction pool and wait for processing by an authoring node. +# Smart Contracts Cookbook -The following is an example of how a signed transaction might look: +Welcome to the Polkadot smart contracts cookbook index. -``` rust -node_runtime::UncheckedExtrinsic::new_signed( - function.clone(), // some call - sp_runtime::AccountId32::from(sender.public()).into(), // some sending account - node_runtime::Signature::Sr25519(signature.clone()), // the account's signature - extra.clone(), // the signed extensions -) -``` +This page contains a list of all relevant tutorials and guides to help you get started coding smart contracts and dApps in Polkadot. -### Transaction Encoding -Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: -- **`[1]`**: Compact encoded length in bytes of the entire transaction. -- **`[2]`**: A u8 containing 1 byte to indicate whether the transaction is signed or unsigned (1 bit) and the encoded transaction version ID (7 bits). -- **`[3]`**: If signed, this field contains an account ID, an SR25519 signature, and some extra data. -- **`[4]`**: Encoded call data, including pallet and function indices and any required arguments. -This encoded format ensures consistency and efficiency in processing transactions across the network. By adhering to this format, applications can construct valid transactions and pass them to the network for execution. +## Get Tokens from the Faucet -To learn more about how compact encoding works using SCALE, see the [SCALE Codec](https://github.com/paritytech/parity-scale-codec){target=\_blank} README on GitHub. +| Title | Difficulty | Tools | Description | +|------------------------------------|:-----------:|-------|-----------------------------------------------------------------------------------------------------------------------| +| [Faucet](/smart-contracts/faucet/) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. | -### Customize Transaction Construction +## EVM/PVM Smart Contracts -Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: +| Title | Difficulty | Tools | Description | +|---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. | +| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | -- **Custom pallets**: You can define new pallets with custom function calls, each with its own parameters and validation logic. -- **Signed extensions**: Developers can implement custom extensions that modify how transactions are prioritized, validated, or included in blocks. +## Port Ethereum DApps -By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. +| Title | Difficulty | Tools | Description | +|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| +| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | -## Lifecycle of a Transaction -In the Polkadot SDK, transactions are often referred to as extrinsics because the data in transactions originates outside of the runtime. These transactions contain data that initiates changes to the chain state. The most common type of extrinsic is a signed transaction, which is cryptographically verified and typically incurs a fee. This section focuses on how signed transactions are processed, validated, and ultimately included in a block. +--- -### Define Transaction Properties +Page Title: Smart Contracts Overview -The Polkadot SDK runtime defines key transaction properties, such as: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ +- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. -- **Transaction validity**: Ensures the transaction meets all runtime requirements. -- **Signed or unsigned**: Identifies whether a transaction needs to be signed by an account. -- **State changes**: Determines how the transaction modifies the state of the chain. +# Smart Contracts on Polkadot -Pallets, which compose the runtime's logic, define the specific transactions that your chain supports. When a user submits a transaction, such as a token transfer, it becomes a signed transaction, verified by the user's account signature. If the account has enough funds to cover fees, the transaction is executed, and the chain's state is updated accordingly. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -### Process on a Block Authoring Node +Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. -In Polkadot SDK-based networks, some nodes are authorized to author blocks. These nodes validate and process transactions. When a transaction is sent to a node that can produce blocks, it undergoes a lifecycle that involves several stages, including validation and execution. Non-authoring nodes gossip the transaction across the network until an authoring node receives it. The following diagram illustrates the lifecycle of a transaction that's submitted to a network and processed by an authoring node. +Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. -![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } +These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. -### Validate and Queue +## Native Smart Contracts -Once a transaction reaches an authoring node, it undergoes an initial validation process to ensure it meets specific conditions defined in the runtime. This validation includes checks for: +### Introduction -- **Correct nonce**: Ensures the transaction is sequentially valid for the account. -- **Sufficient funds**: Confirms the account can cover any associated transaction fees. -- **Signature validity**: Verifies that the sender's signature matches the transaction data. +Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. -After these checks, valid transactions are placed in the transaction pool, where they are queued for inclusion in a block. The transaction pool regularly re-validates queued transactions to ensure they remain valid before being processed. To reach consensus, two-thirds of the nodes must agree on the order of the transactions executed and the resulting state change. Transactions are validated and queued on the local node in a transaction pool to prepare for consensus. +### Smart Contract Development -#### Transaction Pool +The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. -The transaction pool is responsible for managing valid transactions. It ensures that only transactions that pass initial validity checks are queued. Transactions that fail validation, expire, or become invalid for other reasons are removed from the pool. +Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. -The transaction pool organizes transactions into two queues: +### Technical Architecture -- **Ready queue**: Transactions that are valid and ready to be included in a block. -- **Future queue**: Transactions that are not yet valid but could be in the future, such as transactions with a nonce too high for the current state. +PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: -Details on how the transaction pool validates transactions, including fee and signature handling, can be found in the [`validate_transaction`](https://paritytech.github.io/polkadot-sdk/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction){target=\_blank} method. +- Enhanced performance for smart contract execution. +- Improved gas efficiency for complex operations. +- Native compatibility with Polkadot's runtime environment. +- Optimized storage and state management. -#### Invalid Transactions +### Development Tools and Resources -If a transaction is invalid, for example, due to an invalid signature or insufficient funds, it is rejected and won't be added to the block. Invalid transactions might be rejected for reasons such as: +Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: -- The transaction has already been included in a block. -- The transaction's signature does not match the sender. -- The transaction is too large to fit in the current block. +- Contract development in Solidity or Rust. +- Support for standard Ethereum development libraries. +- Integration with widely used development environments. +- Access to blockchain explorers and indexing solutions. +- Compatibility with contract monitoring and management tools. -### Transaction Ordering and Priority +### Cross-Chain Capabilities -When a node is selected as the next block author, it prioritizes transactions based on weight, length, and tip amount. The goal is to fill the block with high-priority transactions without exceeding its maximum size or computational limits. Transactions are ordered as follows: +Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. -- **Inherents first**: Inherent transactions, such as block timestamp updates, are always placed first. -- **Nonce-based ordering**: Transactions from the same account are ordered by their nonce. -- **Fee-based ordering**: Among transactions with the same nonce or priority level, those with higher fees are prioritized. +### Use Cases -### Transaction Execution +Polkadot Hub's smart contract platform is suitable for a wide range of applications: -Once a block author selects transactions from the pool, the transactions are executed in priority order. As each transaction is processed, the state changes are written directly to the chain's storage. It's important to note that these changes are not cached, meaning a failed transaction won't revert earlier state changes, which could leave the block in an inconsistent state. +- DeFi protocols leveraging _cross-chain capabilities_. +- NFT platforms utilizing Polkadot's native token standards. +- Governance systems integrated with Polkadot's democracy mechanisms. +- Cross-chain bridges and asset management solutions. -Events are also written to storage. Runtime logic should not emit an event before performing the associated actions. If the associated transaction fails after the event was emitted, the event will not revert. +## Other Smart Contract Environments -## Transaction Mortality +Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: -Transactions in the network can be configured as either mortal (with expiration) or immortal (without expiration). Every transaction payload contains a block checkpoint (reference block number and hash) and an era/validity period that determines how many blocks after the checkpoint the transaction remains valid. +- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). -When a transaction is submitted, the network validates it against these parameters. If the transaction is not included in a block within the specified validity window, it is automatically removed from the transaction queue. +- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. -- **Mortal transactions**: Have a finite lifespan and will expire after a specified number of blocks. For example, a transaction with a block checkpoint of 1000 and a validity period of 64 blocks will be valid from blocks 1000 to 1064. -- **Immortal transactions**: Never expire and remain valid indefinitely. To create an immortal transaction, set the block checkpoint to 0 (genesis block), use the genesis hash as a reference, and set the validity period to 0. +Each environment provides unique advantages based on developer preferences and application requirements. -However, immortal transactions pose significant security risks through replay attacks. If an account is reaped (balance drops to zero, account removed) and later re-funded, malicious actors can replay old immortal transactions. +## Where to Go Next -The blockchain maintains only a limited number of prior block hashes for reference validation, called `BlockHashCount`. If your validity period exceeds `BlockHashCount`, the effective validity period becomes the minimum of your specified period and the block hash count. +Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. -## Unique Identifiers for Extrinsics +Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. -Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. +
    -Key differences from traditional blockchains: +- Guide __Libraries__ -- Transaction hashes serve only as fingerprints of transaction information. -- Multiple valid transactions can share the same hash. -- Hash uniqueness assumptions lead to serious issues. + --- -For example, when an account is reaped (removed due to insufficient balance) and later recreated, it resets to nonce 0, allowing identical transactions to be valid at different points: + Explore essential libraries to optimize smart contract development and interaction. -| Block | Extrinsic Index | Hash | Origin | Nonce | Call | Result | -|-------|----------------|------|-----------|-------|---------------------|-------------------------------| -| 100 | 0 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Account A reaped | -| 150 | 5 | 0x02 | Account B | 4 | Transfer 7 DOT to A | Account A created (nonce = 0) | -| 200 | 2 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Successful transaction | + [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) -Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. +- Guide __Dev Environments__ -Additional complexity comes from Polkadot SDK's origin abstraction. Origins can represent collectives, governance bodies, or other non-account entities that don't maintain nonces like regular accounts and might dispatch identical calls multiple times with the same hash values. Each execution occurs in different chain states with different results. + --- -The correct way to uniquely identify an extrinsic on a Polkadot SDK-based chain is to use the block ID (height or hash) and the extrinsic index. Since the Polkadot SDK defines blocks as headers plus ordered arrays of extrinsics, the index position within a canonical block provides guaranteed uniqueness. + Set up your development environment for seamless contract deployment and testing. -## Additional Resources + [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) -For a video overview of the lifecycle of transactions and the types of transactions that exist, see the [Transaction lifecycle](https://www.youtube.com/watch?v=3pfM0GOp02c){target=\_blank} seminar from Parity Tech. +
    --- @@ -8604,351 +4029,6 @@ The system maintains precise conversion mechanisms between: This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. ---- - -Page Title: Transactions Weights and Fees - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/ -- Summary: Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. - -# Transactions Weights and Fees - -## Introductions - -When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop the network from producing new blocks. To protect blockchain resources from being drained or overloaded, you need to manage how they are made available and how they are consumed. The resources to be aware of include: - -- Memory usage -- Storage input and output -- Computation -- Transaction and block size -- State database size - -The Polkadot SDK provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource. Two of the most important mechanisms available to block authors are weights and transaction fees. - -[Weights](/reference/glossary/#weight){target=\_blank} manage the time it takes to validate a block and characterize the time it takes to execute the calls in the block's body. By controlling the execution time a block can consume, weights set limits on storage input, output, and computation. - -Some of the weight allowed for a block is consumed as part of the block's initialization and finalization. The weight might also be used to execute mandatory inherent extrinsic calls. To help ensure blocks don’t consume too much execution time and prevent malicious users from overloading the system with unnecessary calls, weights are combined with transaction fees. - -[Transaction fees](/reference/parachains/blocks-transactions-fees/transactions/#transaction-fees){target=\_blank} provide an economic incentive to limit execution time, computation, and the number of calls required to perform operations. Transaction fees are also used to make the blockchain economically sustainable because they are typically applied to transactions initiated by users and deducted before a transaction request is executed. - -## How Fees are Calculated - -The final fee for a transaction is calculated using the following parameters: - -- **`base fee`**: This is the minimum amount a user pays for a transaction. It is declared a base weight in the runtime and converted to a fee using the [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} conversion. -- **`weight fee`**: A fee proportional to the execution time (input and output and computation) that a transaction consumes. -- **`length fee`**: A fee proportional to the encoded length of the transaction. -- **`tip`**: An optional tip to increase the transaction’s priority, giving it a higher chance to be included in the transaction queue. - -The base fee and proportional weight and length fees constitute the inclusion fee. The inclusion fee is the minimum fee that must be available for a transaction to be included in a block. - -```text -inclusion fee = base fee + weight fee + length fee -``` - -Transaction fees are withdrawn before the transaction is executed. After the transaction is executed, the weight can be adjusted to reflect the resources used. If a transaction uses fewer resources than expected, the transaction fee is corrected, and the adjusted transaction fee is deposited. - -## Using the Transaction Payment Pallet - -The [Transaction Payment pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/transaction-payment){target=\_blank} provides the basic logic for calculating the inclusion fee. You can also use the Transaction Payment pallet to: - -- Convert a weight value into a deductible fee based on a currency type using [`Config::WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank}. -- Update the fee for the next block by defining a multiplier based on the chain’s final state at the end of the previous block using [`Config::FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank}. -- Manage the withdrawal, refund, and deposit of transaction fees using [`Config::OnChargeTransaction`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.OnChargeTransaction){target=\_blank}. - -You can learn more about these configuration traits in the [Transaction Payment documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_payment/index.html){target=\_blank}. - -### Understanding the Inclusion Fee - -The formula for calculating the inclusion fee is as follows: - -```text -inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] -``` - -And then, for calculating the final fee: - -```text -final_fee = inclusion_fee + tip -``` - -In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. - -- The `base_fee` derived from the base weight covers inclusion overhead like signature verification. -- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic. -- The `weight_fee` fee is calculated using two parameters: - - The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics. - - The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity. - -To convert the weight to `Currency`, the runtime must define a `WeightToFee` struct that implements a conversion function, [`Convert`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/struct.Pallet.html#method.weight_to_fee){target=\_blank}. - -Note that the extrinsic sender is charged the inclusion fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution. - -### Accounts with an Insufficient Balance - -If an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum existential deposit—then you should ensure the transaction is canceled so that no fee is deducted and the transaction does not begin execution. - -The Polkadot SDK doesn't enforce this rollback behavior. However, this scenario would be rare because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block. - -### Fee Multipliers - -The inclusion fee formula always results in the same fee for the same input. However, weight can be dynamic and—based on how [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} is defined—the final fee can include some degree of variability. -The Transaction Payment pallet provides the [`FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank} configurable parameter to account for this variability. - -The Polkadot network inspires the default update function and implements a targeted adjustment in which a target saturation level of block weight is defined. If the previous block is more saturated, the fees increase slightly. Similarly, if the last block has fewer transactions than the target, fees are decreased by a small amount. For more information about fee multiplier adjustments, see the [Web3 Research Page](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank}. - -## Transactions with Special Requirements - -Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: - -- Bonds are a type of fee that might be returned or slashed after some on-chain event. For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior. -- Deposits are fees that might be returned later. For example, you might require users to pay a deposit to execute an operation that uses storage. The user’s deposit could be returned if a subsequent operation frees up storage. -- Burn operations are used to pay for a transaction based on its internal logic. For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased state size. -- Limits enable you to enforce constant or configurable limits on specific operations. For example, the default [Staking pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/staking){target=\_blank} only allows nominators to nominate 16 validators to limit the complexity of the validator election process. - -It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. - -## Default Weight Annotations - -All dispatchable functions in the Polkadot SDK must specify a weight. The way of doing that is using the annotation-based system that lets you combine fixed values for database read/write weight and/or fixed values based on benchmarks. The most basic example would look like this: - -```rust -#[pallet::weight(100_000)] -fn my_dispatchable() { - // ... -} -``` - -Note that the [`ExtrinsicBaseWeight`](https://crates.parity.io/frame_support/weights/constants/struct.ExtrinsicBaseWeight.html){target=\_blank} is automatically added to the declared weight to account for the costs of simply including an empty extrinsic into a block. - -### Weights and Database Read/Write Operations - -To make weight annotations independent of the deployed database backend, they are defined as a constant and then used in the annotations when expressing database accesses performed by the dispatchable: - -```rust -#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] -fn my_dispatchable() { - // ... -} -``` - -This dispatchable allows one database to read and two to write, in addition to other things that add the additional 20,000. Database access is generally every time a value declared inside the [`#[pallet::storage]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} block is accessed. However, unique accesses are counted because after a value is accessed, it is cached, and reaccessing it does not result in a database operation. That is: - -- Multiple reads of the exact value count as one read. -- Multiple writes of the exact value count as one write. -- Multiple reads of the same value, followed by a write to that value, count as one read and one write. -- A write followed by a read-only counts as one write. - -### Dispatch Classes - -Dispatches are broken into three classes: - -- Normal -- Operational -- Mandatory - -If a dispatch is not defined as `Operational` or `Mandatory` in the weight annotation, the dispatch is identified as `Normal` by default. You can specify that the dispatchable uses another class like this: - -```rust -#[pallet::dispatch((DispatchClass::Operational))] -fn my_dispatchable() { - // ... -} -``` - -This tuple notation also allows you to specify a final argument determining whether the user is charged based on the annotated weight. If you don't specify otherwise, `Pays::Yes` is assumed: - -```rust -#[pallet::dispatch(DispatchClass::Normal, Pays::No)] -fn my_dispatchable() { - // ... -} -``` - -#### Normal Dispatches - -Dispatches in this class represent normal user-triggered transactions. These types of dispatches only consume a portion of a block's total weight limit. For information about the maximum portion of a block that can be consumed for normal dispatches, see [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Normal dispatches are sent to the transaction pool. - -#### Operational Dispatches - -Unlike normal dispatches, which represent the usage of network capabilities, operational dispatches are those that provide network capabilities. Operational dispatches can consume the entire weight limit of a block. They are not bound by the [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Dispatches in this class are given maximum priority and are exempt from paying the [`length_fee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/){target=\_blank}. - -#### Mandatory Dispatches - -Mandatory dispatches are included in a block even if they cause the block to surpass its weight limit. You can only use the mandatory dispatch class for inherent transactions that the block author submits. This dispatch class is intended to represent functions in the block validation process. Because these dispatches are always included in a block regardless of the function weight, the validation process must prevent malicious nodes from abusing the function to craft valid but impossibly heavy blocks. You can typically accomplish this by ensuring that: - -- The operation performed is always light. -- The operation can only be included in a block once. - -To make it more difficult for malicious nodes to abuse mandatory dispatches, they cannot be included in blocks that return errors. This dispatch class serves the assumption that it is better to allow an overweight block to be created than not to allow any block to be created at all. - -### Dynamic Weights - -In addition to purely fixed weights and constants, the weight calculation can consider the input arguments of a dispatchable. The weight should be trivially computable from the input arguments with some basic arithmetic: - -```rust -use frame_support:: { - dispatch:: { - DispatchClass::Normal, - Pays::Yes, - }, - weights::Weight, -}; - -#[pallet::weight(FunctionOf( - |args: (&Vec,)| args.0.len().saturating_mul(10_000), - ) -] -fn handle_users(origin, calls: Vec) { - // Do something per user -} -``` - -## Post Dispatch Weight Correction - -Depending on the execution logic, a dispatchable function might consume less weight than was prescribed pre-dispatch. To correct weight, the function declares a different return type and returns its actual weight: - -```rust -#[pallet::weight(10_000 + 500_000_000)] -fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo { - let was_heavy = do_calculation(input); - - if (was_heavy) { - // None means "no correction" from the weight annotation. - Ok(None.into()) - } else { - // Return the actual weight consumed. - Ok(Some(10_000).into()) - } -} -``` - -## Custom Fees - -You can also define custom fee systems through custom weight functions or inclusion fee functions. - -### Custom Weights - -Instead of using the default weight annotations, you can create a custom weight calculation type using the weights module. The custom weight calculation type must implement the following traits: - -- [`WeighData`](https://crates.parity.io/frame_support/weights/trait.WeighData.html){target=\_blank} to determine the weight of the dispatch. -- [`ClassifyDispatch`](https://crates.parity.io/frame_support/weights/trait.ClassifyDispatch.html){target=\_blank} to determine the class of the dispatch. -- [`PaysFee`](https://crates.parity.io/frame_support/weights/trait.PaysFee.html){target=\_blank} to determine whether the sender of the dispatch pays fees. - -The Polkadot SDK then bundles the output information of the three traits into the [`DispatchInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.DispatchInfo.html){target=\_blank} struct and provides it by implementing the [`GetDispatchInfo`](https://docs.rs/frame-support/latest/frame_support/dispatch/trait.GetDispatchInfo.html){target=\_blank} for all `Call` variants and opaque extrinsic types. This is used internally by the System and Executive modules. - -`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over T, which gets resolved into the tuple of all dispatch arguments except for the origin. The following example illustrates a struct that calculates the weight as `m * len(args)`, where `m` is a given multiplier and args is the concatenated tuple of all dispatch arguments. In this example, the dispatch class is `Operational` if the transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length exceeds 10 bytes. - -```rust -struct LenWeight(u32); -impl WeighData for LenWeight { - fn weigh_data(&self, target: T) -> Weight { - let multiplier = self.0; - let encoded_len = target.encode().len() as u32; - multiplier * encoded_len - } -} - -impl ClassifyDispatch for LenWeight { - fn classify_dispatch(&self, target: T) -> DispatchClass { - let encoded_len = target.encode().len() as u32; - if encoded_len > 100 { - DispatchClass::Operational - } else { - DispatchClass::Normal - } - } -} - -impl PaysFee { - fn pays_fee(&self, target: T) -> Pays { - let encoded_len = target.encode().len() as u32; - if encoded_len > 10 { - Pays::Yes - } else { - Pays::No - } - } -} -``` - -A weight calculator function can also be coerced to the final type of the argument instead of defining it as a vague type that can be encoded. The code would roughly look like this: - -```rust -struct CustomWeight; -impl WeighData<(&u32, &u64)> for CustomWeight { - fn weigh_data(&self, target: (&u32, &u64)) -> Weight { - ... - } -} - -// given a dispatch: -#[pallet::call] -impl, I: 'static> Pallet { - #[pallet::weight(CustomWeight)] - fn foo(a: u32, b: u64) { ... } -} -``` - -In this example, the `CustomWeight` can only be used in conjunction with a dispatch with a particular signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because there aren't any assumptions about ``. - -#### Custom Inclusion Fee - -The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. - -```rust -// Assume this is the balance type -type Balance = u64; - -// Assume we want all the weights to have a `100 + 2 * w` conversion to fees -struct CustomWeightToFee; -impl WeightToFee for CustomWeightToFee { - fn convert(w: Weight) -> Balance { - let a = Balance::from(100); - let b = Balance::from(2); - let w = Balance::from(w); - a + b * w - } -} - -parameter_types! { - pub const ExtrinsicBaseWeight: Weight = 10_000_000; -} - -impl frame_system::Config for Runtime { - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; -} - -parameter_types! { - pub const TransactionByteFee: Balance = 10; -} - -impl transaction_payment::Config { - type TransactionByteFee = TransactionByteFee; - type WeightToFee = CustomWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} - -struct TargetedFeeAdjustment(sp_std::marker::PhantomData); -impl> WeightToFee for TargetedFeeAdjustment { - fn convert(multiplier: Fixed128) -> Fixed128 { - // Don't change anything. Put any fee update info here. - multiplier - } -} -``` - -## Additional Resources - -You now know the weight system, how it affects transaction fee computation, and how to specify weights for your dispatchable calls. The next step is determining the correct weight for your dispatchable operations. You can use Substrate benchmarking functions and frame-benchmarking calls to test your functions with different parameters and empirically determine the proper weight in their worst-case scenarios. - -- [Benchmark](/parachains/customize-runtime/pallet-development/benchmark-pallet/) -- [`SignedExtension`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} -- [Custom weights for the Example pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/examples/basic/src/weights.rs){target=\_blank} -- [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} - - --- Page Title: Wallets @@ -9035,91 +4115,3 @@ Wallet types fall into two categories based on their connection to the internet:
    - - ---- - -Page Title: XCM Tools - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/xcm-tools/ -- Summary: Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. - -# XCM Tools - -## Introduction - -As described in the [Interoperability](/develop/interoperability){target=\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem. - -As XCM is central to enabling communication between blockchains, developers need robust tools to help interact with, build, and test XCM messages. Several XCM tools simplify working with the protocol by providing libraries, frameworks, and utilities that enhance the development process, ensuring that applications built within the Polkadot ecosystem can efficiently use cross-chain functionalities. - -## Popular XCM Tools - -### Moonsong Labs XCM Tools - -[Moonsong Labs XCM Tools](https://github.com/Moonsong-Labs/xcm-tools){target=\_blank} provides a collection of scripts for managing and testing XCM operations between Polkadot SDK-based runtimes. These tools allow performing tasks like asset registration, channel setup, and XCM initialization. Key features include: - -- **Asset registration**: Registers assets, setting units per second (up-front fees), and configuring error (revert) codes. -- **XCM initializer**: Initializes XCM, sets default XCM versions, and configures revert codes for XCM-related precompiles. -- **HRMP manipulator**: Manages HRMP channel actions, including opening, accepting, or closing channels. -- **XCM-Transactor-Info-Setter**: Configures transactor information, including extra weight and fee settings. -- **Decode XCM**: Decodes XCM messages on the relay chain or parachains to help interpret cross-chain communication. - -To get started, clone the repository and install the required dependencies: - -```bash -git clone https://github.com/Moonsong-Labs/xcm-tools && -cd xcm-tools && -yarn install -``` - -For a full overview of each script, visit the [scripts](https://github.com/Moonsong-Labs/xcm-tools/tree/main/scripts){target=\_blank} directory or refer to the [official documentation](https://github.com/Moonsong-Labs/xcm-tools/blob/main/README.md){target=\_blank} on GitHub. - -### ParaSpell - -[ParaSpell](/reference/tools/paraspell/){target=\_blank} is a collection of open-source XCM tools that streamline cross-chain asset transfers and interactions across the Polkadot and Kusama ecosystems. It provides developers with an intuitive interface to build, test, and deploy interoperable dApps, featuring message composition, decoding, and practical utilities for parachain interactions that simplify debugging and cross-chain communication optimization. - -### Astar XCM Tools - -The [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks: - -- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command. -- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments. -- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs. - -To start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\_blank} and compile the xcm-tools package: - -```bash -git clone https://github.com/AstarNetwork/Astar && -cd Astar && -cargo build --release -p xcm-tools -``` - -After compiling, verify the setup with the following command: - -```bash -./target/release/xcm-tools --help -``` -For more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\_blank}. - -### Chopsticks - -The Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\_blank} about XCM. - -### Moonbeam XCM SDK - -The [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank} of the origin or destination assets or which extrinsics are used on which networks. - -The SDK consists of two main packages: - -- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem. -- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum. - -Key features include: - -- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection. -- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems. -- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality. -- **Comprehensive documentation**: Includes usage guides and API references for both packages. - -For detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\_blank}. diff --git a/.ai/categories/infrastructure.md b/.ai/categories/infrastructure.md index 100597494..fdb9107eb 100644 --- a/.ai/categories/infrastructure.md +++ b/.ai/categories/infrastructure.md @@ -474,440 +474,6 @@ Launch your parachain locally and start producing blocks:
    ---- - -Page Title: Blocks - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/ -- Summary: Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. - -# Blocks - -## Introduction - -In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the network. By understanding these concepts, developers can better grasp how blockchains maintain security, consistency, and performance within the Polkadot ecosystem. - -## What is a Block? - -In the Polkadot SDK, a block is a fundamental unit that encapsulates both the header and an array of transactions. The block header includes critical metadata to ensure the integrity and sequence of the blockchain. Here's a breakdown of its components: - -- **Block height**: Indicates the number of blocks created in the chain so far. -- **Parent hash**: The hash of the previous block, providing a link to maintain the blockchain's immutability. -- **Transaction root**: Cryptographic digest summarizing all transactions in the block. -- **State root**: A cryptographic digest representing the post-execution state. -- **Digest**: Additional information that can be attached to a block, such as consensus-related messages. - -Each transaction is part of a series that is executed according to the runtime's rules. The transaction root is a cryptographic digest of this series, which prevents alterations and enables succinct verification by light clients. This verification process allows light clients to confirm whether a transaction exists in a block with only the block header, avoiding downloading the entire block. - -## Block Production - -When an authoring node is authorized to create a new block, it selects transactions from the transaction queue based on priority. This step, known as block production, relies heavily on the executive module to manage the initialization and finalization of blocks. The process is summarized as follows: - -### Initialize Block - -The block initialization process begins with a series of function calls that prepare the block for transaction execution: - -1. **Call `on_initialize`**: The executive module calls the [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hook from the system pallet and other runtime pallets to prepare for the block's transactions. -2. **Coordinate runtime calls**: Coordinates function calls in the order defined by the transaction queue. -3. **Verify information**: Once [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} functions are executed, the executive module checks the parent hash in the block header and the trie root to verify information is consistent. - -### Finalize Block - -Once transactions are processed, the block must be finalized before being broadcast to the network. The finalization steps are as follows: - -1. **Call `on_finalize`**: The executive module calls the [`on_finalize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_finalize){target=\_blank} hooks in each pallet to ensure any remaining state updates or checks are completed before the block is sealed and published. -2. **Verify information**: The block's digest and storage root in the header are checked against the initialized block to ensure consistency. -3. **Call `on_idle`**: The [`on_idle`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_idle){target=\_blank} hook is triggered to process any remaining tasks using the leftover weight from the block. - -## Block Authoring and Import - -Once the block is finalized, it is gossiped to other nodes in the network. Nodes follow this procedure: - -1. **Receive transactions**: The authoring node collects transactions from the network. -2. **Validate**: Transactions are checked for validity. -3. **Queue**: Valid transactions are placed in the transaction pool for execution. -4. **Execute**: State changes are made as the transactions are executed. -5. **Publish**: The finalized block is broadcast to the network. - -### Block Import Queue - -After a block is published, other nodes on the network can import it into their chain state. The block import queue is part of the outer node in every Polkadot SDK-based node and ensures incoming blocks are valid before adding them to the node's state. - -In most cases, you don't need to know details about how transactions are gossiped or how other nodes on the network import blocks. The following traits are relevant, however, if you plan to write any custom consensus logic or want a deeper dive into the block import queue: - -- **[`ImportQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.ImportQueue.html){target=\_blank}**: The trait that defines the block import queue. -- **[`Link`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Link.html){target=\_blank}**: The trait that defines the link between the block import queue and the network. -- **[`BasicQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/struct.BasicQueue.html){target=\_blank}**: A basic implementation of the block import queue. -- **[`Verifier`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Verifier.html){target=\_blank}**: The trait that defines the block verifier. -- **[`BlockImport`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/block_import/trait.BlockImport.html){target=\_blank}**: The trait that defines the block import process. - -These traits govern how blocks are validated and imported across the network, ensuring consistency and security. - -## Additional Resources - -To learn more about the block structure in the Polkadot SDK runtime, see the [`Block` reference](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.Block.html){target=\_blank} entry in the Rust Docs. - - ---- - -Page Title: Chain Data - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/chain-data/ -- Summary: Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. - -# Chain Data - -## Introduction - -Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you can ensure seamless communication between your applications and the blockchain. - -## Application Development - -You might not be directly involved in building frontend applications as a blockchain developer. However, most applications that run on a blockchain require some form of frontend or user-facing client to enable users or other programs to access and modify the data that the blockchain stores. For example, you might develop a browser-based, mobile, or desktop application that allows users to submit transactions, post articles, view their assets, or track previous activity. The backend for that application is configured in the runtime logic for your blockchain, but the frontend client makes the runtime features accessible to your users. - -For your custom chain to be useful to others, you'll need to provide a client application that allows users to view, interact with, or update information that the blockchain keeps track of. In this article, you'll learn how to expose information about your runtime so that client applications can use it, see examples of the information exposed, and explore tools and libraries that use it. - -## Understand Metadata - -Polkadot SDK-based blockchain networks are designed to expose their runtime information, allowing developers to learn granular details regarding pallets, RPC calls, and runtime APIs. The metadata also exposes their related documentation. The chain's metadata is [SCALE-encoded](/reference/parachains/data-encoding/){target=\_blank}, allowing for the development of browser-based, mobile, or desktop applications to support the chain's runtime upgrades seamlessly. It is also possible to develop applications compatible with multiple Polkadot SDK-based chains simultaneously. - -## Expose Runtime Information as Metadata - -To interact with a node or the state of the blockchain, you need to know how to connect to the chain and access the exposed runtime features. This interaction involves a Remote Procedure Call (RPC) through a node endpoint address, commonly through a secure web socket connection. - -An application developer typically needs to know the contents of the runtime logic, including the following details: - -- Version of the runtime the application is connecting to. -- Supported APIs. -- Implemented pallets. -- Defined functions and corresponding type signatures. -- Defined custom types. -- Exposed parameters users can set. - -As the Polkadot SDK is modular and provides a composable framework for building blockchains, there are limitless opportunities to customize the schema of properties. Each runtime can be configured with its properties, including function calls and types, which can be changed over time with runtime upgrades. - -The Polkadot SDK enables you to generate the runtime metadata schema to capture information unique to a runtime. The metadata for a runtime describes the pallets in use and types defined for a specific runtime version. The metadata includes information about each pallet's storage items, functions, events, errors, and constants. The metadata also provides type definitions for any custom types included in the runtime. - -Metadata provides a complete inventory of a chain's runtime. It is key to enabling client applications to interact with the node, parse responses, and correctly format message payloads sent back to that chain. - -## Generate Metadata - -To efficiently use the blockchain's networking resources and minimize the data transmitted over the network, the metadata schema is encoded using the [Parity SCALE Codec](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank}. This encoding is done automatically through the [`scale-info`](https://docs.rs/scale-info/latest/scale_info/){target=\_blank}crate. - -At a high level, generating the metadata involves the following steps: - -1. The pallets in the runtime logic expose callable functions, types, parameters, and documentation that need to be encoded in the metadata. -2. The `scale-info` crate collects type information for the pallets in the runtime, builds a registry of the pallets that exist in a particular runtime, and the relevant types for each pallet in the registry. The type information is detailed enough to enable encoding and decoding for every type. -3. The [`frame-metadata`](https://github.com/paritytech/frame-metadata){target=\_blank} crate describes the structure of the runtime based on the registry provided by the `scale-info` crate. -4. Nodes provide the RPC method `state_getMetadata` to return a complete description of all the types in the current runtime as a hex-encoded vector of SCALE-encoded bytes. - -## Retrieve Runtime Metadata - -The type information provided by the metadata enables applications to communicate with nodes using different runtime versions and across chains that expose different calls, events, types, and storage items. The metadata also allows libraries to generate a substantial portion of the code needed to communicate with a given node, enabling libraries like [`subxt`](https://github.com/paritytech/subxt){target=\_blank} to generate frontend interfaces that are specific to a target chain. - -### Use Polkadot.js - -Visit the [Polkadot.js Portal](https://polkadot.js.org/apps/#/rpc){target=\_blank} and select the **Developer** dropdown in the top banner. Select **RPC Calls** to make the call to request metadata. Follow these steps to make the RPC call: - -1. Select **state** as the endpoint to call. -2. Select **`getMetadata(at)`** as the method to call. -3. Click **Submit RPC call** to submit the call and return the metadata in JSON format. - -### Use Curl - -You can fetch the metadata for the network by calling the node's RPC endpoint. This request returns the metadata in bytes rather than human-readable JSON: - -```sh -curl -H "Content-Type: application/json" \ --d '{"id":1, "jsonrpc":"2.0", "method": "state_getMetadata"}' \ -https://rpc.polkadot.io - -``` - -### Use Subxt - -[`subxt`](https://github.com/paritytech/subxt){target=\_blank} may also be used to fetch the metadata of any data in a human-readable JSON format: - -```sh -subxt metadata --url wss://rpc.polkadot.io --format json > spec.json -``` - -Another option is to use the [`subxt` explorer web UI](https://paritytech.github.io/subxt-explorer/#/){target=\_blank}. - -## Client Applications and Metadata - -The metadata exposes the expected way to decode each type, meaning applications can send, retrieve, and process application information without manual encoding and decoding. Client applications must use the [SCALE codec library](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank} to encode and decode RPC payloads to use the metadata. Client applications use the metadata to interact with the node, parse responses, and format message payloads sent to the node. - -## Metadata Format - -Although the SCALE-encoded bytes can be decoded using the `frame-metadata` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} libraries, there are other tools, such as `subxt` and the Polkadot-JS API, that can convert the raw data to human-readable JSON format. - -The types and type definitions included in the metadata returned by the `state_getMetadata` RPC call depend on the runtime's metadata version. - -In general, the metadata includes the following information: - -- A constant identifying the file as containing metadata. -- The version of the metadata format used in the runtime. -- Type definitions for all types used in the runtime and generated by the `scale-info` crate. -- Pallet information for the pallets included in the runtime in the order that they are defined in the `construct_runtime` macro. - -!!!tip - Depending on the frontend library used (such as the [Polkadot API](https://papi.how/){target=\_blank}), they may format the metadata differently than the raw format shown. - -The following example illustrates a condensed and annotated section of metadata decoded and converted to JSON: - -```json -[ - 1635018093, - { - "V14": { - "types": { - "types": [{}] - }, - "pallets": [{}], - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [{}] - }, - "ty": 141 - } - } -] - -``` - -The constant `1635018093` is a magic number that identifies the file as a metadata file. The rest of the metadata is divided into the `types`, `pallets`, and `extrinsic` sections: - -- The `types` section contains an index of the types and information about each type's type signature. -- The `pallets` section contains information about each pallet in the runtime. -- The `extrinsic` section describes the type identifier and transaction format version that the runtime uses. - -Different extrinsic versions can have varying formats, especially when considering [signed transactions](/reference/parachains/blocks-transactions-fees/transactions/#signed-transactions){target=\_blank}. - -### Pallets - -The following is a condensed and annotated example of metadata for a single element in the `pallets` array (the [`sudo`](https://paritytech.github.io/polkadot-sdk/master/pallet_sudo/index.html){target=\_blank} pallet): - -```json -{ - "name": "Sudo", - "storage": { - "prefix": "Sudo", - "entries": [ - { - "name": "Key", - "modifier": "Optional", - "ty": { - "Plain": 0 - }, - "default": [0], - "docs": ["The `AccountId` of the sudo key."] - } - ] - }, - "calls": { - "ty": 117 - }, - "event": { - "ty": 42 - }, - "constants": [], - "error": { - "ty": 124 - }, - "index": 8 -} - -``` - -Every element metadata contains the name of the pallet it represents and information about its storage, calls, events, and errors. You can look up details about the definition of the calls, events, and errors by viewing the type index identifier. The type index identifier is the `u32` integer used to access the type information for that item. For example, the type index identifier for calls in the Sudo pallet is 117. If you view information for that type identifier in the `types` section of the metadata, it provides information about the available calls, including the documentation for each call. - -For example, the following is a condensed excerpt of the calls for the Sudo pallet: - -```json -{ - "id": 117, - "type": { - "path": ["pallet_sudo", "pallet", "Call"], - "params": [ - { - "name": "T", - "type": null - } - ], - "def": { - "variant": { - "variants": [ - { - "name": "sudo", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 0, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "sudo_unchecked_weight", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - }, - { - "name": "weight", - "type": 8, - "typeName": "Weight" - } - ], - "index": 1, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "set_key", - "fields": [ - { - "name": "new", - "type": 103, - "typeName": "AccountIdLookupOf" - } - ], - "index": 2, - "docs": [ - "Authenticates current sudo key, sets the given AccountId (`new`) as the new sudo" - ] - }, - { - "name": "sudo_as", - "fields": [ - { - "name": "who", - "type": 103, - "typeName": "AccountIdLookupOf" - }, - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 3, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Signed` origin from a given account" - ] - } - ] - } - } - } -} - -``` - -For each field, you can access type information and metadata for the following: - -- **Storage metadata**: Provides the information required to enable applications to get information for specific storage items. -- **Call metadata**: Includes information about the runtime calls defined by the `#[pallet]` macro including call names, arguments and documentation. -- **Event metadata**: Provides the metadata generated by the `#[pallet::event]` macro, including the name, arguments, and documentation for each pallet event. -- **Constants metadata**: Provides metadata generated by the `#[pallet::constant]` macro, including the name, type, and hex-encoded value of the constant. -- **Error metadata**: Provides metadata generated by the `#[pallet::error]` macro, including the name and documentation for each pallet error. - -!!!tip - Type identifiers change from time to time, so you should avoid relying on specific type identifiers in your applications. - -### Extrinsic - -The runtime generates extrinsic metadata and provides useful information about transaction format. When decoded, the metadata contains the transaction version and the list of signed extensions. - -For example: - -```json -{ - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [ - { - "identifier": "CheckNonZeroSender", - "ty": 132, - "additional_signed": 41 - }, - { - "identifier": "CheckSpecVersion", - "ty": 133, - "additional_signed": 4 - }, - { - "identifier": "CheckTxVersion", - "ty": 134, - "additional_signed": 4 - }, - { - "identifier": "CheckGenesis", - "ty": 135, - "additional_signed": 11 - }, - { - "identifier": "CheckMortality", - "ty": 136, - "additional_signed": 11 - }, - { - "identifier": "CheckNonce", - "ty": 138, - "additional_signed": 41 - }, - { - "identifier": "CheckWeight", - "ty": 139, - "additional_signed": 41 - }, - { - "identifier": "ChargeTransactionPayment", - "ty": 140, - "additional_signed": 41 - } - ] - }, - "ty": 141 -} - -``` - -The type system is [composite](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank}, meaning each type identifier contains a reference to a specific type or to another type identifier that provides information about the associated primitive types. - -For example, you can encode the `BitVec` type, but to decode it properly, you must know the types used for the `Order` and `Store` types. To find type information for `Order` and `Store`, you can use the path in the decoded JSON to locate their type identifiers. - -## Included RPC APIs - -A standard node comes with the following APIs to interact with a node: - -- **[`AuthorApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/author/trait.AuthorApiServer.html){target=\_blank}**: Make calls into a full node, including authoring extrinsics and verifying session keys. -- **[`ChainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/chain/trait.ChainApiServer.html){target=\_blank}**: Retrieve block header and finality information. -- **[`OffchainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/offchain/trait.OffchainApiServer.html){target=\_blank}**: Make RPC calls for off-chain workers. -- **[`StateApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/state/trait.StateApiServer.html){target=\_blank}**: Query information about on-chain state such as runtime version, storage items, and proofs. -- **[`SystemApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/system/trait.SystemApiServer.html){target=\_blank}**: Retrieve information about network state, such as connected peers and node roles. - -## Additional Resources - -The following tools can help you locate and decode metadata: - -- [Subxt Explorer](https://paritytech.github.io/subxt-explorer/#/){target=\_blank} -- [Metadata Portal 🌗](https://github.com/paritytech/metadata-portal){target=\_blank} -- [De[code] Sub[strate]](https://github.com/paritytech/desub){target=\_blank} - - --- Page Title: Contract Deployment @@ -1019,280 +585,6 @@ Both REVM and PolkaVM deployments may show significant differences between gas e Both backends support contract deployment effectively, with REVM offering drop-in Ethereum compatibility and PolkaVM providing a more structured two-step approach. For the majority of use cases—deploying standard contracts like tokens or applications—both backends work seamlessly. Advanced patterns like factory contracts may require adjustment for PolkaVM, but these adaptations are straightforward with proper planning. ---- - -Page Title: Cryptography - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/cryptography/ -- Summary: A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. - -# Cryptography - -## Introduction - -Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem. - -## Hash Functions - -Hash functions are fundamental to blockchain technology, creating a unique digital fingerprint for any piece of data, including simple text, images, or any other form of file. They map input data of any size to a fixed-size output (typically 32 bytes) using complex mathematical operations. Hashing is used to verify data integrity, create digital signatures, and provide a secure way to store passwords. This form of mapping is known as the ["pigeonhole principle,"](https://en.wikipedia.org/wiki/Pigeonhole_principle){target=\_blank} it is primarily implemented to efficiently and verifiably identify data from large sets. - -### Key Properties of Hash Functions - -- **Deterministic**: The same input always produces the same output. -- **Quick computation**: It's easy to calculate the hash value for any given input. -- **Pre-image resistance**: It's infeasible to generate the input data from its hash. -- **Small changes in input yield large changes in output**: Known as the ["avalanche effect"](https://en.wikipedia.org/wiki/Avalanche_effect){target=\_blank}. -- **Collision resistance**: The probabilities are extremely low to find two different inputs with the same hash. - -### Blake2 - -The Polkadot SDK utilizes Blake2, a state-of-the-art hashing method that offers: - -- Equal or greater security compared to [SHA-2](https://en.wikipedia.org/wiki/SHA-2){target=\_blank}. -- Significantly faster performance than other algorithms. - -These properties make Blake2 ideal for blockchain systems, reducing sync times for new nodes and lowering the resources required for validation. For detailed technical specifications about Blake2, see the [official Blake2 paper](https://www.blake2.net/blake2.pdf){target=\_blank}. - -## Types of Cryptography - -There are two different ways that cryptographic algorithms are implemented: symmetric cryptography and asymmetric cryptography. - -### Symmetric Cryptography - -Symmetric encryption is a branch of cryptography that isn't based on one-way functions, unlike asymmetric cryptography. It uses the same cryptographic key to encrypt plain text and decrypt the resulting ciphertext. - -Symmetric cryptography is a type of encryption that has been used throughout history, such as the Enigma Cipher and the Caesar Cipher. It is still widely used today and can be found in Web2 and Web3 applications alike. There is only one single key, and a recipient must also have access to it to access the contained information. - -#### Advantages {: #symmetric-advantages } - -- Fast and efficient for large amounts of data. -- Requires less computational power. - -#### Disadvantages {: #symmetric-disadvantages } - -- Key distribution can be challenging. -- Scalability issues in systems with many users. - -### Asymmetric Cryptography - -Asymmetric encryption is a type of cryptography that uses two different keys, known as a keypair: a public key, used to encrypt plain text, and a private counterpart, used to decrypt the ciphertext. - -The public key encrypts a fixed-length message that can only be decrypted with the recipient's private key and, sometimes, a set password. The public key can be used to cryptographically verify that the corresponding private key was used to create a piece of data without compromising the private key, such as with digital signatures. This has obvious implications for identity, ownership, and properties and is used in many different protocols across Web2 and Web3. - -#### Advantages {: #asymmetric-advantages } - -- Solves the key distribution problem. -- Enables digital signatures and secure key exchange. - -#### Disadvantages {: #asymmetric-disadvantages } - -- Slower than symmetric encryption. -- Requires more computational resources. - -### Trade-offs and Compromises - -Symmetric cryptography is faster and requires fewer bits in the key to achieve the same level of security that asymmetric cryptography provides. However, it requires a shared secret before communication can occur, which poses issues to its integrity and a potential compromise point. On the other hand, asymmetric cryptography doesn't require the secret to be shared ahead of time, allowing for far better end-user security. - -Hybrid symmetric and asymmetric cryptography is often used to overcome the engineering issues of asymmetric cryptography, as it is slower and requires more bits in the key to achieve the same level of security. It encrypts a key and then uses the comparatively lightweight symmetric cipher to do the "heavy lifting" with the message. - -## Digital Signatures - -Digital signatures are a way of verifying the authenticity of a document or message using asymmetric keypairs. They are used to ensure that a sender or signer's document or message hasn't been tampered with in transit, and for recipients to verify that the data is accurate and from the expected sender. - -Signing digital signatures only requires a low-level understanding of mathematics and cryptography. For a conceptual example -- when signing a check, it is expected that it cannot be cashed multiple times. This isn't a feature of the signature system but rather the check serialization system. The bank will check that the serial number on the check hasn't already been used. Digital signatures essentially combine these two concepts, allowing the signature to provide the serialization via a unique cryptographic fingerprint that cannot be reproduced. - -Unlike pen-and-paper signatures, knowledge of a digital signature cannot be used to create other signatures. Digital signatures are often used in bureaucratic processes, as they are more secure than simply scanning in a signature and pasting it onto a document. - -Polkadot SDK provides multiple different cryptographic schemes and is generic so that it can support anything that implements the [`Pair` trait](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Pair.html){target=\_blank}. - -### Example of Creating a Digital Signature - -The process of creating and verifying a digital signature involves several steps: - -1. The sender creates a hash of the message. -2. The hash is encrypted using the sender's private key, creating the signature. -3. The message and signature are sent to the recipient. -4. The recipient decrypts the signature using the sender's public key. -5. The recipient hashes the received message and compares it to the decrypted hash. - -If the hashes match, the signature is valid, confirming the message's integrity and the sender's identity. - -## Elliptic Curve - -Blockchain technology requires the ability to have multiple keys creating a signature for block proposal and validation. To this end, Elliptic Curve Digital Signature Algorithm (ECDSA) and Schnorr signatures are two of the most commonly used methods. While ECDSA is a far simpler implementation, Schnorr signatures are more efficient when it comes to multi-signatures. - -Schnorr signatures bring some noticeable features over the ECDSA/EdDSA schemes: - -- It is better for hierarchical deterministic key derivations. -- It allows for native multi-signature through [signature aggregation](https://bitcoincore.org/en/2017/03/23/schnorr-signature-aggregation/){target=\_blank}. -- It is generally more resistant to misuse. - -One sacrifice that is made when using Schnorr signatures over ECDSA is that both require 64 bytes, but only ECDSA signatures communicate their public key. - -### Various Implementations - -- **[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm){target=\_blank}**: Polkadot SDK provides an ECDSA signature scheme using the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1){target=\_blank} curve. This is the same cryptographic algorithm used to secure [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin){target=\_blank} and [Ethereum](https://en.wikipedia.org/wiki/Ethereum){target=\_blank}. - -- **[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519){target=\_blank}**: An EdDSA signature scheme using [Curve25519](https://en.wikipedia.org/wiki/Curve25519){target=\_blank}. It is carefully engineered at several levels of design and implementation to achieve very high speeds without compromising security. - -- **[SR25519](https://research.web3.foundation/Polkadot/security/keys/accounts-more){target=\_blank}**: Based on the same underlying curve as Ed25519. However, it uses Schnorr signatures instead of the EdDSA scheme. - - ---- - -Page Title: Data Encoding - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/data-encoding/ -- Summary: SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. - -# Data Encoding - -## Introduction - -The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data. - -The SCALE codec enables communication between the runtime and the outer node. This mechanism is designed for high-performance, copy-free data encoding and decoding in resource-constrained environments like the Polkadot SDK [Wasm runtime](/develop/parachains/deployment/build-deterministic-runtime/#introduction){target=\_blank}. - -It is not self-describing, meaning the decoding context must fully know the encoded data types. - -Parity's libraries utilize the [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} crate (a Rust implementation of the SCALE codec) to handle encoding and decoding for interactions between RPCs and the runtime. - -The `codec` mechanism is ideal for Polkadot SDK-based chains because: - -- It is lightweight compared to generic serialization frameworks like [`serde`](https://serde.rs/){target=\_blank}, which add unnecessary bulk to binaries. -- It doesn’t rely on Rust’s `libstd`, making it compatible with `no_std` environments like Wasm runtime. -- It integrates seamlessly with Rust, allowing easy derivation of encoding and decoding logic for new types using `#[derive(Encode, Decode)]`. - -Defining a custom encoding scheme in the Polkadot SDK-based chains, rather than using an existing Rust codec library, is crucial for enabling cross-platform and multi-language support. - -## SCALE Codec - -The codec is implemented using the following traits: - -- [`Encode`](#encode) -- [`Decode`](#decode) -- [`CompactAs`](#compactas) -- [`HasCompact`](#hascompact) -- [`EncodeLike`](#encodelike) - -### Encode - -The [`Encode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Encode.html){target=\_blank} trait handles data encoding into SCALE format and includes the following key functions: - -- **`size_hint(&self) -> usize`**: Estimates the number of bytes required for encoding to prevent multiple memory allocations. This should be inexpensive and avoid complex operations. Optional if the size isn’t known. -- **`encode_to(&self, dest: &mut T)`**: Encodes the data, appending it to a destination buffer. -- **`encode(&self) -> Vec`**: Encodes the data and returns it as a byte vector. -- **`using_encoded R>(&self, f: F) -> R`**: Encodes the data and passes it to a closure, returning the result. -- **`encoded_size(&self) -> usize`**: Calculates the encoded size. Should be used when the encoded data isn’t required. - -!!!tip - For best performance, value types should override `using_encoded`, and allocating types should override `encode_to`. It's recommended to implement `size_hint` for all types where possible. - -### Decode - -The [`Decode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Decode.html){target=\_blank} trait handles decoding SCALE-encoded data back into the appropriate types: - -- **`fn decode(value: &mut I) -> Result`**: Decodes data from the SCALE format, returning an error if decoding fails. - -### CompactAs - -The [`CompactAs`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.CompactAs.html){target=\_blank} trait wraps custom types for compact encoding: - -- **`encode_as(&self) -> &Self::As`**: Encodes the type as a compact type. -- **`decode_from(_: Self::As) -> Result`**: decodes from a compact encoded type. - -### HasCompact - -The [`HasCompact`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.HasCompact.html){target=\_blank} trait indicates a type supports compact encoding. - -### EncodeLike - -The [`EncodeLike`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.EncodeLike.html){target=\_blank} trait is used to ensure multiple types that encode similarly are accepted by the same function. When using `derive`, it is automatically implemented. - -### Data Types - -The table below outlines how the Rust implementation of the Parity SCALE codec encodes different data types. - -| Type | Description | Example SCALE Decoded Value | SCALE Encoded Value | -|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| -| Boolean | Boolean values are encoded using the least significant bit of a single byte. | `false` / `true` | `0x00` / `0x01` | -| Compact/general integers | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2^536) and is more efficient at encoding most values than the fixed-width version. | `unsigned integer 0` / `unsigned integer 1` / `unsigned integer 42` / `unsigned integer 69` / `unsigned integer 65535` / `BigInt(100000000000000)` | `0x00` / `0x04` / `0xa8` / `0x1501` / `0xfeff0300` / `0x0b00407a10f35a` | -| Enumerations (tagged-unions) | A fixed number of variants, each mutually exclusive and potentially implying a further value or series of values. Encoded as the first byte identifying the index of the variant that the value is. Any further bytes are used to encode any data that the variant implies. Thus, no more than 256 variants are supported. | `Int(42)` and `Bool(true)` where `enum IntOrBool { Int(u8), Bool(bool) }` | `0x002a` and `0x0101` | -| Fixed-width integers | Basic integers are encoded using a fixed-width little-endian (LE) format. | `signed 8-bit integer 69` / `unsigned 16-bit integer 42` / `unsigned 32-bit integer 16777215` | `0x45` / `0x2a00` / `0xffffff00` | -| Options | One or zero values of a particular type. | `Some` / `None` | `0x01` followed by the encoded value / `0x00` | -| Results | Results are commonly used enumerations which indicate whether certain operations were successful or unsuccessful. | `Ok(42)` / `Err(false)` | `0x002a` / `0x0100` | -| Strings | Strings are Vectors of bytes (Vec) containing a valid UTF8 sequence. | | | -| Structs | For structures, the values are named, but that is irrelevant for the encoding (names are ignored - only order matters). | `SortedVecAsc::from([3, 5, 2, 8])` | `[3, 2, 5, 8] ` | -| Tuples | A fixed-size series of values, each with a possibly different but predetermined and fixed type. This is simply the concatenation of each encoded value. | Tuple of compact unsigned integer and boolean: `(3, false)` | `0x0c00` | -| Vectors (lists, series, sets) | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. | Vector of unsigned `16`-bit integers: `[4, 8, 15, 16, 23, 42]` | `0x18040008000f00100017002a00` | - -## Encode and Decode Rust Trait Implementations - -Here's how the `Encode` and `Decode` traits are implemented: - - -```rust -use parity_scale_codec::{Encode, Decode}; - -[derive(Debug, PartialEq, Encode, Decode)] -enum EnumType { - #[codec(index = 15)] - A, - B(u32, u64), - C { - a: u32, - b: u64, - }, -} - -let a = EnumType::A; -let b = EnumType::B(1, 2); -let c = EnumType::C { a: 1, b: 2 }; - -a.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x0f"); -}); - -b.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -c.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -let mut da: &[u8] = b"\x0f"; -assert_eq!(EnumType::decode(&mut da).ok(), Some(a)); - -let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut db).ok(), Some(b)); - -let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut dc).ok(), Some(c)); - -let mut dz: &[u8] = &[0]; -assert_eq!(EnumType::decode(&mut dz).ok(), None); -``` - -## SCALE Codec Libraries - -Several SCALE codec implementations are available in various languages. Here's a list of them: - -- **AssemblyScript**: [`LimeChain/as-scale-codec`](https://github.com/LimeChain/as-scale-codec){target=\_blank} -- **C**: [`MatthewDarnell/cScale`](https://github.com/MatthewDarnell/cScale){target=\_blank} -- **C++**: [`qdrvm/scale-codec-cpp`](https://github.com/qdrvm/scale-codec-cpp){target=\_blank} -- **JavaScript**: [`polkadot-js/api`](https://github.com/polkadot-js/api){target=\_blank} -- **Dart**: [`leonardocustodio/polkadart`](https://github.com/leonardocustodio/polkadart){target=\_blank} -- **Haskell**: [`airalab/hs-web3`](https://github.com/airalab/hs-web3/tree/master/packages/scale){target=\_blank} -- **Golang**: [`itering/scale.go`](https://github.com/itering/scale.go){target=\_blank} -- **Java**: [`splix/polkaj`](https://github.com/splix/polkaj){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **Ruby**: [` wuminzhe/scale_rb`](https://github.com/wuminzhe/scale_rb){target=\_blank} -- **TypeScript**: [`parity-scale-codec-ts`](https://github.com/tjjfvi/subshape){target=\_blank}, [`scale-ts`](https://github.com/unstoppablejs/unstoppablejs/tree/main/packages/scale-ts#scale-ts){target=\_blank}, [`soramitsu/scale-codec-js-library`](https://github.com/soramitsu/scale-codec-js-library){target=\_blank}, [`subsquid/scale-codec`](https://github.com/subsquid/squid-sdk/tree/master/substrate/scale-codec){target=\_blank} - - --- Page Title: Deploy an ERC-20 to Polkadot Hub @@ -3100,370 +2392,130 @@ From here, follow the quick starts to get connected, iterate locally with your p --- -Page Title: Glossary +Page Title: Get Started with XCM -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md -- Canonical (HTML): https://docs.polkadot.com/reference/glossary/ -- Summary: Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ +- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. -# Glossary +# Get Started with XCM -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. +## Introduction -Additional glossaries from around the ecosystem you might find helpful: - -- [Polkadot Wiki Glossary](https://wiki.polkadot.com/general/glossary){target=\_blank} -- [Polkadot SDK Glossary](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/glossary/index.html){target=\_blank} - -## Authority - -The role in a blockchain that can participate in consensus mechanisms. - -- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final. -- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author). - -Authority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol. - -## Authority Round (Aura) - -A deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol. - -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. - -## Blind Assignment of Blockchain Extension (BABE) - -A [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block. - -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. - -## Block Author - -The node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_. - -## Byzantine Fault Tolerance (BFT) - -The ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack. - -### Byzantine Failure - -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. - -### Practical Byzantine Fault Tolerance (pBFT) - -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. - -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. - -### Preimage - -A preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\_blank}, the output, the hash, cannot be used to reveal the input, the preimage. - -## Call - -In the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object. - -## Chain Specification - -A chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains. - -## Collator - -An [author](#block-author) of a [parachain](#parachain) network. -They aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus). - -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. - -## Collective - -Most often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network. - -## Consensus +Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. -Consensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship. +With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. -See also [hybrid consensus](#hybrid-consensus). +## Messaging Format -## Consensus Algorithm +XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. -Ensures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft). +XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. -Consensus algorithms are generally concerned with ensuring two properties: +## The Four Principles of XCM -- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. -- **Liveness**: Indicating the ability of the chain to keep progressing. +XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: -## Consensus Engine +- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. +- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. +- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. +- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. -The node subsystem responsible for consensus tasks. +These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. -For detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} blog series. +## The XCM Tech Stack -See also [hybrid consensus](#hybrid-consensus). +![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) -## Coretime +The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. +## Core Functionalities of XCM -On-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety. +XCM enhances cross-consensus communication by introducing several powerful features: -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank}. +- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. +- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. +- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. -## Development Phrase +The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. +## XCM Example -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: +The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). +```rust +let message = Xcm(vec![ + WithdrawAsset((Here, amount).into()), + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } +]); ``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk -``` - -Many tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`. - -## Digest - -An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: - -- [Light clients](#light-client) for chain synchronization. -- Consensus engines for block verification. -- The runtime itself, in the case of pre-runtime digests. - -## Dispatchable - -Function objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations. - -## Events - -A means of recording that some particular [state](#state) transition happened. - -In the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization. - -## Executor - -A means of executing a function call in a given [runtime](#runtime) with a set of dependencies. -There are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_. - -- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes. - -- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain. - -## Existential Deposit - -The minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. - -If an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\_blank} to drop its references to that account. - -If the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\_blank}. - -## Extrinsic - -A general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder. - -It is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). - -For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. - -## Fork Choice Rule/Strategy - -A fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\_blank}, in which the chain with the most blocks is selected. - -## FRAME (Framework for Runtime Aggregation of Modularized Entities) - -Enables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes. - -[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank} - -## Full Node - -A node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization. - -## Genesis Configuration - -A mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file. - -## GRANDPA - -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. - -The [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\_blank}. - -## Header - -A structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization. - -## Hybrid Consensus - -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. - -Hybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa). - -## Inherent Transactions - -A special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block. - -Only the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified. - -## JSON-RPC - -A stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON. - -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. - -## Keystore - -A subsystem for managing keys for the purpose of producing new blocks. - -## Kusama - -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. - -Kusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\_blank} network and is referred to as [Polkadot's "wild cousin."](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\_blank}. - -As a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation. - -## libp2p - -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). - -Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. -## Light Client - -A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. - -A light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\_blank} server, enabling blockchain users to interact with the network. - -## Metadata - -Data that provides information about one or more aspects of a system. -The metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system. - -## Nominated Proof of Stake (NPoS) - -A method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes. - -## Oracle - -An entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services. - -## Origin - -A [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\_blank}. - -## Pallet - -A module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime). -Pallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item). - -## Parachain - -A parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_. -You can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\_blank}. - -## Paseo - -Paseo TestNet provisions testing on Polkadot's "production" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing. - -## Polkadot - -The [Polkadot network](https://polkadot.com/){target=\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain). - -## Polkadot Cloud - -Polkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance. - -## Polkadot Hub - -Polkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3. - -## PolkaVM - -PolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution. - -## Relay Chain - -Relay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another. - -## Rococo - -A [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead. - -## Runtime - -The runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function. - -## Slot - -A fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block. - -## Sovereign Account - -The unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem. - -The sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier. - -## SS58 Address Format - -A public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain - -The [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks - -## State Transition Function (STF) - -The logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime). - -## Storage Item - -[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime). -Learn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\_blank} reference document in the Polkadot SDK. - -## Substrate - -A flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\_blank}. - -## Transaction - -An [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}. - -## Transaction Era - -A definable period expressed as a range of block numbers during which a transaction can be included in a block. -Transaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero. - -## Trie (Patricia Merkle Tree) +The message consists of three instructions described as follows: -A data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set. +- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. -In Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays. + ```rust + WithdrawAsset((Here, amount).into()), + ``` -## Validator + - **`Here`**: The native parachain token. + - **`amount`**: The number of tokens that are transferred. -A validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance. + The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. -## WebAssembly (Wasm) +- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. + ```rust + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + ``` -[Wasm](https://webassembly.org/){target=\_blank} can be compiled from many languages, including -the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state. + - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. + - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. -## Weight +- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. -A convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block. -Polkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware. + ```rust + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } + ``` -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: + - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. + +This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. -- Block construction -- Network propagation -- Import and verification +## Overview -By defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements. +XCM revolutionizes cross-chain communication by enabling use cases such as: -## Westend +- Token transfers between blockchains. +- Asset locking for cross-chain smart contract interactions. +- Remote execution of functions on other blockchains. -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. +These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. --- @@ -3890,258 +2942,60 @@ To stop the node, press `Control-C` in the terminal. --- -Page Title: Interoperability +Page Title: JSON-RPC APIs -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/interoperability/ -- Summary: Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ +- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. -# Interoperability +# JSON-RPC APIs +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions. - -Polkadot’s design ensures that blockchains can transcend their individual limitations by working together as part of a unified system. This cooperative architecture is what sets Polkadot apart in the blockchain landscape. - -## Why Interoperability Matters - -The blockchain ecosystem is inherently fragmented. Different blockchains excel in specialized domains such as finance, gaming, or supply chain management, but these chains function in isolation without interoperability. This lack of connectivity stifles the broader utility of blockchain technology. - -Interoperability solves this problem by enabling blockchains to: - -- **Collaborate across networks**: Chains can interact to share assets, functionality, and data, creating synergies that amplify their individual strengths. -- **Achieve greater scalability**: Specialized chains can offload tasks to others, optimizing performance and resource utilization. -- **Expand use-case potential**: Cross-chain applications can leverage features from multiple blockchains, unlocking novel user experiences and solutions. - -In the Polkadot ecosystem, interoperability transforms a collection of isolated chains into a cohesive, efficient network, pushing the boundaries of what blockchains can achieve together. +Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. -## Key Mechanisms for Interoperability +This guide uses the Polkadot Hub TestNet endpoint: -At the core of Polkadot's cross-chain collaboration are foundational technologies designed to break down barriers between networks. These mechanisms empower blockchains to communicate, share resources, and operate as a cohesive ecosystem. +```text +https://testnet-passet-hub-eth-rpc.polkadot.io +``` -### Cross-Consensus Messaging (XCM): The Backbone of Communication +## Available Methods -Polkadot's Cross-Consensus Messaging (XCM) is the standard framework for interaction between parachains, relay chains, and, eventually, external blockchains. XCM provides a trustless, secure messaging format for exchanging assets, sharing data, and executing cross-chain operations. +### eth_accounts -Through XCM, decentralized applications can: +Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. -- Transfer tokens and other assets across chains. -- Coordinate complex workflows that span multiple blockchains. -- Enable seamless user experiences where underlying blockchain differences are invisible. -- XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem. +**Parameters**: -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. +None. -### Bridges: Connecting External Networks +**Example**: -While XCM enables interoperability within the Polkadot ecosystem, bridges extend this functionality to external blockchains such as Ethereum and Bitcoin. By connecting these networks, bridges allow Polkadot-based chains to access external liquidity, additional functionalities, and broader user bases. +```bash title="eth_accounts" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_accounts", + "params":[], + "id":1 +}' +``` -With bridges, developers and users gain the ability to: +--- -- Integrate external assets into Polkadot-based applications. -- Combine the strengths of Polkadot’s scalability with the liquidity of other networks. -- Facilitate accurate multi-chain applications that transcend ecosystem boundaries. +### eth_blockNumber -For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. +Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. -## The Polkadot Advantage +**Parameters**: -Polkadot was purpose-built for interoperability. Unlike networks that add interoperability as an afterthought, Polkadot integrates it as a fundamental design principle. This approach offers several distinct advantages: +None. -- **Developer empowerment**: Polkadot’s interoperability tools allow developers to build applications that leverage multiple chains’ capabilities without added complexity. -- **Enhanced ecosystem collaboration**: Chains in Polkadot can focus on their unique strengths while contributing to the ecosystem’s overall growth. -- **Future-proofing blockchain**: By enabling seamless communication, Polkadot ensures its ecosystem can adapt to evolving demands and technologies. - -## Looking Ahead - -Polkadot’s vision of interoperability extends beyond technical functionality, representing a shift towards a more collaborative blockchain landscape. By enabling chains to work together, Polkadot fosters innovation, efficiency, and accessibility, paving the way for a decentralized future where blockchains are not isolated competitors but interconnected collaborators. - - ---- - -Page Title: Introduction to XCM - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ -- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. - -# Introduction to XCM - -## Introduction - -Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. - -With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. - -## Messaging Format - -XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. - -XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. - -## The Four Principles of XCM - -XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: - -- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. -- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. -- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. -- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. - -These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. - -## The XCM Tech Stack - -![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) - -The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. - -## Core Functionalities of XCM - -XCM enhances cross-consensus communication by introducing several powerful features: - -- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. -- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. -- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. - -The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. - -## XCM Example - -The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). - -```rust -let message = Xcm(vec![ - WithdrawAsset((Here, amount).into()), - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } -]); -``` - -The message consists of three instructions described as follows: - -- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. - - ```rust - WithdrawAsset((Here, amount).into()), - ``` - - - **`Here`**: The native parachain token. - - **`amount`**: The number of tokens that are transferred. - - The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. - -- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. - - ```rust - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - ``` - - - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. - - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. - -- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. - - ```rust - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } - ``` - - - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. - -This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - -## Overview - -XCM revolutionizes cross-chain communication by enabling use cases such as: - -- Token transfers between blockchains. -- Asset locking for cross-chain smart contract interactions. -- Remote execution of functions on other blockchains. - -These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - - ---- - -Page Title: JSON-RPC APIs - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ -- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. - -# JSON-RPC APIs - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. - -This guide uses the Polkadot Hub TestNet endpoint: - -```text -https://testnet-passet-hub-eth-rpc.polkadot.io -``` - -## Available Methods - -### eth_accounts - -Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_accounts" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_accounts", - "params":[], - "id":1 -}' -``` - ---- - -### eth_blockNumber - -Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. - -**Parameters**: - -None. - -**Example**: +**Example**: ```bash title="eth_blockNumber" curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ @@ -4959,306 +3813,108 @@ If an error occurs, the response will include an error object: --- -Page Title: Networks +Page Title: Offenses and Slashes -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/networks/ -- Summary: Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes.md +- Canonical (HTML): https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/offenses-and-slashes/ +- Summary: Learn about how Polkadot discourages validator misconduct via an offenses and slashing system, including details on offenses and their consequences. -# Networks +# Offenses and Slashes ## Introduction -The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's various networks and explain how they fit into the development workflow. +In Polkadot's Nominated Proof of Stake (NPoS) system, validator misconduct is deterred through a combination of slashing, disabling, and reputation penalties. Validators and nominators who stake tokens face consequences for validator misbehavior, which range from token slashes to restrictions on network participation. -## Network Overview +This page outlines the types of offenses recognized by Polkadot, including block equivocations and invalid votes, as well as the corresponding penalties. While some parachains may implement additional custom slashing mechanisms, this guide focuses on the offenses tied to staking within the Polkadot ecosystem. -Polkadot's development process is structured to ensure new features and upgrades are rigorously tested before being deployed on live production networks. The progression follows a well-defined path, starting from local environments and advancing through TestNets, ultimately reaching the Polkadot MainNet. The diagram below outlines the typical progression of the Polkadot development cycle: +## Offenses -``` mermaid -flowchart LR - id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] - id1[Local] --> id3[Paseo] --> id5[Polkadot] -``` +Polkadot is a public permissionless network. As such, it has a mechanism to disincentivize offenses and incentivize good behavior. You can review the [parachain protocol](https://wiki.polkadot.com/learn/learn-parachains-protocol/#parachain-protocol){target=\_blank} to understand better the terminology used to describe offenses. Polkadot validator offenses fall into two categories: invalid votes and equivocations. -This flow ensures developers can thoroughly test and iterate without risking real tokens or affecting production networks. Testing tools like [Chopsticks](#chopsticks) and various TestNets make it easier to experiment safely before releasing to production. +### Invalid Votes -A typical journey through the Polkadot core protocol development process might look like this: +A validator will be penalized for inappropriate voting activity during the block inclusion and approval processes. The invalid voting related offenses are as follows: -1. **Local development node**: Development starts in a local environment, where developers can create, test, and iterate on upgrades or new features using a local development node. This stage allows rapid experimentation in an isolated setup without any external dependencies. +- **Backing an invalid block**: A para-validator backs an invalid block for inclusion in a fork of the relay chain. +- **`ForInvalid` vote**: When acting as a secondary checker, the validator votes in favor of an invalid block. +- **`AgainstValid` vote**: When acting as a secondary checker, the validator votes against a valid block. This type of vote wastes network resources required to resolve the disparate votes and resulting dispute. -2. **Westend**: After testing locally, upgrades are deployed to [Westend](#westend), Polkadot's primary TestNet. Westend simulates real-world conditions without using real tokens, making it the ideal place for rigorous feature testing before moving on to production networks. +### Equivocations -3. **Kusama**: Once features have passed extensive testing on Westend, they move to Kusama, Polkadot's experimental and fast-moving "canary" network. Kusama operates as a high-fidelity testing ground with actual economic incentives, giving developers insights into how their features will perform in a real-world environment. +Equivocation occurs when a validator produces statements that conflict with each other when producing blocks or voting. Unintentional equivocations usually occur when duplicate signing keys reside on the validator host. If keys are never duplicated, the probability of an honest equivocation slash decreases to near zero. The equivocation related offenses are as follows: -4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network. +- **Equivocation**: The validator produces two or more of the same block or vote. + - **GRANDPA and BEEFY equivocation**: The validator signs two or more votes in the same round on different chains. + - **BABE equivocation**: The validator produces two or more blocks on the relay chain in the same time slot. +- **Double seconded equivocation**: The validator attempts to second, or back, more than one block in the same round. +- **Seconded and valid equivocation**: The validator seconds, or backs, a block and then attempts to hide their role as the responsible backer by later placing a standard validation vote. - In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. +## Penalties -5. **Paseo**: For parachain and dApp developers, Paseo serves as a community-run TestNet that mirrors Polkadot's runtime. Like Westend for core protocol development, Paseo provides a testing ground for parachain development without affecting live networks. +On Polkadot, offenses to the network incur different penalties depending on severity. There are three main penalties: slashing, disabling, and reputation changes. -!!!note - The Rococo TestNet deprecation date was October 14, 2024. Teams should use Westend for Polkadot protocol and feature testing and Paseo for chain development-related testing. +### Slashing -## Polkadot Development Networks +Validators engaging in bad actor behavior in the network may be subject to slashing if they commit a qualifying offense. When a validator is slashed, they and their nominators lose a percentage of their staked DOT or KSM, from as little as 0.01% up to 100% based on the severity of the offense. Nominators are evaluated for slashing against their active validations at any given time. Validator nodes are evaluated as discrete entities, meaning an operator can't attempt to mitigate the offense on another node they operate in order to avoid a slash. -Development and testing are crucial to building robust dApps and parachains and performing network upgrades within the Polkadot ecosystem. To achieve this, developers can leverage various networks and tools that provide a risk-free environment for experimentation and validation before deploying features to live networks. These networks help avoid the costs and risks associated with real tokens, enabling testing for functionalities like governance, cross-chain messaging, and runtime upgrades. +Any slashed DOT or KSM will be added to the [Treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} rather than burned or distributed as rewards. Moving slashed funds to the Treasury allows tokens to be quickly moved away from malicious validators while maintaining the ability to revert faulty slashes when needed. -## Kusama Network +A nominator with a very large bond may nominate several validators in a single era. In this case, a slash is proportionate to the amount staked to the offending validator. Stake allocation and validator activation is controlled by the [Phragmén algorithm](https://wiki.polkadot.com/learn/learn-phragmen/#algorithm){target=\_blank}. -Kusama is the experimental version of Polkadot, designed for developers who want to move quickly and test their applications in a real-world environment with economic incentives. Kusama serves as a production-grade testing ground where developers can deploy features and upgrades with the pressure of game theory and economics in mind. It mirrors Polkadot but operates as a more flexible space for innovation. +A validator slash creates an `unapplied` state transition. You can view pending slashes on [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc.polkadot.io#/staking/slashes){target=\_blank}. The UI will display the slash per validator, the affected nominators, and the slash amounts. The unapplied state includes a 27-day grace period during which a governance proposal can be made to reverse the slash. Once this grace period expires, the slash is applied. -The native token for Kusama is KSM. For more information about KSM, visit the [Native Assets](https://wiki.polkadot.com/kusama/kusama-getting-started/){target=\_blank} page. +#### Equivocation Slash -## Test Networks +The Web3 Foundation's [Slashing mechanisms](https://research.web3.foundation/Polkadot/security/slashing/amounts){target=\_blank} page provides guidelines for evaluating the security threat level of different offenses and determining penalties proportionate to the threat level of the offense. Offenses requiring coordination between validators or extensive computational costs to the system will typically call for harsher penalties than those more likely to be unintentional than malicious. A description of potential offenses for each threat level and the corresponding penalties is as follows: -The following test networks provide controlled environments for testing upgrades and new features. TestNet tokens are available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}. +- **Level 1**: Honest misconduct such as isolated cases of unresponsiveness. + - **Penalty**: Validator can be kicked out or slashed up to 0.1% of stake in the validator slot. +- **Level 2**: Misconduct that can occur honestly but is a sign of bad practices. Examples include repeated cases of unresponsiveness and isolated cases of equivocation. + - **Penalty**: Slash of up to 1% of stake in the validator slot. +- **Level 3**: Misconduct that is likely intentional but of limited effect on the performance or security of the network. This level will typically include signs of coordination between validators. Examples include repeated cases of equivocation or isolated cases of unjustified voting on GRANDPA. + - **Penalty**: Reduction in networking reputation metrics, slash of up to 10% of stake in the validator slot. +- **Level 4**: Misconduct that poses severe security or monetary risk to the system or mass collusion. Examples include signs of extensive coordination, creating a serious security risk to the system, or forcing the system to use extensive resources to counter the misconduct. + - **Penalty**: Slash of up to 100% of stake in the validator slot. -### Westend +See the next section to understand how slash amounts for equivocations are calculated. If you want to know more details about slashing, please look at the research page on [Slashing mechanisms](https://research.web3.foundation/Polkadot/security/slashing/amounts){target=\_blank}. -Westend is Polkadot's primary permanent TestNet. Unlike temporary test networks, Westend is not reset to the genesis block, making it an ongoing environment for testing Polkadot core features. Managed by Parity Technologies, Westend ensures that developers can test features in a real-world simulation without using actual tokens. +#### Slash Calculation for Equivocation -The native token for Westend is WND. More details about WND can be found on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_2){target=\_blank} page. +The slashing penalty for GRANDPA, BABE, and BEEFY equivocations is calculated using the formula below, where `x` represents the number of offenders and `n` is the total number of validators in the active set: -### Paseo +```text +min((3 * x / n )^2, 1) +``` -[Paseo](https://github.com/paseo-network){target=\_blank} is a community-managed TestNet designed for parachain and dApp developers. It mirrors Polkadot's runtime and is maintained by Polkadot community members. Paseo provides a dedicated space for parachain developers to test their applications in a Polkadot-like environment without the risks associated with live networks. +The following scenarios demonstrate how this formula means slash percentages can increase exponentially based on the number of offenders involved compared to the size of the validator pool: -The native token for Paseo is PAS. Additional information on PAS is available on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_1){target=\_blank} page. +- **Minor offense**: Assume 1 validator out of a 100 validator active set equivocates in a slot. A single validator committing an isolated offense is most likely a mistake rather than malicious attack on the network. This offense results in a 0.09% slash to the stake in the validator slot. -## Local Test Networks + ``` mermaid + flowchart LR + N["Total Validators = 100"] + X["Offenders = 1"] + F["min((3 * 1 / 100)^2, 1) = 0.0009"] + G["0.09% slash of stake"] -Local test networks are an essential part of the development cycle for blockchain developers using the Polkadot SDK. They allow for fast, iterative testing in controlled, private environments without connecting to public TestNets. Developers can quickly spin up local instances to experiment, debug, and validate their code before deploying to larger TestNets like Westend or Paseo. Two key tools for local network testing are Zombienet and Chopsticks. + N --> F + X --> F + F --> G + ``` -### Zombienet +- **Moderate offense**: Assume 5 validators out a 100 validator active set equivocate in a slot. This is a slightly more serious event as there may be some element of coordination involved. This offense results in a 2.25% slash to the stake in the validator slot. -[Zombienet](https://github.com/paritytech/zombienet){target=\_blank} is a flexible testing framework for Polkadot SDK-based blockchains. It enables developers to create and manage ephemeral, short-lived networks. This feature makes Zombienet particularly useful for quick iterations, as it allows you to run multiple local networks concurrently, mimicking different runtime conditions. Whether you're developing a parachain or testing your custom blockchain logic, Zombienet gives you the tools to automate local testing. + ``` mermaid + flowchart LR + N["Total Validators = 100"] + X["Offenders = 5"] + F["min((3 * 5 / 100)^2, 1) = 0.0225"] + G["2.25% slash of stake"] -Key features of Zombienet include: - -- Creating dynamic, local networks with different configurations. -- Running parachains and relay chains in a simulated environment. -- Efficient testing of network components like cross-chain messaging and governance. - -Zombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets. - -### Chopsticks - -[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\_blank} is a tool designed to create forks of Polkadot SDK-based blockchains, allowing developers to interact with network forks as part of their testing process. This capability makes Chopsticks a powerful option for testing upgrades, runtime changes, or cross-chain applications in a forked network environment. - -Key features of Chopsticks include: - -- Forking live Polkadot SDK-based blockchains for isolated testing. -- Simulating cross-chain messages in a private, controlled setup. -- Debugging network behavior by interacting with the fork in real-time. - -Chopsticks provides a controlled environment for developers to safely explore the effects of runtime changes. It ensures that network behavior is tested and verified before upgrades are deployed to live networks. - - ---- - -Page Title: Node and Runtime - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/node-and-runtime/ -- Summary: Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. - -# Node and Runtime - -## Introduction - -Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network. - -Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. - -If the system were a monolithic protocol, any modification would require updating the entire system. Instead, Polkadot achieves true upgradeability by defining an immutable meta-protocol (the client) and a protocol (the runtime) that can be upgraded independently. - -This separation gives the [Polkadot Relay Chain](/polkadot-protocol/architecture/polkadot-chain){target=\_blank} and all connected [parachains](/polkadot-protocol/architecture/parachains){target=\_blank} an evolutionary advantage over other blockchain platforms. - -## Architectural Principles - -The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: - -- Client (Meta-protocol): - - Handles the foundational infrastructure of the blockchain. - - Manages runtime execution, networking, consensus, and other off-chain components. - - Provides an immutable base layer that ensures network stability. - - Upgradable only through hard forks. - -- Runtime (Protocol): - - Defines the blockchain's state transition logic. - - Determines the specific rules and behaviors of the blockchain. - - Compiled to WebAssembly (Wasm) for platform-independent execution. - - Capable of being upgraded without network-wide forking. - -### Advantages of this Architecture - -- **Forkless upgrades**: Runtime can be updated without disrupting the entire network. -- **Modularity**: Clear separation allows independent development of client and runtime. -- **Flexibility**: Enables rapid iteration and evolution of blockchain logic. -- **Performance**: WebAssembly compilation provides efficient, cross-platform execution. - -## Node (Client) - -The node, also known as the client, is the core component responsible for executing the Wasm runtime and orchestrating various essential blockchain components. It ensures the correct execution of the state transition function and manages multiple critical subsystems, including: - -- **Wasm execution**: Runs the blockchain runtime, which defines the state transition rules. -- **Database management**: Stores blockchain data. -- **Networking**: Facilitates peer-to-peer communication, block propagation, and transaction gossiping. -- **Transaction pool (Mempool)**: Manages pending transactions before they are included in a block. -- **Consensus mechanism**: Ensures agreement on the blockchain state across nodes. -- **RPC services**: Provides external interfaces for applications and users to interact with the node. - -## Runtime - -The runtime is more than just a set of rules. It's the fundamental logic engine that defines a blockchain's entire behavior. In Polkadot SDK-based blockchains, the runtime represents a complete, self-contained description of the blockchain's state transition function. - -### Characteristics - -The runtime is distinguished by three key characteristics: - -- **Business logic**: Defines the complete application-specific blockchain behavior. -- **WebAssembly compilation**: Ensures platform-independent, secure execution. -- **On-chain storage**: Stored within the blockchain's state, allowing dynamic updates. - -### Key Functions - -The runtime performs several critical functions, such as: - -- Define state transition rules. -- Implement blockchain-specific logic. -- Manage account interactions. -- Control transaction processing. -- Define governance mechanisms. -- Handle custom pallets and modules. - -## Communication Between Node and Runtime - -The client and runtime communicate exclusively using [SCALE-encoded](/polkadot-protocol/parachain-basics/data-encoding){target=\_blank} communication. This ensures efficient and compact data exchange between the two components. - -### Runtime APIs - -The Runtime API consists of well-defined functions and constants a client assumes are implemented in the Runtime Wasm blob. These APIs enable the client to interact with the runtime to execute blockchain operations and retrieve information. The client invokes these APIs to: - -- Build, execute, and finalize blocks. -- Access metadata. -- Access consensus related information. -- Handle transaction execution. - -### Host Functions - -During execution, the runtime can access certain external client functionalities via host functions. The specific functions the client exposes allow the runtime to perform operations outside the WebAssembly domain. Host functions enable the runtime to: - -- Perform cryptographic operations. -- Access the current blockchain state. -- Handle storage modifications. -- Allocate memory. - - ---- - -Page Title: Offenses and Slashes - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes.md -- Canonical (HTML): https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/offenses-and-slashes/ -- Summary: Learn about how Polkadot discourages validator misconduct via an offenses and slashing system, including details on offenses and their consequences. - -# Offenses and Slashes - -## Introduction - -In Polkadot's Nominated Proof of Stake (NPoS) system, validator misconduct is deterred through a combination of slashing, disabling, and reputation penalties. Validators and nominators who stake tokens face consequences for validator misbehavior, which range from token slashes to restrictions on network participation. - -This page outlines the types of offenses recognized by Polkadot, including block equivocations and invalid votes, as well as the corresponding penalties. While some parachains may implement additional custom slashing mechanisms, this guide focuses on the offenses tied to staking within the Polkadot ecosystem. - -## Offenses - -Polkadot is a public permissionless network. As such, it has a mechanism to disincentivize offenses and incentivize good behavior. You can review the [parachain protocol](https://wiki.polkadot.com/learn/learn-parachains-protocol/#parachain-protocol){target=\_blank} to understand better the terminology used to describe offenses. Polkadot validator offenses fall into two categories: invalid votes and equivocations. - -### Invalid Votes - -A validator will be penalized for inappropriate voting activity during the block inclusion and approval processes. The invalid voting related offenses are as follows: - -- **Backing an invalid block**: A para-validator backs an invalid block for inclusion in a fork of the relay chain. -- **`ForInvalid` vote**: When acting as a secondary checker, the validator votes in favor of an invalid block. -- **`AgainstValid` vote**: When acting as a secondary checker, the validator votes against a valid block. This type of vote wastes network resources required to resolve the disparate votes and resulting dispute. - -### Equivocations - -Equivocation occurs when a validator produces statements that conflict with each other when producing blocks or voting. Unintentional equivocations usually occur when duplicate signing keys reside on the validator host. If keys are never duplicated, the probability of an honest equivocation slash decreases to near zero. The equivocation related offenses are as follows: - -- **Equivocation**: The validator produces two or more of the same block or vote. - - **GRANDPA and BEEFY equivocation**: The validator signs two or more votes in the same round on different chains. - - **BABE equivocation**: The validator produces two or more blocks on the relay chain in the same time slot. -- **Double seconded equivocation**: The validator attempts to second, or back, more than one block in the same round. -- **Seconded and valid equivocation**: The validator seconds, or backs, a block and then attempts to hide their role as the responsible backer by later placing a standard validation vote. - -## Penalties - -On Polkadot, offenses to the network incur different penalties depending on severity. There are three main penalties: slashing, disabling, and reputation changes. - -### Slashing - -Validators engaging in bad actor behavior in the network may be subject to slashing if they commit a qualifying offense. When a validator is slashed, they and their nominators lose a percentage of their staked DOT or KSM, from as little as 0.01% up to 100% based on the severity of the offense. Nominators are evaluated for slashing against their active validations at any given time. Validator nodes are evaluated as discrete entities, meaning an operator can't attempt to mitigate the offense on another node they operate in order to avoid a slash. - -Any slashed DOT or KSM will be added to the [Treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} rather than burned or distributed as rewards. Moving slashed funds to the Treasury allows tokens to be quickly moved away from malicious validators while maintaining the ability to revert faulty slashes when needed. - -A nominator with a very large bond may nominate several validators in a single era. In this case, a slash is proportionate to the amount staked to the offending validator. Stake allocation and validator activation is controlled by the [Phragmén algorithm](https://wiki.polkadot.com/learn/learn-phragmen/#algorithm){target=\_blank}. - -A validator slash creates an `unapplied` state transition. You can view pending slashes on [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Frpc.polkadot.io#/staking/slashes){target=\_blank}. The UI will display the slash per validator, the affected nominators, and the slash amounts. The unapplied state includes a 27-day grace period during which a governance proposal can be made to reverse the slash. Once this grace period expires, the slash is applied. - -#### Equivocation Slash - -The Web3 Foundation's [Slashing mechanisms](https://research.web3.foundation/Polkadot/security/slashing/amounts){target=\_blank} page provides guidelines for evaluating the security threat level of different offenses and determining penalties proportionate to the threat level of the offense. Offenses requiring coordination between validators or extensive computational costs to the system will typically call for harsher penalties than those more likely to be unintentional than malicious. A description of potential offenses for each threat level and the corresponding penalties is as follows: - -- **Level 1**: Honest misconduct such as isolated cases of unresponsiveness. - - **Penalty**: Validator can be kicked out or slashed up to 0.1% of stake in the validator slot. -- **Level 2**: Misconduct that can occur honestly but is a sign of bad practices. Examples include repeated cases of unresponsiveness and isolated cases of equivocation. - - **Penalty**: Slash of up to 1% of stake in the validator slot. -- **Level 3**: Misconduct that is likely intentional but of limited effect on the performance or security of the network. This level will typically include signs of coordination between validators. Examples include repeated cases of equivocation or isolated cases of unjustified voting on GRANDPA. - - **Penalty**: Reduction in networking reputation metrics, slash of up to 10% of stake in the validator slot. -- **Level 4**: Misconduct that poses severe security or monetary risk to the system or mass collusion. Examples include signs of extensive coordination, creating a serious security risk to the system, or forcing the system to use extensive resources to counter the misconduct. - - **Penalty**: Slash of up to 100% of stake in the validator slot. - -See the next section to understand how slash amounts for equivocations are calculated. If you want to know more details about slashing, please look at the research page on [Slashing mechanisms](https://research.web3.foundation/Polkadot/security/slashing/amounts){target=\_blank}. - -#### Slash Calculation for Equivocation - -The slashing penalty for GRANDPA, BABE, and BEEFY equivocations is calculated using the formula below, where `x` represents the number of offenders and `n` is the total number of validators in the active set: - -```text -min((3 * x / n )^2, 1) -``` - -The following scenarios demonstrate how this formula means slash percentages can increase exponentially based on the number of offenders involved compared to the size of the validator pool: - -- **Minor offense**: Assume 1 validator out of a 100 validator active set equivocates in a slot. A single validator committing an isolated offense is most likely a mistake rather than malicious attack on the network. This offense results in a 0.09% slash to the stake in the validator slot. - - ``` mermaid - flowchart LR - N["Total Validators = 100"] - X["Offenders = 1"] - F["min((3 * 1 / 100)^2, 1) = 0.0009"] - G["0.09% slash of stake"] - - N --> F - X --> F - F --> G - ``` - -- **Moderate offense**: Assume 5 validators out a 100 validator active set equivocate in a slot. This is a slightly more serious event as there may be some element of coordination involved. This offense results in a 2.25% slash to the stake in the validator slot. - - ``` mermaid - flowchart LR - N["Total Validators = 100"] - X["Offenders = 5"] - F["min((3 * 5 / 100)^2, 1) = 0.0225"] - G["2.25% slash of stake"] - - N --> F - X --> F - F --> G - ``` + N --> F + X --> F + F --> G + ``` - **Major offense**: Assume 20 validators out a 100 validator active set equivocate in a slot. This is a major security threat as it possible represents a coordinated attack on the network. This offense results in a 36% slash and all slashed validators will also be chilled. ``` mermaid @@ -5329,100 +3985,6 @@ Some minor offenses, such as spamming, are only punished by networking reputatio Refer to the Polkadot Wiki's [offenses page](https://wiki.polkadot.com/learn/learn-offenses/){target=\_blank} for a summary of penalties for specific offenses. ---- - -Page Title: On-Chain Governance Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md -- Canonical (HTML): https://docs.polkadot.com/reference/governance/ -- Summary: Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. - -# On-Chain Governance - -## Introduction - -Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model. - -This guide will explain the principles and structure of OpenGov and walk you through its key components, such as Origins, Tracks, and Delegation. You will learn about improvements over earlier governance systems, including streamlined voting processes and enhanced stakeholder participation. - -With OpenGov, Polkadot achieves a flexible, scalable, and democratic governance framework that allows multiple proposals to proceed simultaneously, ensuring the network evolves in alignment with its community's needs. - -## Governance Evolution - -Polkadot’s governance journey began with [Governance V1](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#governance-summary){target=\_blank}, a system that proved effective in managing treasury funds and protocol upgrades. However, it faced limitations, such as: - -- Slow voting cycles, causing delays in decision-making. -- Inflexibility in handling multiple referendums, restricting scalability. - -To address these challenges, Polkadot introduced OpenGov, a governance model designed for greater inclusivity, efficiency, and scalability. OpenGov replaces the centralized structures of Governance V1, such as the Council and Technical Committee, with a fully decentralized and dynamic framework. - -For a full comparison of the historic and current governance models, visit the [Gov1 vs. Polkadot OpenGov](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#gov1-vs-polkadot-opengov){target=\_blank} section of the Polkadot Wiki. - -## OpenGov Key Features - -OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: - -- **Decentralization**: Shifts all decision-making power to the public, ensuring a more democratic process. -- **Enhanced delegation**: Allows users to delegate their votes to trusted experts across specific governance tracks. -- **Simultaneous referendums**: Multiple proposals can progress at once, enabling faster decision-making. -- **Polkadot Technical Fellowship**: A broad, community-driven group replacing the centralized Technical Committee. - -This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. - -## Origins and Tracks - -In OpenGov, origins and tracks are central to managing proposals and votes. - -- **Origin**: Determines the authority level of a proposal (e.g., Treasury, Root) which decides the track of all referendums from that origin. -- **Track**: Define the procedural flow of a proposal, such as voting duration, approval thresholds, and enactment timelines. - -Developers must be aware that referendums from different origins and tracks will take varying amounts of time to reach approval and enactment. The [Polkadot Technical Fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} has the option to shorten this timeline by whitelisting a proposal and allowing it to be enacted through the [Whitelist Caller](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#whitelisted-caller){target=\_blank} origin. - -Visit [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#origins-and-tracks){target=\_blank} for details on current origins and tracks, associated terminology, and parameters. - -## Referendums - -In OpenGov, anyone can submit a referendum, fostering an open and participatory system. The timeline for a referendum depends on the privilege level of the origin with more significant changes offering more time for community voting and participation before enactment. - -The timeline for an individual referendum includes four distinct periods: - -- **Lead-in**: A minimum amount of time to allow for community participation, available room in the origin, and payment of the decision deposit. Voting is open during this period. -- **Decision**: Voting continues. -- **Confirmation**: Referendum must meet [approval and support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} criteria during entire period to avoid rejection. -- **Enactment**: Changes approved by the referendum are executed. - -### Vote on Referendums - -Voters can vote with their tokens on each referendum. Polkadot uses a voluntary token locking mechanism, called conviction voting, as a way for voters to increase their voting power. A token holder signals they have a stronger preference for approving a proposal based upon their willingness to lock up tokens. Longer voluntary token locks are seen as a signal of continual approval and translate to increased voting weight. - -See [Voting on a Referendum](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank} for a deeper look at conviction voting and related token locks. - -### Delegate Voting Power - -The OpenGov system also supports multi-role delegations, allowing token holders to assign their voting power on different tracks to entities with expertise in those areas. - -For example, if a token holder lacks the technical knowledge to evaluate proposals on the [Root track](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#root){target=\_blank}, they can delegate their voting power for that track to an expert they trust to vote in the best interest of the network. This ensures informed decision-making across tracks while maintaining flexibility for token holders. - -Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. - -### Cancel a Referendum - -Polkadot OpenGov has two origins for rejecting ongoing referendums: - -- [**Referendum Canceller**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-canceller){target=\_blank}: Cancels an active referendum when non-malicious errors occur and refunds the deposits to the originators. -- [**Referendum Killer**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-killer){target=\_blank}: Used for urgent, malicious cases this origin instantly terminates an active referendum and slashes deposits. - -See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. - -## Additional Resources - -- **[Democracy pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/democracy/src){target=\_blank}**: Handles administration of general stakeholder voting. -- **[Gov2: Polkadot’s Next Generation of Decentralised Governance](https://medium.com/polkadot-network/gov2-polkadots-next-generation-of-decentralised-governance-4d9ef657d11b){target=\_blank}**: Medium article by Gavin Wood. -- **[Polkadot Direction](https://matrix.to/#/#Polkadot-Direction:parity.io){target=\_blank}**: Matrix Element client. -- **[Polkassembly](https://polkadot.polkassembly.io/){target=\_blank}**: OpenGov dashboard and UI. -- **[Polkadot.js Apps Governance](https://polkadot.js.org/apps/#/referenda){target=\_blank}**: Overview of active referendums. - - --- Page Title: Overview of FRAME @@ -5559,973 +4121,51 @@ This section covers the most common customization patterns you'll encounter: --- -Page Title: Overview of the Polkadot Relay Chain +Page Title: Pause Validating -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/ -- Summary: Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-pause-validating.md +- Canonical (HTML): https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/ +- Summary: Learn how to temporarily pause staking activity in Polkadot using the chill extrinsic, with guidance for validators and nominators. -# Overview +# Pause Validating ## Introduction -Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank}, and cross-chain interactions via its native [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank}. - -This guide covers key aspects of Polkadot’s architecture, including its high-level protocol structure, blockspace commoditization, and the role of its native token, DOT, in governance, staking, and resource allocation. - -## Polkadot 1.0 - -Polkadot 1.0 represents the state of Polkadot as of 2023, coinciding with the release of [Polkadot runtime v1.0.0](https://github.com/paritytech/polkadot/releases/tag/v1.0.0){target=\_blank}. This section will focus on Polkadot 1.0, along with philosophical insights into network resilience and blockspace. - -As a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including: - -- **Application-specific Layer-1 blockchains (parachains)**: Polkadot's sharded network allows for parallel transaction processing, with shards that can have unique state transition functions, enabling custom-built L1 chains optimized for specific applications. - -- **Shared security and scalability**: L1 chains connected to Polkadot benefit from its [Nominated Proof of Stake (NPoS)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#nominated-proof-of-stake){target=\_blank} system, providing security out-of-the-box without the need to bootstrap their own. - -- **Secure interoperability**: Polkadot's native interoperability enables seamless data and value exchange between parachains. This interoperability can also be used outside of the ecosystem for bridging with external networks. - -- **Resilient infrastructure**: Decentralized and scalable, Polkadot ensures ongoing support for development and community initiatives via its on-chain [treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} and governance. - -- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. - -- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. - - - [Polkadot Blockchain Academy](https://polkadot.com/blockchain-academy){target=\_blank} - - [EdX courses](https://www.edx.org/school/web3x){target=\_blank} - - Rust and Substrate courses (coming soon) - -### High-Level Architecture - -Polkadot features a chain that serves as the central component of the system. This chain is depicted as a ring encircled by several parachains that are connected to it. - -According to Polkadot's design, any blockchain that can compile to WebAssembly (Wasm) and adheres to the Parachains Protocol becomes a parachain on the Polkadot network. - -Here’s a high-level overview of the Polkadot protocol architecture: - -![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } - -Parachains propose blocks to Polkadot validators, who check for availability and validity before finalizing them. With the relay chain providing security, collators—full nodes of parachains—can focus on their tasks without needing strong incentives. - -The [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank} allows parachains to exchange messages freely, leveraging the chain's security for trust-free communication. - -In order to interact with chains that want to use their own finalization process (e.g., Bitcoin), Polkadot has [bridges](/reference/parachains/interoperability/#bridges-connecting-external-networks){target=\_blank} that offer two-way compatibility, meaning that transactions can be made between different parachains. - -### Polkadot's Additional Functionalities - -Historically, obtaining core slots on Polkadot chain relied upon crowdloans and auctions. Chain cores were leased through auctions for three-month periods, up to a maximum of two years. Crowdloans enabled users to securely lend funds to teams for lease deposits in exchange for pre-sale tokens, which is the only way to access slots on Polkadot 1.0. Auctions are now deprecated in favor of [coretime](/polkadot-protocol/architecture/system-chains/coretime/){target=\_blank}. - -Additionally, the chain handles [staking](https://wiki.polkadot.com/learn/learn-staking/){target=\_blank}, [accounts](/reference/parachains/accounts/){target=\_blank}, balances, and [governance](/reference/governance/){target=\_blank}. - -#### Agile Coretime - -The new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. - -[Agile coretime](/reference/polkadot-hub/consensus-and-security/agile-coretime/){target=\_blank} improves the efficient use of Polkadot's network resources and offers economic flexibility for developers, extending Polkadot's capabilities far beyond the original vision outlined in the [whitepaper](https://polkadot.com/papers/Polkadot-whitepaper.pdf){target=\_blank}. - -It enables parachains to purchase monthly "bulk" allocations of coretime (the time allocated for utilizing a core, measured in Polkadot relay chain blocks), ensuring heavy-duty parachains that can author a block every six seconds with [Asynchronous Backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} can reliably renew their coretime each month. Although six-second block times are now the default, parachains have the option of producing blocks less frequently. - -Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. - -### Polkadot's Resilience - -Decentralization is a vital component of blockchain networks, but it comes with trade-offs: - -- An overly decentralized network may face challenges in reaching consensus and require significant energy to operate. -- Also, a network that achieves consensus quickly risks centralization, making it easier to manipulate or attack. - -A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. - -Polkadot 1.0 currently achieves resilience through several strategies: - -- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. - -- **Decentralized nodes**: Designed to encourage operators to join the network. This program aims to expand and diversify the validators in the ecosystem who aim to become independent of the program during their term. Feel free to explore more about the program on the official [Decentralized Nodes](https://nodes.web3.foundation/){target=\_blank} page. - -- **On-chain treasury and governance**: Known as [OpenGov](/reference/governance/){target=\_blank}, this system allows every decision to be made through public referenda, enabling any token holder to cast a vote. - -### Polkadot's Blockspace - -Polkadot 1.0’s design allows for the commoditization of blockspace. - -Blockspace is a blockchain's capacity to finalize and commit operations, encompassing its security, computing, and storage capabilities. Its characteristics can vary across different blockchains, affecting security, flexibility, and availability. - -- **Security**: Measures the robustness of blockspace in Proof of Stake (PoS) networks linked to the stake locked on validator nodes, the variance in stake among validators, and the total number of validators. It also considers social centralization (how many validators are owned by single operators) and physical centralization (how many validators run on the same service provider). - -- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes. - -- **Availability**: Indicates how easily users can access blockspace. It should be easily accessible, allowing diverse business models to thrive, ideally regulated by a marketplace based on demand and supplemented by options for "second-hand" blockspace. - -Polkadot is built on core blockspace principles, but there's room for improvement. Tasks like balance transfers, staking, and governance are managed on the relay chain. - -Delegating these responsibilities to [system chains](/polkadot-protocol/architecture/system-chains/){target=\_blank} could enhance flexibility and allow the relay chain to concentrate on providing shared security and interoperability. - -For more information about blockspace, watch [Robert Habermeier’s interview](https://www.youtube.com/watch?v=e1vISppPwe4){target=\_blank} or read his [technical blog post](https://www.rob.tech/blog/polkadot-blockspace-over-blockchains/){target=\_blank}. - -## DOT Token - -DOT is the native token of the Polkadot network, much like BTC for Bitcoin and Ether for the Ethereum blockchain. DOT has 10 decimals, uses the Planck base unit, and has a balance type of `u128`. The same is true for Kusama's KSM token with the exception of having 12 decimals. - -### Redenomination of DOT - -Polkadot conducted a community poll, which ended on 27 July 2020 at block 888,888, to decide whether to redenominate the DOT token. The stakeholders chose to redenominate the token, changing the value of 1 DOT from 1e12 plancks to 1e10 plancks. - -Importantly, this did not affect the network's total number of base units (plancks); it only affects how a single DOT is represented. The redenomination became effective 72 hours after transfers were enabled, occurring at block 1,248,328 on 21 August 2020 around 16:50 UTC. - -### The Planck Unit - -The smallest unit of account balance on Polkadot SDK-based blockchains (such as Polkadot and Kusama) is called _Planck_, named after the Planck length, the smallest measurable distance in the physical universe. - -Similar to how BTC's smallest unit is the Satoshi and ETH's is the Wei, Polkadot's native token DOT equals 1e10 Planck, while Kusama's native token KSM equals 1e12 Planck. - -### Uses for DOT - -DOT serves three primary functions within the Polkadot network: - -- **Governance**: It is used to participate in the governance of the network. -- **Staking**: DOT is staked to support the network's operation and security. -- **Buying coretime**: Used to purchase coretime in-bulk or on-demand and access the chain to benefit from Polkadot's security and interoperability. - -Additionally, DOT can serve as a transferable token. For example, DOT, held in the treasury, can be allocated to teams developing projects that benefit the Polkadot ecosystem. - -## JAM and the Road Ahead - -The Join-Accumulate Machine (JAM) represents a transformative redesign of Polkadot's core architecture, envisioned as the successor to the current relay chain. Unlike traditional blockchain architectures, JAM introduces a unique computational model that processes work through two primary functions: - -- **Join**: Handles data integration. -- **Accumulate**: Folds computations into the chain's state. - -JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: - -- **Permissionless code execution**: JAM is designed to be more generic and flexible, allowing for permissionless code execution through services that can be deployed without governance approval. -- **More effective block time utilization**: JAM's efficient pipeline processing model places the prior state root in block headers instead of the posterior state root, enabling more effective utilization of block time for computations. - -This architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes. - - ---- - -Page Title: Parachains Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/ -- Summary: Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. - -# Parachains Overview - -## Introduction - -A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network. - -Unlike standalone blockchains that must bootstrap their own validator sets and security, parachains leverage Polkadot's pooled security model. This allows parachain developers to focus on their application-specific functionality rather than consensus and security infrastructure. Parachains can communicate with each other through Cross-Consensus Messaging (XCM), enabling seamless interoperability across the Polkadot ecosystem. - -Key capabilities that parachains provide include: - -- **Shared security**: Inherit security from Polkadot's validator set without maintaining your own. -- **Interoperability**: Communicate trustlessly with other parachains via XCM. -- **Scalability**: Process transactions in parallel with other parachains. -- **Customization**: Build application-specific logic tailored to your use case. -- **Upgradeability**: Upgrade runtime logic without hard forks. - -## Polkadot SDK: Parachain Architecture - -Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: - -![](/images/reference/parachains/index/overview-01.webp) - -- **[Substrate](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html){target=\_blank}**: The foundation providing core blockchain primitives and libraries. -- **[FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank}**: A modular framework for building your parachain's runtime logic. -- **[Cumulus](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html){target=\_blank}**: Essential libraries and pallets that enable parachain functionality. -- **[XCM (Cross Consensus Messaging)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/xcm/index.html){target=\_blank}**: The messaging format for communicating with other parachains and the relay chain. -- **[Polkadot](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/polkadot/index.html){target=\_blank}**: The relay chain that provides security and coordination. - -### Substrate: The Foundation - -Substrate provides the core infrastructure that every parachain is built upon. It handles the low-level blockchain functionality, allowing you to focus on your application's unique features. Substrate includes implementations for networking, database management, consensus participation, and the execution environment for your runtime. - -Every Polkadot SDK node consists of two main components: - -- **Client (Host)**: Handles infrastructure services. - - - Native binary that runs on validator and collator nodes. - - Executes the Wasm-compiled runtime. - - Manages networking, database, mempool, and block production. - - Interfaces with the relay chain for validation. - -- **Runtime (State Transition Function)**: Contains your business logic. - - - Defines how your Polkadot SDK node processes transactions. - - Compiled to [Wasm](https://webassembly.org/){target=\_blank} for deterministic execution. - - Stored on-chain and upgradeable via governance. - -```mermaid -%%{init: {'flowchart': {'padding': 5, 'nodeSpacing': 50, 'rankSpacing': 10}}}%% -graph TB - classDef title font-size:20px,font-weight:bold,stroke-width:0px - classDef clientStyle font-size:16px,font-weight:bold - classDef clientSubNodeStyle margin-top:10px - classDef runtimeCallExecutorStyle padding-top:10px - - subgraph sg1[Parachain
    Node] - direction TB - - I[RuntimeCall Executor] - B[Wasm Runtime - STF] - - subgraph sg2[Client] - direction TB - C[Network and Blockchain
    Infrastructure Services
    + Relay Chain Interface] - end - - I --> B - end - - class sg1 title - class sg2 clientStyle - class C clientSubNodeStyle - class I runtimeCallExecutorStyle - -``` - -### FRAME: Building Blocks for Your Runtime - -FRAME provides modular components called [pallets](/reference/glossary#pallet){target=\_blank} that you can compose to build your parachain's runtime. Each pallet provides specific functionality that you can customize and configure for your needs. This modular approach allows you to quickly assemble complex functionality without writing everything from scratch. - -```mermaid -graph LR - subgraph SP["Parachain Runtime"] - direction LR - Timestamp ~~~ Aura ~~~ ParachainSystem - Balances ~~~ TransactionPayment ~~~ Sudo - subgraph Timestamp["Timestamp"] - SS1[Custom Config] - end - subgraph Aura["Aura"] - SS2[Custom Config] - end - subgraph ParachainSystem["Parachain System"] - SS3[Custom Config] - end - subgraph Balances["Balances"] - SS4[Custom Config] - end - subgraph TransactionPayment["Transaction Payment"] - SS5[Custom Config] - end - subgraph Sudo["Sudo"] - SS6[Custom Config] - end - style Timestamp stroke:#FF69B4 - style Aura stroke:#FF69B4 - style ParachainSystem stroke:#FF69B4 - style Balances stroke:#FF69B4 - style TransactionPayment stroke:#FF69B4 - style Sudo stroke:#FF69B4 - style SS1 stroke-dasharray: 5 - style SS2 stroke-dasharray: 5 - style SS3 stroke-dasharray: 5 - style SS4 stroke-dasharray: 5 - style SS5 stroke-dasharray: 5 - style SS6 stroke-dasharray: 5 - - end - subgraph AP["Available FRAME Pallets"] - direction LR - A1[Aura]~~~A2[Parachain
    System]~~~A3[Transaction
    Payment]~~~A4[Sudo] - B1[Identity]~~~B2[Balances]~~~B3[Assets]~~~B4[EVM] - C1[Timestamp]~~~C2[Staking]~~~C3[Contracts]~~~C4[and more...] - end - AP --> SP -``` - -### Cumulus: Parachain-Specific Functionality - -Cumulus is what transforms a Polkadot SDK-based runtime into a parachain-capable runtime. It provides the essential components for communicating with the relay chain, participating in Polkadot's consensus, and handling parachain-specific operations like block validation and collation. - -Key Cumulus components include: - -- **Parachain system pallet**: Core parachain functionality and relay chain communication. -- **Collator consensus**: Block production logic for parachain collators. -- **Relay chain interface**: APIs for interacting with the Polkadot relay chain. -- **Validation data**: Handling proof-of-validity data required by relay chain validators. - -## Where to Go Next - -Building a parachain requires understanding the relationship between your chain and the Polkadot relay chain. The Polkadot SDK provides all the tools needed to design custom runtime logic, enable cross-chain communication, and deploy your parachain to production. - -The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. - -
    - -- Guide __Launch a Simple Parachain__ - - --- - - Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. - - [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) - - -- Guide __Customize Your Runtime__ - - --- - - Design your parachain's runtime logic and choose appropriate pallets for your use case. - - [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) - -- Guide __Interoperability__ - - --- - - Implement XCM for trustless cross-chain communication with other parachains. - - [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/) - -- Guide __Runtime Upgrades__ - - --- - - Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. - - [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) - -
    - - ---- - -Page Title: Pause Validating - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-pause-validating.md -- Canonical (HTML): https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/ -- Summary: Learn how to temporarily pause staking activity in Polkadot using the chill extrinsic, with guidance for validators and nominators. - -# Pause Validating - -## Introduction - -If you need to temporarily stop participating in Polkadot staking activities without fully unbonding your funds, chilling your account allows you to do so efficiently. Chilling removes your node from active validation or nomination in the next era while keeping your funds bonded, making it ideal for planned downtimes or temporary pauses. - -This guide covers the steps for chilling as a validator or nominator, using the `chill` and `chillOther` extrinsics, and how these affect your staking status and nominations. - -## Chilling Your Node - -If you need to temporarily step back from staking without unbonding your funds, you can "chill" your account. Chilling pauses your active staking participation, setting your account to inactive in the next era while keeping your funds bonded. - -To chill your account, go to the **Network > Staking > Account Actions** page on [Polkadot.js Apps](https://polkadot.js.org/apps){target=\_blank}, and select **Stop**. Alternatively, you can call the [`chill`](https://paritytech.github.io/polkadot-sdk/master/pallet_staking/enum.Call.html#variant.chill){target=\_blank} extrinsic in the Staking pallet. - -## Staking Election Timing Considerations - -When a node actively participates in staking but then chills, it will continue contributing for the remainder of the current era. However, its eligibility for the next election depends on the chill status at the start of the new era: - -- **Chilled during previous era**: Will not participate in the current era election and will remain inactive until reactivated. -- **Chilled during current era**: Will not be selected for the next era's election. -- **Chilled after current era**: May be selected if it was active during the previous era and is now chilled. - -## Chilling as a Nominator - -When you choose to chill as a nominator, your active nominations are reset. Upon re-entering the nominating process, you must reselect validators to support manually. Depending on preferences, these can be the same validators as before or a new set. Remember that your previous nominations won’t be saved or automatically reactivated after chilling. - -While chilled, your nominator account remains bonded, preserving your staked funds without requiring a full unbonding process. When you’re ready to start nominating again, you can issue a new nomination call to activate your bond with a fresh set of validators. This process bypasses the need for re-bonding, allowing you to maintain your stake while adjusting your involvement in active staking. - -## Chilling as a Validator - -When you chill as a validator, your active validator status is paused. Although your nominators remain bonded to you, the validator bond will no longer appear as an active choice for new or revised nominations until reactivated. Any existing nominators who take no action will still have their stake linked to the validator, meaning they don’t need to reselect the validator upon reactivation. However, if nominators adjust their stakes while the validator is chilled, they will not be able to nominate the chilled validator until it resumes activity. - -Upon reactivating as a validator, you must also reconfigure your validator preferences, such as commission rate and other parameters. These can be set to match your previous configuration or updated as desired. This step is essential for rejoining the active validator set and regaining eligibility for nominations. - -## Chill Other - -Historical constraints in the runtime prevented unlimited nominators and validators from being supported. These constraints created a need for checks to keep the size of the staking system manageable. One of these checks is the `chillOther` extrinsic, allowing users to chill accounts that no longer met standards such as minimum staking requirements set through on-chain governance. - -This control mechanism included a `ChillThreshold`, which was structured to define how close to the maximum number of nominators or validators the staking system would be allowed to get before users could start chilling one another. With the passage of [Referendum #90](https://polkadot-old.polkassembly.io/referendum/90){target=\_blank}, the value for `maxNominatorCount` on Polkadot was set to `None`, effectively removing the limit on how many nominators and validators can participate. This means the `ChillThreshold` will never be met; thus, `chillOther` no longer has any effect. - - ---- - -Page Title: Polkadot SDK Accounts - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/accounts/ -- Summary: Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. - -# Accounts - -## Introduction - -Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains. - -This page will guide you through the essential aspects of accounts, including their data structure, balance types, reference counters, and address formats. You’ll learn how accounts are managed within the runtime, how balances are categorized, and how addresses are encoded and validated. - -## Account Data Structure - -Accounts are foundational to any blockchain, and the Polkadot SDK provides a flexible management system. This section explains how the Polkadot SDK defines accounts and manages their lifecycle through data structures within the runtime. - -### Account - -The [`Account` data type](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/type.Account.html){target=\_blank} is a storage map within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank} that links an account ID to its corresponding data. This structure is fundamental for mapping account-related information within the chain. - -The code snippet below shows how accounts are defined: - -```rs - /// The full account information for a particular account ID. - #[pallet::storage] - #[pallet::getter(fn account)] - pub type Account = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - AccountInfo, - ValueQuery, - >; -``` - -The preceding code block defines a storage map named `Account`. The `StorageMap` is a type of on-chain storage that maps keys to values. In the `Account` map, the key is an account ID, and the value is the account's information. Here, `T` represents the generic parameter for the runtime configuration, which is defined by the pallet's configuration trait (`Config`). - -The `StorageMap` consists of the following parameters: - -- **`_`**: Used in macro expansion and acts as a placeholder for the storage prefix type. Tells the macro to insert the default prefix during expansion. -- **`Blake2_128Concat`**: The hashing function applied to keys in the storage map. -- **`T: :AccountId`**: Represents the key type, which corresponds to the account’s unique ID. -- **`AccountInfo`**: The value type stored in the map. For each account ID, the map stores an `AccountInfo` struct containing: - - - **`T::Nonce`**: A nonce for the account, which is incremented with each transaction to ensure transaction uniqueness. - - **`T: :AccountData`**: Custom account data defined by the runtime configuration, which could include balances, locked funds, or other relevant information. - -- **`ValueQuery`**: Defines how queries to the storage map behave when no value is found; returns a default value instead of `None`. - -For a detailed explanation of storage maps, see the [`StorageMap`](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/struct.StorageMap.html){target=\_blank} entry in the Rust docs. - -### Account Info - -The `AccountInfo` structure is another key element within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank}, providing more granular details about each account's state. This structure tracks vital data, such as the number of transactions and the account’s relationships with other modules. - -```rs -/// Information of an account. -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct AccountInfo { - /// The number of transactions this account has sent. - pub nonce: Nonce, - /// The number of other modules that currently depend on this account's existence. The account - /// cannot be reaped until this is zero. - pub consumers: RefCount, - /// The number of other modules that allow this account to exist. The account may not be reaped - /// until this and `sufficients` are both zero. - pub providers: RefCount, - /// The number of modules that allow this account to exist for their own purposes only. The - /// account may not be reaped until this and `providers` are both zero. - pub sufficients: RefCount, - /// The additional data that belongs to this account. Used to store the balance(s) in a lot of - /// chains. - pub data: AccountData, -} -``` - -The `AccountInfo` structure includes the following components: - -- **`nonce`**: Tracks the number of transactions initiated by the account, which ensures transaction uniqueness and prevents replay attacks. -- **`consumers`**: Counts how many other modules or pallets rely on this account’s existence. The account cannot be removed from the chain (reaped) until this count reaches zero. -- **`providers`**: Tracks how many modules permit this account’s existence. An account can only be reaped once both `providers` and `sufficients` are zero. -- **`sufficients`**: Represents the number of modules that allow the account to exist for internal purposes, independent of any other modules. -- **`AccountData`**: A flexible data structure that can be customized in the runtime configuration, usually containing balances or other user-specific data. - -This structure helps manage an account's state and prevents its premature removal while it is still referenced by other on-chain data or modules. The [`AccountInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.AccountInfo.html){target=\_blank} structure can vary as long as it satisfies the trait bounds defined by the `AccountData` associated type in the [`frame-system::pallet::Config`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/trait.Config.html){target=\_blank} trait. - -### Account Reference Counters - -Polkadot SDK uses reference counters to track an account’s dependencies across different runtime modules. These counters ensure that accounts remain active while data is associated with them. - -The reference counters include: - -- **`consumers`**: Prevents account removal while other pallets still rely on the account. -- **`providers`**: Ensures an account is active before other pallets store data related to it. -- **`sufficients`**: Indicates the account’s independence, ensuring it can exist even without a native token balance, such as when holding sufficient alternative assets. - -#### Providers Reference Counters - -The `providers` counter ensures that an account is ready to be depended upon by other runtime modules. For example, it is incremented when an account has a balance above the existential deposit, which marks the account as active. - -The system requires this reference counter to be greater than zero for the `consumers` counter to be incremented, ensuring the account is stable before any dependencies are added. - -#### Consumers Reference Counters - -The `consumers` counter ensures that the account cannot be reaped until all references to it across the runtime have been removed. This check prevents the accidental deletion of accounts that still have active on-chain data. - -It is the user’s responsibility to clear out any data from other runtime modules if they wish to remove their account and reclaim their existential deposit. - -#### Sufficients Reference Counter - -The `sufficients` counter tracks accounts that can exist independently without relying on a native account balance. This is useful for accounts holding other types of assets, like tokens, without needing a minimum balance in the native token. - -For instance, the [Assets pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank}, may increment this counter for an account holding sufficient tokens. - -#### Account Deactivation - -In Polkadot SDK-based chains, an account is deactivated when its reference counters (such as `providers`, `consumers`, and `sufficient`) reach zero. These counters ensure the account remains active as long as other runtime modules or pallets reference it. - -When all dependencies are cleared and the counters drop to zero, the account becomes deactivated and may be removed from the chain (reaped). This is particularly important in Polkadot SDK-based blockchains, where accounts with balances below the existential deposit threshold are pruned from storage to conserve state resources. - -Each pallet that references an account has cleanup functions that decrement these counters when the pallet no longer depends on the account. Once these counters reach zero, the account is marked for deactivation. - -#### Updating Counters - -The Polkadot SDK provides runtime developers with various methods to manage account lifecycle events, such as deactivation or incrementing reference counters. These methods ensure that accounts cannot be reaped while still in use. - -The following helper functions manage these counters: - -- **`inc_consumers()`**: Increments the `consumer` reference counter for an account, signaling that another pallet depends on it. -- **`dec_consumers()`**: Decrements the `consumer` reference counter, signaling that a pallet no longer relies on the account. -- **`inc_providers()`**: Increments the `provider` reference counter, ensuring the account remains active. -- **`dec_providers()`**: Decrements the `provider` reference counter, allowing for account deactivation when no longer in use. -- **`inc_sufficients()`**: Increments the `sufficient` reference counter for accounts that hold sufficient assets. -- **`dec_sufficients()`**: Decrements the `sufficient` reference counter. - -To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. - -The `System` pallet offers three query functions to assist developers in tracking account states: - -- **[`can_inc_consumer()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_inc_consumer){target=\_blank}**: Checks if the account can safely increment the consumer reference. -- **[`can_dec_provider()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_dec_provider){target=\_blank}**: Ensures that no consumers exist before allowing the decrement of the provider counter. -- **[`is_provider_required()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.is_provider_required){target=\_blank}**: Verifies whether the account still has any active consumer references. - -This modular and flexible system of reference counters tightly controls the lifecycle of accounts in Polkadot SDK-based blockchains, preventing the accidental removal or retention of unneeded accounts. You can refer to the [System pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html){target=\_blank} for more details. - - -## Account Balance Types - -In the Polkadot ecosystem, account balances are categorized into different types based on how the funds are utilized and their availability. These balance types determine the actions that can be performed, such as transferring tokens, paying transaction fees, or participating in governance activities. Understanding these balance types helps developers manage user accounts and implement balance-dependent logic. - -!!! note "A more efficient distribution of account balance types is in development" - Soon, pallets in the Polkadot SDK will implement the [`Fungible` trait](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} (see the [tracking issue](https://github.com/paritytech/polkadot-sdk/issues/226){target=\_blank} for more details). For example, the [`transaction-storage`](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_storage/index.html){target=\_blank} pallet changed the implementation of the [`Currency`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/currency/index.html){target=\_blank} trait (see the [Refactor transaction storage pallet to use fungible traits](https://github.com/paritytech/polkadot-sdk/pull/1800){target=\_blank} PR for further details): - - ```rust - type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - ``` - - To the [`Fungible`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} trait: - - ```rust - type BalanceOf = <::Currency as FnInspect<::AccountId>>::Balance; - ``` - - This update will enable more efficient use of account balances, allowing the free balance to be utilized for on-chain activities such as setting proxies and managing identities. - -### Balance Types - -The five main balance types are: - -- **Free balance**: Represents the total tokens available to the account for any on-chain activity, including staking, governance, and voting. However, it may not be fully spendable or transferrable if portions of it are locked or reserved. -- **Locked balance**: Portions of the free balance that cannot be spent or transferred because they are tied up in specific activities like [staking](https://wiki.polkadot.com/learn/learn-staking/#nominating-validators){target=\_blank}, [vesting](https://wiki.polkadot.com/learn/learn-guides-transfers/#vested-transfers-with-the-polkadot-js-ui){target=\_blank}, or participating in [governance](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank}. While the tokens remain part of the free balance, they are non-transferable for the duration of the lock. -- **Reserved balance**: Funds locked by specific system actions, such as setting up an [identity](https://wiki.polkadot.com/learn/learn-identity/){target=\_blank}, creating [proxies](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}, or submitting [deposits for governance proposals](https://wiki.polkadot.com/learn/learn-guides-polkadot-opengov/#claiming-opengov-deposits){target=\_blank}. These tokens are not part of the free balance and cannot be spent unless they are unreserved. -- **Spendable balance**: The portion of the free balance that is available for immediate spending or transfers. It is calculated by subtracting the maximum of locked or reserved amounts from the free balance, ensuring that existential deposit limits are met. -- **Untouchable balance**: Funds that cannot be directly spent or transferred but may still be utilized for on-chain activities, such as governance participation or staking. These tokens are typically tied to certain actions or locked for a specific period. - -The spendable balance is calculated as follows: - -```text -spendable = free - max(locked - reserved, ED) -``` - -Here, `free`, `locked`, and `reserved` are defined above. The `ED` represents the [existential deposit](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank}, the minimum balance required to keep an account active and prevent it from being reaped. You may find you can't see all balance types when looking at your account via a wallet. Wallet providers often display only spendable, locked, and reserved balances. - -### Locks - -Locks are applied to an account's free balance, preventing that portion from being spent or transferred. Locks are automatically placed when an account participates in specific on-chain activities, such as staking or governance. Although multiple locks may be applied simultaneously, they do not stack. Instead, the largest lock determines the total amount of locked tokens. - -Locks follow these basic rules: - -- If different locks apply to varying amounts, the largest lock amount takes precedence. -- If multiple locks apply to the same amount, the lock with the longest duration governs when the balance can be unlocked. - -#### Locks Example - -Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: - -- 80 DOT is staked with a 28-day lock period. -- 24 DOT is locked for governance with a 1x conviction and a 7-day lock period. -- 4 DOT is locked for governance with a 6x conviction and a 224-day lock period. - -In this case, the total locked amount is 80 DOT because only the largest lock (80 DOT from staking) governs the locked balance. These 80 DOT will be released at different times based on the lock durations. In this example, the 24 DOT locked for governance will be released first since the shortest lock period is seven days. The 80 DOT stake with a 28-day lock period is released next. Now, all that remains locked is the 4 DOT for governance. After 224 days, all 80 DOT (minus the existential deposit) will be free and transferable. - -![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) - -#### Edge Cases for Locks - -In scenarios where multiple convictions and lock periods are active, the lock duration and amount are determined by the longest period and largest amount. For example, if you delegate with different convictions and attempt to undelegate during an active lock period, the lock may be extended for the full amount of tokens. For a detailed discussion on edge case lock behavior, see this [Stack Exchange post](https://substrate.stackexchange.com/questions/5067/delegating-and-undelegating-during-the-lock-period-extends-it-for-the-initial-am){target=\_blank}. - -### Balance Types on Polkadot.js - -Polkadot.js provides a user-friendly interface for managing and visualizing various account balances on Polkadot and Kusama networks. When interacting with Polkadot.js, you will encounter multiple balance types that are critical for understanding how your funds are distributed and restricted. This section explains how different balances are displayed in the Polkadot.js UI and what each type represents. - -![](/images/reference/parachains/accounts/accounts-02.webp) - -The most common balance types displayed on Polkadot.js are: - -- **Total balance**: The total number of tokens available in the account. This includes all tokens, whether they are transferable, locked, reserved, or vested. However, the total balance does not always reflect what can be spent immediately. In this example, the total balance is 0.6274 KSM. - -- **Transferable balance**: Shows how many tokens are immediately available for transfer. It is calculated by subtracting the locked and reserved balances from the total balance. For example, if an account has a total balance of 0.6274 KSM and a transferable balance of 0.0106 KSM, only the latter amount can be sent or spent freely. - -- **Vested balance**: Tokens that allocated to the account but released according to a specific schedule. Vested tokens remain locked and cannot be transferred until fully vested. For example, an account with a vested balance of 0.2500 KSM means that this amount is owned but not yet transferable. - -- **Locked balance**: Tokens that are temporarily restricted from being transferred or spent. These locks typically result from participating in staking, governance, or vested transfers. In Polkadot.js, locked balances do not stack—only the largest lock is applied. For instance, if an account has 0.5500 KSM locked for governance and staking, the locked balance would display 0.5500 KSM, not the sum of all locked amounts. - -- **Reserved balance**: Refers to tokens locked for specific on-chain actions, such as setting an identity, creating a proxy, or making governance deposits. Reserved tokens are not part of the free balance, but can be freed by performing certain actions. For example, removing an identity would unreserve those funds. - -- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period. - -- **Redeemable balance**: The number of tokens that have completed the unbonding period and are ready to be unlocked and transferred again. For example, if an account has a redeemable balance of 0.1000 KSM, those tokens are now available for spending. - -- **Democracy balance**: Reflects the number of tokens locked for governance activities, such as voting on referenda. These tokens are locked for the duration of the governance action and are only released after the lock period ends. - -By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. - -## Address Formats - -The SS58 address format is a core component of the Polkadot SDK that enables accounts to be uniquely identified across Polkadot-based networks. This format is a modified version of Bitcoin's Base58Check encoding, specifically designed to accommodate the multi-chain nature of the Polkadot ecosystem. SS58 encoding allows each chain to define its own set of addresses while maintaining compatibility and checksum validation for security. - -### Basic Format - -SS58 addresses consist of three main components: - -```text -base58encode(concat(,
    , )) -``` - -- **Address type**: A byte or set of bytes that define the network (or chain) for which the address is intended. This ensures that addresses are unique across different Polkadot SDK-based chains. -- **Address**: The public key of the account encoded as bytes. -- **Checksum**: A hash-based checksum which ensures that addresses are valid and unaltered. The checksum is derived from the concatenated address type and address components, ensuring integrity. - -The encoding process transforms the concatenated components into a Base58 string, providing a compact and human-readable format that avoids easily confused characters (e.g., zero '0', capital 'O', lowercase 'l'). This encoding function ([`encode`](https://docs.rs/bs58/latest/bs58/fn.encode.html){target=\_blank}) is implemented exactly as defined in Bitcoin and IPFS specifications, using the same alphabet as both implementations. - -For more details about the SS58 address format implementation, see the [`Ss58Codec`](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Ss58Codec.html){target=\_blank} trait in the Rust Docs. - -### Address Type - -The address type defines how an address is interpreted and to which network it belongs. Polkadot SDK uses different prefixes to distinguish between various chains and address formats: - -- **Address types `0-63`**: Simple addresses, commonly used for network identifiers. -- **Address types `64-127`**: Full addresses that support a wider range of network identifiers. -- **Address types `128-255`**: Reserved for future address format extensions. - -For example, Polkadot’s main network uses an address type of 0, while Kusama uses 2. This ensures that addresses can be used without confusion between networks. - -The address type is always encoded as part of the SS58 address, making it easy to quickly identify the network. Refer to the [SS58 registry](https://github.com/paritytech/ss58-registry){target=\_blank} for the canonical listing of all address type identifiers and how they map to Polkadot SDK-based networks. - -### Address Length - -SS58 addresses can have different lengths depending on the specific format. Address lengths range from as short as 3 to 35 bytes, depending on the complexity of the address and network requirements. This flexibility allows SS58 addresses to adapt to different chains while providing a secure encoding mechanism. - -| Total | Type | Raw account | Checksum | -|-------|------|-------------|----------| -| 3 | 1 | 1 | 1 | -| 4 | 1 | 2 | 1 | -| 5 | 1 | 2 | 2 | -| 6 | 1 | 4 | 1 | -| 7 | 1 | 4 | 2 | -| 8 | 1 | 4 | 3 | -| 9 | 1 | 4 | 4 | -| 10 | 1 | 8 | 1 | -| 11 | 1 | 8 | 2 | -| 12 | 1 | 8 | 3 | -| 13 | 1 | 8 | 4 | -| 14 | 1 | 8 | 5 | -| 15 | 1 | 8 | 6 | -| 16 | 1 | 8 | 7 | -| 17 | 1 | 8 | 8 | -| 35 | 1 | 32 | 2 | - -SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. - -### Checksum Types - -A checksum is applied to validate SS58 addresses. Polkadot SDK uses a Blake2b-512 hash function to calculate the checksum, which is appended to the address before encoding. The checksum length can vary depending on the address format (e.g., 1-byte, 2-byte, or longer), providing varying levels of validation strength. - -The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. - -### Validating Addresses - -SS58 addresses can be validated using the subkey command-line interface or the Polkadot.js API. These tools help ensure an address is correctly formatted and valid for the intended network. The following sections will provide an overview of how validation works with these tools. - -#### Using Subkey - -[Subkey](https://paritytech.github.io/polkadot-sdk/master/subkey/index.html){target=\_blank} is a CLI tool provided by Polkadot SDK for generating and managing keys. It can inspect and validate SS58 addresses. - -The `inspect` command gets a public key and an SS58 address from the provided secret URI. The basic syntax for the `subkey inspect` command is: - -```bash -subkey inspect [flags] [options] uri -``` - -For the `uri` command-line argument, you can specify the secret seed phrase, a hex-encoded private key, or an SS58 address. If the input is a valid address, the `subkey` program displays the corresponding hex-encoded public key, account identifier, and SS58 addresses. - -For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: - -```bash -subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" -``` - -The command displays output similar to the following: - -
    - subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" - Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account: - Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849 - Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR - Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - SS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR -
    - -The `subkey` program assumes an address is based on a public/private key pair. If you inspect an address, the command returns the 32-byte account identifier. - -However, not all addresses in Polkadot SDK-based networks are based on keys. - -Depending on the command-line options you specify and the input you provided, the command output might also display the network for which the address has been encoded. For example: - -```bash -subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" -``` - -The command displays output similar to the following: - -
    - subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" - Public Key URI `12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU` is account: - Network ID/Version: polkadot - Public key (hex): 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Account ID: 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Public key (SS58): 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU - SS58 Address: 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU -
    - -#### Using Polkadot.js API - -To verify an address in JavaScript or TypeScript projects, you can use the functions built into the [Polkadot.js API](https://polkadot.js.org/docs/){target=\_blank}. For example: - -```js -// Import Polkadot.js API dependencies -const { decodeAddress, encodeAddress } = require('@polkadot/keyring'); -const { hexToU8a, isHex } = require('@polkadot/util'); - -// Specify an address to test. -const address = 'INSERT_ADDRESS_TO_TEST'; - -// Check address -const isValidSubstrateAddress = () => { - try { - encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); - - return true; - } catch (error) { - return false; - } -}; - -// Query result -const isValid = isValidSubstrateAddress(); -console.log(isValid); - -``` - -If the function returns `true`, the specified address is a valid address. - -#### Other SS58 Implementations - -Support for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries. - -- **Crystal**: [`wyhaines/base58.cr`](https://github.com/wyhaines/base58.cr){target=\_blank} -- **Go**: [`itering/subscan-plugin`](https://github.com/itering/subscan-plugin){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **TypeScript**: [`subsquid/squid-sdk`](https://github.com/subsquid/squid-sdk){target=\_blank} - - ---- - -Page Title: Randomness - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/randomness/ -- Summary: Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. - -# Randomness - -## Introduction - -Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as "random" numbers on a computer are actually pseudo-random. These numbers rely on an initial "seed," which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\_blank}, [heart rates](https://mdpi.altmetric.com/details/47574324){target=\_blank}, or even [lava lamps](https://en.wikipedia.org/wiki/Lavarand){target=\_blank}. While this may seem random, given the same "seed," the same sequence of numbers will always be generated. - -In a global blockchain network, relying on real-world entropy for randomness isn’t feasible because these inputs vary by time and location. If nodes use different inputs, blockchains can fork. Hence, real-world randomness isn't suitable for use as a seed in blockchain systems. - -Currently, two primary methods for generating randomness in blockchains are used: [`RANDAO`](#randao) and [`VRF`](#vrf) (Verifiable Random Function). Polkadot adopts the `VRF` approach for its randomness. - -## VRF - -A Verifiable Random Function (VRF) is a cryptographic function that generates a random number and proof that ensures the submitter produced the number. This proof allows anyone to verify the validity of the random number. - -Polkadot's VRF is similar to the one used in [**Ouroboros Praos**](https://eprint.iacr.org/2017/573.pdf){target=\_blank}, which secures randomness for block production in systems like [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe){target=\_blank} (Polkadot’s block production mechanism). - -The key difference is that Polkadot's VRF doesn’t rely on a central clock—avoiding the issue of whose clock to trust. Instead, it uses its own past results and slot numbers to simulate time and determine future outcomes. - -### How VRF Works - -Slots on Polkadot are discrete units of time, each lasting six seconds, and can potentially hold a block. Multiple slots form an epoch, with 2400 slots making up one four-hour epoch. - -In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: - -1. A "secret key," unique to each validator, is used for the die roll. -2. An epoch randomness value, derived from the hash of VRF outputs from blocks two epochs ago (N-2), so past randomness influences the current epoch (N). -3. The current slot number. - -This process helps maintain fair randomness across the network. - -Here is a graphical representation: - -![](/images/reference/parachains/randomness/randomness-01.webp) - -The VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). - -The result is checked by the validator against a protocol threshold. If it's below the threshold, the validator becomes a candidate for block production in that slot. - -The validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`. - -So, VRF can be expressed like: - -`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)` - -Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. - -After executing the VRF, the `RESULT` is compared to a protocol-defined `THRESHOLD`. If the `RESULT` is below the `THRESHOLD`, the validator becomes a valid candidate to propose a block for that slot. Otherwise, the validator skips the slot. - -As a result, there may be multiple validators eligible to propose a block for a slot. In this case, the block accepted by other nodes will prevail, provided it is on the chain with the latest finalized block as determined by the GRANDPA finality gadget. It's also possible for no block producers to be available for a slot, in which case the AURA consensus takes over. AURA is a fallback mechanism that randomly selects a validator to produce a block, running in parallel with BABE and only stepping in when no block producers exist for a slot. Otherwise, it remains inactive. - -Because validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. - -To verify resolution of this issue and that Polkadot block times remain near constant-time, see the [PoS Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} page of this documentation. - -## RANDAO - -An alternative on-chain randomness method is Ethereum's RANDAO, where validators perform thousands of hashes on a seed and publish the final hash during a round. The collective input from all validators forms the random number, and as long as one honest validator participates, the randomness is secure. - -To enhance security, RANDAO can optionally be combined with a Verifiable Delay Function (VDF), ensuring that randomness can't be predicted or manipulated during computation. - -For more information about RANDAO, see the [Randomness - RANDAO](https://eth2book.info/capella/part2/building_blocks/randomness/){target=\_blank} section of the Upgrading Ethereum documentation. - -## VDFs - -Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. - -They produce a unique result that can be quickly verified publicly. When combined with RANDAO, feeding RANDAO's output into a VDF introduces a delay that nullifies an attacker's chance to influence the randomness. - -However, VDF likely requires specialized ASIC devices to run separately from standard nodes. - -!!!warning - While only one is needed to secure the system, and they will be open-source and inexpensive, running VDF devices involves significant costs without direct incentives, adding friction for blockchain users. - -## Additional Resources - -For more information about the reasoning for choices made along with proofs, see Polkadot's research on blockchain randomness and sortition in the [Block production](https://research.web3.foundation/Polkadot/protocols/block-production){target=\_blank} entry of the Polkadot Wiki. - -For a discussion with Web3 Foundation researchers about when and under what conditions Polkadot's randomness can be utilized, see the [Discussion on Randomness used in Polkadot](https://github.com/use-ink/ink/issues/57){target=\_blank} issue on GitHub. - - ---- - -Page Title: Register a Local Asset - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md -- Canonical (HTML): https://docs.polkadot.com/chain-interactions/token-operations/register-local-asset/ -- Summary: Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. - -# Register a Local Asset on Asset Hub - -## Introduction - -As detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation. - -This guide will take you through the steps of registering a local asset on the Asset Hub parachain. - -## Prerequisites - -Before you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and a funded wallet with DOT or KSM. - -- For Polkadot Asset Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata. -- For Kusama Asset Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata. - -You need to ensure that your Asset Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees. - -## Steps to Register a Local Asset - -To register a local asset on the Asset Hub parachain, follow these steps: - -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. - - - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`. - - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider. - -2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. - - ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) - -3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column. - - ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) - -4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. - - ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) - -5. Fill in the required fields in the **Create Asset** form: - - 1. **creator account**: The account to be used for creating this asset and setting up the initial metadata. - 2. **asset name**: The descriptive name of the asset you are registering. - 3. **asset symbol**: The symbol that will be used to represent the asset. - 4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface. - 5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested. - 6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id. - 7. Click on the **Next** button. - - ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp) - -6. Choose the accounts for the roles listed below: +If you need to temporarily stop participating in Polkadot staking activities without fully unbonding your funds, chilling your account allows you to do so efficiently. Chilling removes your node from active validation or nomination in the next era while keeping your funds bonded, making it ideal for planned downtimes or temporary pauses. - 1. **admin account**: The account designated for continuous administration of the token. - 2. **issuer account**: The account that will be used for issuing this token. - 3. **freezer account**: The account that will be used for performing token freezing operations. - 4. Click on the **Create** button. +This guide covers the steps for chilling as a validator or nominator, using the `chill` and `chillOther` extrinsics, and how these affect your staking status and nominations. - ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp) +## Chilling Your Node -7. Click on the **Sign and Submit** button to complete the asset registration process. +If you need to temporarily step back from staking without unbonding your funds, you can "chill" your account. Chilling pauses your active staking participation, setting your account to inactive in the next era while keeping your funds bonded. - ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) +To chill your account, go to the **Network > Staking > Account Actions** page on [Polkadot.js Apps](https://polkadot.js.org/apps){target=\_blank}, and select **Stop**. Alternatively, you can call the [`chill`](https://paritytech.github.io/polkadot-sdk/master/pallet_staking/enum.Call.html#variant.chill){target=\_blank} extrinsic in the Staking pallet. -## Verify Asset Registration +## Staking Election Timing Considerations -After completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets){target=\_blank} section of the Polkadot.js Apps interface. +When a node actively participates in staking but then chills, it will continue contributing for the remainder of the current era. However, its eligibility for the next election depends on the chill status at the start of the new era: -![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp) +- **Chilled during previous era**: Will not participate in the current era election and will remain inactive until reactivated. +- **Chilled during current era**: Will not be selected for the next era's election. +- **Chilled after current era**: May be selected if it was active during the previous era and is now chilled. -!!! tip - Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field. +## Chilling as a Nominator -In this way, you have successfully registered a local asset on the Asset Hub parachain. +When you choose to chill as a nominator, your active nominations are reset. Upon re-entering the nominating process, you must reselect validators to support manually. Depending on preferences, these can be the same validators as before or a new set. Remember that your previous nominations won’t be saved or automatically reactivated after chilling. -For an in-depth explanation about Asset Hub and its features, see the [Asset Hub](/chain-interactions/token-operations/convert-assets/){target=\_blank} entry in the Polkadot Wiki. +While chilled, your nominator account remains bonded, preserving your staked funds without requiring a full unbonding process. When you’re ready to start nominating again, you can issue a new nomination call to activate your bond with a fresh set of validators. This process bypasses the need for re-bonding, allowing you to maintain your stake while adjusting your involvement in active staking. -## Test Setup Environment +## Chilling as a Validator -You can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank} documentation. +When you chill as a validator, your active validator status is paused. Although your nominators remain bonded to you, the validator bond will no longer appear as an active choice for new or revised nominations until reactivated. Any existing nominators who take no action will still have their stake linked to the validator, meaning they don’t need to reselect the validator upon reactivation. However, if nominators adjust their stakes while the validator is chilled, they will not be able to nominate the chilled validator until it resumes activity. -To set up a test environment, execute the following command: +Upon reactivating as a validator, you must also reconfigure your validator preferences, such as commission rate and other parameters. These can be set to match your previous configuration or updated as desired. This step is essential for rejoining the active validator set and regaining eligibility for nominations. -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` +## Chill Other -The above command will spawn a lazy fork of Polkadot Asset Hub with the latest block data from the network. If you need to test Kusama Asset Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. +Historical constraints in the runtime prevented unlimited nominators and validators from being supported. These constraints created a need for checks to keep the size of the staking system manageable. One of these checks is the `chillOther` extrinsic, allowing users to chill accounts that no longer met standards such as minimum staking requirements set through on-chain governance. -An Asset Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet. +This control mechanism included a `ChillThreshold`, which was structured to define how close to the maximum number of nominators or validators the staking system would be allowed to get before users could start chilling one another. With the passage of [Referendum #90](https://polkadot-old.polkassembly.io/referendum/90){target=\_blank}, the value for `maxNominatorCount` on Polkadot was set to `None`, effectively removing the limit on how many nominators and validators can participate. This means the `ChillThreshold` will never be met; thus, `chillOther` no longer has any effect. --- @@ -8126,495 +5766,103 @@ ProtectClock=true ProtectControlGroups=true ProtectHostname=true ProtectKernelModules=true -ProtectKernelTunables=true -ProtectSystem=strict -RemoveIPC=true -RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX -RestrictNamespaces=false -RestrictSUIDSGID=true -SystemCallArchitectures=native -SystemCallFilter=@system-service -SystemCallFilter=landlock_add_rule landlock_create_ruleset landlock_restrict_self seccomp mount umount2 -SystemCallFilter=~@clock @module @reboot @swap @privileged -SystemCallFilter=pivot_root -UMask=0027 - -[Install] -WantedBy=multi-user.target -``` - -!!! warning "Restart delay and equivocation risk" - It is recommended that a node's restart be delayed with `RestartSec` in the case of a crash. It's possible that when a node crashes, consensus votes in GRANDPA aren't persisted to disk. In this case, there is potential to equivocate when immediately restarting. Delaying the restart will allow the network to progress past potentially conflicting votes. - -### Run the Service - -Activate the systemd service to start on system boot by running: - -```bash -systemctl enable polkadot-validator.service -``` - -To start the service manually, use: - -```bash -systemctl start polkadot-validator.service -``` - -Check the service's status to confirm it is running: - -```bash -systemctl status polkadot-validator.service -``` - -To view the logs in real-time, use [journalctl](https://www.freedesktop.org/software/systemd/man/latest/journalctl.html){target=\_blank} like so: - -```bash -journalctl -f -u polkadot-validator -``` - -With these steps, you can effectively manage and monitor your validator as a systemd service. - -Once your validator is active, it's officially part of Polkadot's security infrastructure. For questions or further support, you can reach out to the [Polkadot Validator chat](https://matrix.to/#/!NZrbtteFeqYKCUGQtr:matrix.parity.io?via=matrix.parity.io&via=matrix.org&via=web3.foundation){target=\_blank} for tips and troubleshooting. - - ---- - -Page Title: Stop Validating - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md -- Canonical (HTML): https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/ -- Summary: Learn to safely stop validating on Polkadot, including chilling, unbonding tokens, and purging validator keys. - -# Stop Validating - -## Introduction - -If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability. - -## Pause Versus Stop - -If you wish to remain a validator or nominator (for example, stopping for planned downtime or server maintenance), submitting the `chill` extrinsic in the `staking` pallet should suffice. Additional steps are only needed to unbond funds or reap an account. - -The following are steps to ensure a smooth stop to validation: - -- Chill the validator. -- Purge validator session keys. -- Unbond your tokens. - -## Chill Validator - -When stepping back from validating, the first step is to chill your validator status. This action stops your validator from being considered for the next era without fully unbonding your tokens, which can be useful for temporary pauses like maintenance or planned downtime. - -Use the `staking.chill` extrinsic to initiate this. For more guidance on chilling your node, refer to the [Pause Validating](/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/){target=\_blank} guide. You may also claim any pending staking rewards at this point. - -## Purge Validator Session Keys - -Purging validator session keys is a critical step in removing the association between your validator account and its session keys, which ensures that your account is fully disassociated from validator activities. The `session.purgeKeys` extrinsic removes the reference to your session keys from the stash or staking proxy account that originally set them. - -Here are a couple of important things to know about purging keys: - -- **Account used to purge keys**: Always use the same account to purge keys you originally used to set them, usually your stash or staking proxy account. Using a different account may leave an unremovable reference to the session keys on the original account, preventing its reaping. -- **Account reaping issue**: Failing to purge keys will prevent you from reaping (fully deleting) your stash account. If you attempt to transfer tokens without purging, you'll need to rebond, purge the session keys, unbond again, and wait through the unbonding period before any transfer. - -## Unbond Your Tokens - -After chilling your node and purging session keys, the final step is to unbond your staked tokens. This action removes them from staking and begins the unbonding period (usually 28 days for Polkadot and seven days for Kusama), after which the tokens will be transferable. - -To unbond tokens, go to **Network > Staking > Account Actions** on Polkadot.js Apps. Select your stash account, click on the dropdown menu, and choose **Unbond Funds**. Alternatively, you can use the `staking.unbond` extrinsic if you handle this via a staking proxy account. - -Once the unbonding period is complete, your tokens will be available for use in transactions or transfers outside of staking. - - ---- - -Page Title: Technical Reference Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md -- Canonical (HTML): https://docs.polkadot.com/reference/ -- Summary: Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. - -## Introduction - -The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need. - -Polkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\_blank} to the [governance](/reference/glossary#governance){target=\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants. - -This guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem. - -## Polkadot Hub - -[Polkadot Hub](/reference/polkadot-hub/){target=\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain. - -The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: - -- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications. -- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem. -- **Staking**: Participate in network security and earn rewards by staking DOT. -- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov. -- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities. -- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem. -- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations. - -## Parachains - -[Parachains](/reference/parachains/){target=\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers: - -- **Accounts**: Deep dive into account types, storage, and management on parachains. -- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms. -- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus. -- **Chain data**: Explore data structures, storage layouts, and state management. -- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains. -- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility. -- **Networks**: Learn about networking protocols and peer-to-peer communication. -- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\_blank}, the standard for cross-chain communication. -- **Randomness**: Understand how randomness is generated and used in Polkadot chains. -- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. - -## On-Chain Governance - -[On-Chain governance](/reference/governance/){target=\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details: - -- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums. -- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity. -- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance. -- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system. - -## Glossary - -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: - -- Blockchain concepts (blocks, transactions, state) -- Consensus mechanisms (validators, collators, finality) -- Polkadot-specific terms (relay chain, parachain, XCM, FRAME) -- Network components (nodes, runtimes, storage) -- Governance terminology (origins, tracks, referendums) - -## Tools - -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: - -- **Light clients**: Lightweight solutions for interacting with the network without running full nodes. -- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\_blank} and [PAPI](/reference/tools/papi/){target=\_blank} for building applications. -- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\_blank} and other Rust-based libraries for SDK development. -- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\_blank} for Python developers. -- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\_blank}, and [Omninode](/reference/tools/omninode/){target=\_blank} for smart contract and parachain testing. -- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\_blank} for substrate interaction. -- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\_blank} for XCM integration and asset transfers. - -## Where to Go Next - -For detailed exploration of specific areas, proceed to any of the main sections: - -
    - -- Learn **Polkadot Hub** - - --- - - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. - - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) - -- Learn **Parachains** - - --- - - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. - - [:octicons-arrow-right-24: Reference](/reference/parachains/) - -- Learn **On-Chain Governance** - - --- - - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. - - [:octicons-arrow-right-24: Reference](/reference/governance/) - -- Guide **Glossary** - - --- - - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. - - [:octicons-arrow-right-24: Reference](/reference/glossary/) - -- Guide **Tools** - - --- - - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. - - [:octicons-arrow-right-24: Reference](/reference/tools/) - -
    - - ---- - -Page Title: Transactions - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/ -- Summary: Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. - -# Transactions - -## Introduction - -Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions. - -This guide walks you through the different transaction types and how they're formatted, validated, and processed within the Polkadot ecosystem. You'll also learn how to customize transaction formats and construct transactions for FRAME-based runtimes, ensuring a complete understanding of how transactions are built and executed in Polkadot SDK-based chains. - -## What Is a Transaction? - -In the Polkadot SDK, transactions represent operations that modify the chain's state, bundled into blocks for execution. The term extrinsic is often used to refer to any data that originates outside the runtime and is included in the chain. While other blockchain systems typically refer to these operations as "transactions," the Polkadot SDK adopts the broader term "extrinsic" to capture the wide variety of data types that can be added to a block. - -There are three primary types of transactions (extrinsics) in the Polkadot SDK: - -- **Signed transactions**: Signed by the submitting account, often carrying transaction fees. -- **Unsigned transactions**: Submitted without a signature, often requiring custom validation logic. -- **Inherent transactions**: Typically inserted directly into blocks by block authoring nodes, without gossiping between peers. - -Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. - -### Signed Transactions - -Signed transactions require an account's signature and typically involve submitting a request to execute a runtime call. The signature serves as a form of cryptographic proof that the sender has authorized the action, using their private key. These transactions often involve a transaction fee to cover the cost of execution and incentivize block producers. - -Signed transactions are the most common type of transaction and are integral to user-driven actions, such as token transfers. For instance, when you transfer tokens from one account to another, the sending account must sign the transaction to authorize the operation. - -For example, the [`pallet_balances::Call::transfer_allow_death`](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/pallet/struct.Pallet.html#method.transfer_allow_death){target=\_blank} extrinsic in the Balances pallet allows you to transfer tokens. Since your account initiates this transaction, your account key is used to sign it. You'll also be responsible for paying the associated transaction fee, with the option to include an additional tip to incentivize faster inclusion in the block. - -### Unsigned Transactions - -Unsigned transactions do not require a signature or account-specific data from the sender. Unlike signed transactions, they do not come with any form of economic deterrent, such as fees, which makes them susceptible to spam or replay attacks. Custom validation logic must be implemented to mitigate these risks and ensure these transactions are secure. - -Unsigned transactions typically involve scenarios where including a fee or signature is unnecessary or counterproductive. However, due to the absence of fees, they require careful validation to protect the network. For example, [`pallet_im_online::Call::heartbeat`](https://paritytech.github.io/polkadot-sdk/master/pallet_im_online/pallet/struct.Pallet.html#method.heartbeat){target=\_blank} extrinsic allows validators to send a heartbeat signal, indicating they are active. Since only validators can make this call, the logic embedded in the transaction ensures that the sender is a validator, making the need for a signature or fee redundant. - -Unsigned transactions are more resource-intensive than signed ones because custom validation is required, but they play a crucial role in certain operational scenarios, especially when regular user accounts aren't involved. - -### Inherent Transactions - -Inherent transactions are a specialized type of unsigned transaction that is used primarily for block authoring. Unlike signed or other unsigned transactions, inherent transactions are added directly by block producers and are not broadcasted to the network or stored in the transaction queue. They don't require signatures or the usual validation steps and are generally used to insert system-critical data directly into blocks. - -A key example of an inherent transaction is inserting a timestamp into each block. The [`pallet_timestamp::Call::now`](https://paritytech.github.io/polkadot-sdk/master/pallet_timestamp/pallet/struct.Pallet.html#method.now-1){target=\_blank} extrinsic allows block authors to include the current time in the block they are producing. Since the block producer adds this information, there is no need for transaction validation, like signature verification. The validation in this case is done indirectly by the validators, who check whether the timestamp is within an acceptable range before finalizing the block. - -Another example is the [`paras_inherent::Call::enter`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/paras_inherent/pallet/struct.Pallet.html#method.enter){target=\_blank} extrinsic, which enables parachain collator nodes to send validation data to the relay chain. This inherent transaction ensures that the necessary parachain data is included in each block without the overhead of gossiped transactions. - -Inherent transactions serve a critical role in block authoring by allowing important operational data to be added directly to the chain without needing the validation processes required for standard transactions. - -## Transaction Formats - -Understanding the structure of signed and unsigned transactions is crucial for developers building on Polkadot SDK-based chains. Whether you're optimizing transaction processing, customizing formats, or interacting with the transaction pool, knowing the format of extrinsics, Polkadot's term for transactions, is essential. - -### Types of Transaction Formats - -In Polkadot SDK-based chains, extrinsics can fall into three main categories: - -- **Unchecked extrinsics**: Typically used for signed transactions that require validation. They contain a signature and additional data, such as a nonce and information for fee calculation. Unchecked extrinsics are named as such because they require validation checks before being accepted into the transaction pool. -- **Checked extrinsics**: Typically used for inherent extrinsics (unsigned transactions); these don't require signature verification. Instead, they carry information such as where the extrinsic originates and any additional data required for the block authoring process. -- **Opaque extrinsics**: Used when the format of an extrinsic is not yet fully committed or finalized. They are still decodable, but their structure can be flexible depending on the context. - -### Signed Transaction Data Structure - -A signed transaction typically includes the following components: - -- **Signature**: Verifies the authenticity of the transaction sender. -- **Call**: The actual function or method call the transaction is requesting (for example, transferring funds). -- **Nonce**: Tracks the number of prior transactions sent from the account, helping to prevent replay attacks. -- **Tip**: An optional incentive to prioritize the transaction in block inclusion. -- **Additional data**: Includes details such as spec version, block hash, and genesis hash to ensure the transaction is valid within the correct runtime and chain context. - -Here's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime: - -``` code - + + -``` - -Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. - -### Signed Extensions - -Polkadot SDK also provides the concept of [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}, which allow developers to extend extrinsics with additional data or validation logic before they are included in a block. The [`SignedExtension`](https://paritytech.github.io/try-runtime-cli/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} set helps enforce custom rules or protections, such as ensuring the transaction's validity or calculating priority. - -The transaction queue regularly calls signed extensions to verify a transaction's validity before placing it in the ready queue. This safeguard ensures transactions won't fail in a block. Signed extensions are commonly used to enforce validation logic and protect the transaction pool from spam and replay attacks. - -In FRAME, a signed extension can hold any of the following types by default: - -- **[`AccountId`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/types_common/type.AccountId.html){target=\_blank}**: To encode the sender's identity. -- **[`Call`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Call){target=\_blank}**: To encode the pallet call to be dispatched. This data is used to calculate transaction fees. -- **[`AdditionalSigned`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.AdditionalSigned){target=\_blank}**: To handle any additional data to go into the signed payload allowing you to attach any custom logic prior to dispatching a transaction. -- **[`Pre`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Pre){target=\_blank}**: To encode the information that can be passed from before a call is dispatched to after it gets dispatched. - -Signed extensions can enforce checks like: - -- **[`CheckSpecVersion`](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/extensions/check_spec_version.rs.html){target=\_blank}**: Ensures the transaction is compatible with the runtime's current version. -- **[`CheckWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.CheckWeight.html){target=\_blank}**: Calculates the weight (or computational cost) of the transaction, ensuring the block doesn't exceed the maximum allowed weight. - -These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. - -## Transaction Construction - -Building transactions in the Polkadot SDK involves constructing a payload that can be verified, signed, and submitted for inclusion in a block. Each runtime in the Polkadot SDK has its own rules for validating and executing transactions, but there are common patterns for constructing a signed transaction. - -### Construct a Signed Transaction - -A signed transaction in the Polkadot SDK includes various pieces of data to ensure security, prevent replay attacks, and prioritize processing. Here's an overview of how to construct one: - -1. **Construct the unsigned payload**: Gather the necessary information for the call, including: - - - **Pallet index**: Identifies the pallet where the runtime function resides. - - **Function index**: Specifies the particular function to call in the pallet. - - **Parameters**: Any additional arguments required by the function call. - -2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: - - - **Transaction nonce**: Unique identifier to prevent replay attacks. - - **Era information**: Defines how long the transaction is valid before it's dropped from the pool. - - **Block hash**: Ensures the transaction doesn't execute on the wrong chain or fork. - -3. **Sign the payload**: Using the sender's private key, sign the payload to ensure that the transaction can only be executed by the account holder. -4. **Serialize the signed payload**: Once signed, the transaction must be serialized into a binary format, ensuring the data is compact and easy to transmit over the network. -5. **Submit the serialized transaction**: Finally, submit the serialized transaction to the network, where it will enter the transaction pool and wait for processing by an authoring node. - -The following is an example of how a signed transaction might look: - -``` rust -node_runtime::UncheckedExtrinsic::new_signed( - function.clone(), // some call - sp_runtime::AccountId32::from(sender.public()).into(), // some sending account - node_runtime::Signature::Sr25519(signature.clone()), // the account's signature - extra.clone(), // the signed extensions -) -``` - -### Transaction Encoding - -Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: - -- **`[1]`**: Compact encoded length in bytes of the entire transaction. -- **`[2]`**: A u8 containing 1 byte to indicate whether the transaction is signed or unsigned (1 bit) and the encoded transaction version ID (7 bits). -- **`[3]`**: If signed, this field contains an account ID, an SR25519 signature, and some extra data. -- **`[4]`**: Encoded call data, including pallet and function indices and any required arguments. - -This encoded format ensures consistency and efficiency in processing transactions across the network. By adhering to this format, applications can construct valid transactions and pass them to the network for execution. - -To learn more about how compact encoding works using SCALE, see the [SCALE Codec](https://github.com/paritytech/parity-scale-codec){target=\_blank} README on GitHub. - -### Customize Transaction Construction - -Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: - -- **Custom pallets**: You can define new pallets with custom function calls, each with its own parameters and validation logic. -- **Signed extensions**: Developers can implement custom extensions that modify how transactions are prioritized, validated, or included in blocks. - -By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. - -## Lifecycle of a Transaction - -In the Polkadot SDK, transactions are often referred to as extrinsics because the data in transactions originates outside of the runtime. These transactions contain data that initiates changes to the chain state. The most common type of extrinsic is a signed transaction, which is cryptographically verified and typically incurs a fee. This section focuses on how signed transactions are processed, validated, and ultimately included in a block. - -### Define Transaction Properties - -The Polkadot SDK runtime defines key transaction properties, such as: - -- **Transaction validity**: Ensures the transaction meets all runtime requirements. -- **Signed or unsigned**: Identifies whether a transaction needs to be signed by an account. -- **State changes**: Determines how the transaction modifies the state of the chain. - -Pallets, which compose the runtime's logic, define the specific transactions that your chain supports. When a user submits a transaction, such as a token transfer, it becomes a signed transaction, verified by the user's account signature. If the account has enough funds to cover fees, the transaction is executed, and the chain's state is updated accordingly. - -### Process on a Block Authoring Node - -In Polkadot SDK-based networks, some nodes are authorized to author blocks. These nodes validate and process transactions. When a transaction is sent to a node that can produce blocks, it undergoes a lifecycle that involves several stages, including validation and execution. Non-authoring nodes gossip the transaction across the network until an authoring node receives it. The following diagram illustrates the lifecycle of a transaction that's submitted to a network and processed by an authoring node. - -![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } - -### Validate and Queue +ProtectKernelTunables=true +ProtectSystem=strict +RemoveIPC=true +RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX +RestrictNamespaces=false +RestrictSUIDSGID=true +SystemCallArchitectures=native +SystemCallFilter=@system-service +SystemCallFilter=landlock_add_rule landlock_create_ruleset landlock_restrict_self seccomp mount umount2 +SystemCallFilter=~@clock @module @reboot @swap @privileged +SystemCallFilter=pivot_root +UMask=0027 -Once a transaction reaches an authoring node, it undergoes an initial validation process to ensure it meets specific conditions defined in the runtime. This validation includes checks for: +[Install] +WantedBy=multi-user.target +``` -- **Correct nonce**: Ensures the transaction is sequentially valid for the account. -- **Sufficient funds**: Confirms the account can cover any associated transaction fees. -- **Signature validity**: Verifies that the sender's signature matches the transaction data. +!!! warning "Restart delay and equivocation risk" + It is recommended that a node's restart be delayed with `RestartSec` in the case of a crash. It's possible that when a node crashes, consensus votes in GRANDPA aren't persisted to disk. In this case, there is potential to equivocate when immediately restarting. Delaying the restart will allow the network to progress past potentially conflicting votes. -After these checks, valid transactions are placed in the transaction pool, where they are queued for inclusion in a block. The transaction pool regularly re-validates queued transactions to ensure they remain valid before being processed. To reach consensus, two-thirds of the nodes must agree on the order of the transactions executed and the resulting state change. Transactions are validated and queued on the local node in a transaction pool to prepare for consensus. +### Run the Service -#### Transaction Pool +Activate the systemd service to start on system boot by running: -The transaction pool is responsible for managing valid transactions. It ensures that only transactions that pass initial validity checks are queued. Transactions that fail validation, expire, or become invalid for other reasons are removed from the pool. +```bash +systemctl enable polkadot-validator.service +``` -The transaction pool organizes transactions into two queues: +To start the service manually, use: -- **Ready queue**: Transactions that are valid and ready to be included in a block. -- **Future queue**: Transactions that are not yet valid but could be in the future, such as transactions with a nonce too high for the current state. +```bash +systemctl start polkadot-validator.service +``` -Details on how the transaction pool validates transactions, including fee and signature handling, can be found in the [`validate_transaction`](https://paritytech.github.io/polkadot-sdk/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction){target=\_blank} method. +Check the service's status to confirm it is running: -#### Invalid Transactions +```bash +systemctl status polkadot-validator.service +``` -If a transaction is invalid, for example, due to an invalid signature or insufficient funds, it is rejected and won't be added to the block. Invalid transactions might be rejected for reasons such as: +To view the logs in real-time, use [journalctl](https://www.freedesktop.org/software/systemd/man/latest/journalctl.html){target=\_blank} like so: -- The transaction has already been included in a block. -- The transaction's signature does not match the sender. -- The transaction is too large to fit in the current block. +```bash +journalctl -f -u polkadot-validator +``` -### Transaction Ordering and Priority +With these steps, you can effectively manage and monitor your validator as a systemd service. -When a node is selected as the next block author, it prioritizes transactions based on weight, length, and tip amount. The goal is to fill the block with high-priority transactions without exceeding its maximum size or computational limits. Transactions are ordered as follows: +Once your validator is active, it's officially part of Polkadot's security infrastructure. For questions or further support, you can reach out to the [Polkadot Validator chat](https://matrix.to/#/!NZrbtteFeqYKCUGQtr:matrix.parity.io?via=matrix.parity.io&via=matrix.org&via=web3.foundation){target=\_blank} for tips and troubleshooting. -- **Inherents first**: Inherent transactions, such as block timestamp updates, are always placed first. -- **Nonce-based ordering**: Transactions from the same account are ordered by their nonce. -- **Fee-based ordering**: Among transactions with the same nonce or priority level, those with higher fees are prioritized. -### Transaction Execution +--- -Once a block author selects transactions from the pool, the transactions are executed in priority order. As each transaction is processed, the state changes are written directly to the chain's storage. It's important to note that these changes are not cached, meaning a failed transaction won't revert earlier state changes, which could leave the block in an inconsistent state. +Page Title: Stop Validating -Events are also written to storage. Runtime logic should not emit an event before performing the associated actions. If the associated transaction fails after the event was emitted, the event will not revert. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md +- Canonical (HTML): https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/ +- Summary: Learn to safely stop validating on Polkadot, including chilling, unbonding tokens, and purging validator keys. -## Transaction Mortality +# Stop Validating -Transactions in the network can be configured as either mortal (with expiration) or immortal (without expiration). Every transaction payload contains a block checkpoint (reference block number and hash) and an era/validity period that determines how many blocks after the checkpoint the transaction remains valid. +## Introduction -When a transaction is submitted, the network validates it against these parameters. If the transaction is not included in a block within the specified validity window, it is automatically removed from the transaction queue. +If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability. -- **Mortal transactions**: Have a finite lifespan and will expire after a specified number of blocks. For example, a transaction with a block checkpoint of 1000 and a validity period of 64 blocks will be valid from blocks 1000 to 1064. +## Pause Versus Stop -- **Immortal transactions**: Never expire and remain valid indefinitely. To create an immortal transaction, set the block checkpoint to 0 (genesis block), use the genesis hash as a reference, and set the validity period to 0. +If you wish to remain a validator or nominator (for example, stopping for planned downtime or server maintenance), submitting the `chill` extrinsic in the `staking` pallet should suffice. Additional steps are only needed to unbond funds or reap an account. -However, immortal transactions pose significant security risks through replay attacks. If an account is reaped (balance drops to zero, account removed) and later re-funded, malicious actors can replay old immortal transactions. +The following are steps to ensure a smooth stop to validation: -The blockchain maintains only a limited number of prior block hashes for reference validation, called `BlockHashCount`. If your validity period exceeds `BlockHashCount`, the effective validity period becomes the minimum of your specified period and the block hash count. +- Chill the validator. +- Purge validator session keys. +- Unbond your tokens. -## Unique Identifiers for Extrinsics +## Chill Validator -Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. +When stepping back from validating, the first step is to chill your validator status. This action stops your validator from being considered for the next era without fully unbonding your tokens, which can be useful for temporary pauses like maintenance or planned downtime. -Key differences from traditional blockchains: +Use the `staking.chill` extrinsic to initiate this. For more guidance on chilling your node, refer to the [Pause Validating](/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/){target=\_blank} guide. You may also claim any pending staking rewards at this point. -- Transaction hashes serve only as fingerprints of transaction information. -- Multiple valid transactions can share the same hash. -- Hash uniqueness assumptions lead to serious issues. +## Purge Validator Session Keys -For example, when an account is reaped (removed due to insufficient balance) and later recreated, it resets to nonce 0, allowing identical transactions to be valid at different points: +Purging validator session keys is a critical step in removing the association between your validator account and its session keys, which ensures that your account is fully disassociated from validator activities. The `session.purgeKeys` extrinsic removes the reference to your session keys from the stash or staking proxy account that originally set them. -| Block | Extrinsic Index | Hash | Origin | Nonce | Call | Result | -|-------|----------------|------|-----------|-------|---------------------|-------------------------------| -| 100 | 0 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Account A reaped | -| 150 | 5 | 0x02 | Account B | 4 | Transfer 7 DOT to A | Account A created (nonce = 0) | -| 200 | 2 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Successful transaction | +Here are a couple of important things to know about purging keys: -Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. +- **Account used to purge keys**: Always use the same account to purge keys you originally used to set them, usually your stash or staking proxy account. Using a different account may leave an unremovable reference to the session keys on the original account, preventing its reaping. +- **Account reaping issue**: Failing to purge keys will prevent you from reaping (fully deleting) your stash account. If you attempt to transfer tokens without purging, you'll need to rebond, purge the session keys, unbond again, and wait through the unbonding period before any transfer. -Additional complexity comes from Polkadot SDK's origin abstraction. Origins can represent collectives, governance bodies, or other non-account entities that don't maintain nonces like regular accounts and might dispatch identical calls multiple times with the same hash values. Each execution occurs in different chain states with different results. +## Unbond Your Tokens -The correct way to uniquely identify an extrinsic on a Polkadot SDK-based chain is to use the block ID (height or hash) and the extrinsic index. Since the Polkadot SDK defines blocks as headers plus ordered arrays of extrinsics, the index position within a canonical block provides guaranteed uniqueness. +After chilling your node and purging session keys, the final step is to unbond your staked tokens. This action removes them from staking and begins the unbonding period (usually 28 days for Polkadot and seven days for Kusama), after which the tokens will be transferable. -## Additional Resources +To unbond tokens, go to **Network > Staking > Account Actions** on Polkadot.js Apps. Select your stash account, click on the dropdown menu, and choose **Unbond Funds**. Alternatively, you can use the `staking.unbond` extrinsic if you handle this via a staking proxy account. -For a video overview of the lifecycle of transactions and the types of transactions that exist, see the [Transaction lifecycle](https://www.youtube.com/watch?v=3pfM0GOp02c){target=\_blank} seminar from Parity Tech. +Once the unbonding period is complete, your tokens will be available for use in transactions or transfers outside of staking. --- @@ -8724,351 +5972,6 @@ The system maintains precise conversion mechanisms between: This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. ---- - -Page Title: Transactions Weights and Fees - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/ -- Summary: Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. - -# Transactions Weights and Fees - -## Introductions - -When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop the network from producing new blocks. To protect blockchain resources from being drained or overloaded, you need to manage how they are made available and how they are consumed. The resources to be aware of include: - -- Memory usage -- Storage input and output -- Computation -- Transaction and block size -- State database size - -The Polkadot SDK provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource. Two of the most important mechanisms available to block authors are weights and transaction fees. - -[Weights](/reference/glossary/#weight){target=\_blank} manage the time it takes to validate a block and characterize the time it takes to execute the calls in the block's body. By controlling the execution time a block can consume, weights set limits on storage input, output, and computation. - -Some of the weight allowed for a block is consumed as part of the block's initialization and finalization. The weight might also be used to execute mandatory inherent extrinsic calls. To help ensure blocks don’t consume too much execution time and prevent malicious users from overloading the system with unnecessary calls, weights are combined with transaction fees. - -[Transaction fees](/reference/parachains/blocks-transactions-fees/transactions/#transaction-fees){target=\_blank} provide an economic incentive to limit execution time, computation, and the number of calls required to perform operations. Transaction fees are also used to make the blockchain economically sustainable because they are typically applied to transactions initiated by users and deducted before a transaction request is executed. - -## How Fees are Calculated - -The final fee for a transaction is calculated using the following parameters: - -- **`base fee`**: This is the minimum amount a user pays for a transaction. It is declared a base weight in the runtime and converted to a fee using the [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} conversion. -- **`weight fee`**: A fee proportional to the execution time (input and output and computation) that a transaction consumes. -- **`length fee`**: A fee proportional to the encoded length of the transaction. -- **`tip`**: An optional tip to increase the transaction’s priority, giving it a higher chance to be included in the transaction queue. - -The base fee and proportional weight and length fees constitute the inclusion fee. The inclusion fee is the minimum fee that must be available for a transaction to be included in a block. - -```text -inclusion fee = base fee + weight fee + length fee -``` - -Transaction fees are withdrawn before the transaction is executed. After the transaction is executed, the weight can be adjusted to reflect the resources used. If a transaction uses fewer resources than expected, the transaction fee is corrected, and the adjusted transaction fee is deposited. - -## Using the Transaction Payment Pallet - -The [Transaction Payment pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/transaction-payment){target=\_blank} provides the basic logic for calculating the inclusion fee. You can also use the Transaction Payment pallet to: - -- Convert a weight value into a deductible fee based on a currency type using [`Config::WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank}. -- Update the fee for the next block by defining a multiplier based on the chain’s final state at the end of the previous block using [`Config::FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank}. -- Manage the withdrawal, refund, and deposit of transaction fees using [`Config::OnChargeTransaction`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.OnChargeTransaction){target=\_blank}. - -You can learn more about these configuration traits in the [Transaction Payment documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_payment/index.html){target=\_blank}. - -### Understanding the Inclusion Fee - -The formula for calculating the inclusion fee is as follows: - -```text -inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] -``` - -And then, for calculating the final fee: - -```text -final_fee = inclusion_fee + tip -``` - -In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. - -- The `base_fee` derived from the base weight covers inclusion overhead like signature verification. -- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic. -- The `weight_fee` fee is calculated using two parameters: - - The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics. - - The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity. - -To convert the weight to `Currency`, the runtime must define a `WeightToFee` struct that implements a conversion function, [`Convert`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/struct.Pallet.html#method.weight_to_fee){target=\_blank}. - -Note that the extrinsic sender is charged the inclusion fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution. - -### Accounts with an Insufficient Balance - -If an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum existential deposit—then you should ensure the transaction is canceled so that no fee is deducted and the transaction does not begin execution. - -The Polkadot SDK doesn't enforce this rollback behavior. However, this scenario would be rare because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block. - -### Fee Multipliers - -The inclusion fee formula always results in the same fee for the same input. However, weight can be dynamic and—based on how [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} is defined—the final fee can include some degree of variability. -The Transaction Payment pallet provides the [`FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank} configurable parameter to account for this variability. - -The Polkadot network inspires the default update function and implements a targeted adjustment in which a target saturation level of block weight is defined. If the previous block is more saturated, the fees increase slightly. Similarly, if the last block has fewer transactions than the target, fees are decreased by a small amount. For more information about fee multiplier adjustments, see the [Web3 Research Page](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank}. - -## Transactions with Special Requirements - -Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: - -- Bonds are a type of fee that might be returned or slashed after some on-chain event. For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior. -- Deposits are fees that might be returned later. For example, you might require users to pay a deposit to execute an operation that uses storage. The user’s deposit could be returned if a subsequent operation frees up storage. -- Burn operations are used to pay for a transaction based on its internal logic. For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased state size. -- Limits enable you to enforce constant or configurable limits on specific operations. For example, the default [Staking pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/staking){target=\_blank} only allows nominators to nominate 16 validators to limit the complexity of the validator election process. - -It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. - -## Default Weight Annotations - -All dispatchable functions in the Polkadot SDK must specify a weight. The way of doing that is using the annotation-based system that lets you combine fixed values for database read/write weight and/or fixed values based on benchmarks. The most basic example would look like this: - -```rust -#[pallet::weight(100_000)] -fn my_dispatchable() { - // ... -} -``` - -Note that the [`ExtrinsicBaseWeight`](https://crates.parity.io/frame_support/weights/constants/struct.ExtrinsicBaseWeight.html){target=\_blank} is automatically added to the declared weight to account for the costs of simply including an empty extrinsic into a block. - -### Weights and Database Read/Write Operations - -To make weight annotations independent of the deployed database backend, they are defined as a constant and then used in the annotations when expressing database accesses performed by the dispatchable: - -```rust -#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] -fn my_dispatchable() { - // ... -} -``` - -This dispatchable allows one database to read and two to write, in addition to other things that add the additional 20,000. Database access is generally every time a value declared inside the [`#[pallet::storage]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} block is accessed. However, unique accesses are counted because after a value is accessed, it is cached, and reaccessing it does not result in a database operation. That is: - -- Multiple reads of the exact value count as one read. -- Multiple writes of the exact value count as one write. -- Multiple reads of the same value, followed by a write to that value, count as one read and one write. -- A write followed by a read-only counts as one write. - -### Dispatch Classes - -Dispatches are broken into three classes: - -- Normal -- Operational -- Mandatory - -If a dispatch is not defined as `Operational` or `Mandatory` in the weight annotation, the dispatch is identified as `Normal` by default. You can specify that the dispatchable uses another class like this: - -```rust -#[pallet::dispatch((DispatchClass::Operational))] -fn my_dispatchable() { - // ... -} -``` - -This tuple notation also allows you to specify a final argument determining whether the user is charged based on the annotated weight. If you don't specify otherwise, `Pays::Yes` is assumed: - -```rust -#[pallet::dispatch(DispatchClass::Normal, Pays::No)] -fn my_dispatchable() { - // ... -} -``` - -#### Normal Dispatches - -Dispatches in this class represent normal user-triggered transactions. These types of dispatches only consume a portion of a block's total weight limit. For information about the maximum portion of a block that can be consumed for normal dispatches, see [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Normal dispatches are sent to the transaction pool. - -#### Operational Dispatches - -Unlike normal dispatches, which represent the usage of network capabilities, operational dispatches are those that provide network capabilities. Operational dispatches can consume the entire weight limit of a block. They are not bound by the [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Dispatches in this class are given maximum priority and are exempt from paying the [`length_fee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/){target=\_blank}. - -#### Mandatory Dispatches - -Mandatory dispatches are included in a block even if they cause the block to surpass its weight limit. You can only use the mandatory dispatch class for inherent transactions that the block author submits. This dispatch class is intended to represent functions in the block validation process. Because these dispatches are always included in a block regardless of the function weight, the validation process must prevent malicious nodes from abusing the function to craft valid but impossibly heavy blocks. You can typically accomplish this by ensuring that: - -- The operation performed is always light. -- The operation can only be included in a block once. - -To make it more difficult for malicious nodes to abuse mandatory dispatches, they cannot be included in blocks that return errors. This dispatch class serves the assumption that it is better to allow an overweight block to be created than not to allow any block to be created at all. - -### Dynamic Weights - -In addition to purely fixed weights and constants, the weight calculation can consider the input arguments of a dispatchable. The weight should be trivially computable from the input arguments with some basic arithmetic: - -```rust -use frame_support:: { - dispatch:: { - DispatchClass::Normal, - Pays::Yes, - }, - weights::Weight, -}; - -#[pallet::weight(FunctionOf( - |args: (&Vec,)| args.0.len().saturating_mul(10_000), - ) -] -fn handle_users(origin, calls: Vec) { - // Do something per user -} -``` - -## Post Dispatch Weight Correction - -Depending on the execution logic, a dispatchable function might consume less weight than was prescribed pre-dispatch. To correct weight, the function declares a different return type and returns its actual weight: - -```rust -#[pallet::weight(10_000 + 500_000_000)] -fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo { - let was_heavy = do_calculation(input); - - if (was_heavy) { - // None means "no correction" from the weight annotation. - Ok(None.into()) - } else { - // Return the actual weight consumed. - Ok(Some(10_000).into()) - } -} -``` - -## Custom Fees - -You can also define custom fee systems through custom weight functions or inclusion fee functions. - -### Custom Weights - -Instead of using the default weight annotations, you can create a custom weight calculation type using the weights module. The custom weight calculation type must implement the following traits: - -- [`WeighData`](https://crates.parity.io/frame_support/weights/trait.WeighData.html){target=\_blank} to determine the weight of the dispatch. -- [`ClassifyDispatch`](https://crates.parity.io/frame_support/weights/trait.ClassifyDispatch.html){target=\_blank} to determine the class of the dispatch. -- [`PaysFee`](https://crates.parity.io/frame_support/weights/trait.PaysFee.html){target=\_blank} to determine whether the sender of the dispatch pays fees. - -The Polkadot SDK then bundles the output information of the three traits into the [`DispatchInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.DispatchInfo.html){target=\_blank} struct and provides it by implementing the [`GetDispatchInfo`](https://docs.rs/frame-support/latest/frame_support/dispatch/trait.GetDispatchInfo.html){target=\_blank} for all `Call` variants and opaque extrinsic types. This is used internally by the System and Executive modules. - -`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over T, which gets resolved into the tuple of all dispatch arguments except for the origin. The following example illustrates a struct that calculates the weight as `m * len(args)`, where `m` is a given multiplier and args is the concatenated tuple of all dispatch arguments. In this example, the dispatch class is `Operational` if the transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length exceeds 10 bytes. - -```rust -struct LenWeight(u32); -impl WeighData for LenWeight { - fn weigh_data(&self, target: T) -> Weight { - let multiplier = self.0; - let encoded_len = target.encode().len() as u32; - multiplier * encoded_len - } -} - -impl ClassifyDispatch for LenWeight { - fn classify_dispatch(&self, target: T) -> DispatchClass { - let encoded_len = target.encode().len() as u32; - if encoded_len > 100 { - DispatchClass::Operational - } else { - DispatchClass::Normal - } - } -} - -impl PaysFee { - fn pays_fee(&self, target: T) -> Pays { - let encoded_len = target.encode().len() as u32; - if encoded_len > 10 { - Pays::Yes - } else { - Pays::No - } - } -} -``` - -A weight calculator function can also be coerced to the final type of the argument instead of defining it as a vague type that can be encoded. The code would roughly look like this: - -```rust -struct CustomWeight; -impl WeighData<(&u32, &u64)> for CustomWeight { - fn weigh_data(&self, target: (&u32, &u64)) -> Weight { - ... - } -} - -// given a dispatch: -#[pallet::call] -impl, I: 'static> Pallet { - #[pallet::weight(CustomWeight)] - fn foo(a: u32, b: u64) { ... } -} -``` - -In this example, the `CustomWeight` can only be used in conjunction with a dispatch with a particular signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because there aren't any assumptions about ``. - -#### Custom Inclusion Fee - -The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. - -```rust -// Assume this is the balance type -type Balance = u64; - -// Assume we want all the weights to have a `100 + 2 * w` conversion to fees -struct CustomWeightToFee; -impl WeightToFee for CustomWeightToFee { - fn convert(w: Weight) -> Balance { - let a = Balance::from(100); - let b = Balance::from(2); - let w = Balance::from(w); - a + b * w - } -} - -parameter_types! { - pub const ExtrinsicBaseWeight: Weight = 10_000_000; -} - -impl frame_system::Config for Runtime { - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; -} - -parameter_types! { - pub const TransactionByteFee: Balance = 10; -} - -impl transaction_payment::Config { - type TransactionByteFee = TransactionByteFee; - type WeightToFee = CustomWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} - -struct TargetedFeeAdjustment(sp_std::marker::PhantomData); -impl> WeightToFee for TargetedFeeAdjustment { - fn convert(multiplier: Fixed128) -> Fixed128 { - // Don't change anything. Put any fee update info here. - multiplier - } -} -``` - -## Additional Resources - -You now know the weight system, how it affects transaction fee computation, and how to specify weights for your dispatchable calls. The next step is determining the correct weight for your dispatchable operations. You can use Substrate benchmarking functions and frame-benchmarking calls to test your functions with different parameters and empirically determine the proper weight in their worst-case scenarios. - -- [Benchmark](/parachains/customize-runtime/pallet-development/benchmark-pallet/) -- [`SignedExtension`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} -- [Custom weights for the Example pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/examples/basic/src/weights.rs){target=\_blank} -- [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} - - --- Page Title: Upgrade a Validator Node @@ -9391,91 +6294,3 @@ For example, on November 19, 2024, the minimum stake backing a validator in Polk - [**Chain State Values**](https://wiki.polkadot.com/general/chain-state-values/){target=\_blank} - [**Subscan**](https://polkadot.subscan.io/validator_list?status=validator){target=\_blank} - [**Staking Dashboard**](https://staking.polkadot.cloud/#/overview){target=\_blank} - - ---- - -Page Title: XCM Tools - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/xcm-tools/ -- Summary: Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. - -# XCM Tools - -## Introduction - -As described in the [Interoperability](/develop/interoperability){target=\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem. - -As XCM is central to enabling communication between blockchains, developers need robust tools to help interact with, build, and test XCM messages. Several XCM tools simplify working with the protocol by providing libraries, frameworks, and utilities that enhance the development process, ensuring that applications built within the Polkadot ecosystem can efficiently use cross-chain functionalities. - -## Popular XCM Tools - -### Moonsong Labs XCM Tools - -[Moonsong Labs XCM Tools](https://github.com/Moonsong-Labs/xcm-tools){target=\_blank} provides a collection of scripts for managing and testing XCM operations between Polkadot SDK-based runtimes. These tools allow performing tasks like asset registration, channel setup, and XCM initialization. Key features include: - -- **Asset registration**: Registers assets, setting units per second (up-front fees), and configuring error (revert) codes. -- **XCM initializer**: Initializes XCM, sets default XCM versions, and configures revert codes for XCM-related precompiles. -- **HRMP manipulator**: Manages HRMP channel actions, including opening, accepting, or closing channels. -- **XCM-Transactor-Info-Setter**: Configures transactor information, including extra weight and fee settings. -- **Decode XCM**: Decodes XCM messages on the relay chain or parachains to help interpret cross-chain communication. - -To get started, clone the repository and install the required dependencies: - -```bash -git clone https://github.com/Moonsong-Labs/xcm-tools && -cd xcm-tools && -yarn install -``` - -For a full overview of each script, visit the [scripts](https://github.com/Moonsong-Labs/xcm-tools/tree/main/scripts){target=\_blank} directory or refer to the [official documentation](https://github.com/Moonsong-Labs/xcm-tools/blob/main/README.md){target=\_blank} on GitHub. - -### ParaSpell - -[ParaSpell](/reference/tools/paraspell/){target=\_blank} is a collection of open-source XCM tools that streamline cross-chain asset transfers and interactions across the Polkadot and Kusama ecosystems. It provides developers with an intuitive interface to build, test, and deploy interoperable dApps, featuring message composition, decoding, and practical utilities for parachain interactions that simplify debugging and cross-chain communication optimization. - -### Astar XCM Tools - -The [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks: - -- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command. -- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments. -- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs. - -To start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\_blank} and compile the xcm-tools package: - -```bash -git clone https://github.com/AstarNetwork/Astar && -cd Astar && -cargo build --release -p xcm-tools -``` - -After compiling, verify the setup with the following command: - -```bash -./target/release/xcm-tools --help -``` -For more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\_blank}. - -### Chopsticks - -The Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\_blank} about XCM. - -### Moonbeam XCM SDK - -The [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank} of the origin or destination assets or which extrinsics are used on which networks. - -The SDK consists of two main packages: - -- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem. -- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum. - -Key features include: - -- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection. -- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems. -- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality. -- **Comprehensive documentation**: Includes usage guides and API references for both packages. - -For detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\_blank}. diff --git a/.ai/categories/networks.md b/.ai/categories/networks.md index 095a99153..32021e250 100644 --- a/.ai/categories/networks.md +++ b/.ai/categories/networks.md @@ -474,440 +474,6 @@ Launch your parachain locally and start producing blocks:
    ---- - -Page Title: Blocks - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/ -- Summary: Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. - -# Blocks - -## Introduction - -In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the network. By understanding these concepts, developers can better grasp how blockchains maintain security, consistency, and performance within the Polkadot ecosystem. - -## What is a Block? - -In the Polkadot SDK, a block is a fundamental unit that encapsulates both the header and an array of transactions. The block header includes critical metadata to ensure the integrity and sequence of the blockchain. Here's a breakdown of its components: - -- **Block height**: Indicates the number of blocks created in the chain so far. -- **Parent hash**: The hash of the previous block, providing a link to maintain the blockchain's immutability. -- **Transaction root**: Cryptographic digest summarizing all transactions in the block. -- **State root**: A cryptographic digest representing the post-execution state. -- **Digest**: Additional information that can be attached to a block, such as consensus-related messages. - -Each transaction is part of a series that is executed according to the runtime's rules. The transaction root is a cryptographic digest of this series, which prevents alterations and enables succinct verification by light clients. This verification process allows light clients to confirm whether a transaction exists in a block with only the block header, avoiding downloading the entire block. - -## Block Production - -When an authoring node is authorized to create a new block, it selects transactions from the transaction queue based on priority. This step, known as block production, relies heavily on the executive module to manage the initialization and finalization of blocks. The process is summarized as follows: - -### Initialize Block - -The block initialization process begins with a series of function calls that prepare the block for transaction execution: - -1. **Call `on_initialize`**: The executive module calls the [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hook from the system pallet and other runtime pallets to prepare for the block's transactions. -2. **Coordinate runtime calls**: Coordinates function calls in the order defined by the transaction queue. -3. **Verify information**: Once [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} functions are executed, the executive module checks the parent hash in the block header and the trie root to verify information is consistent. - -### Finalize Block - -Once transactions are processed, the block must be finalized before being broadcast to the network. The finalization steps are as follows: - -1. **Call `on_finalize`**: The executive module calls the [`on_finalize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_finalize){target=\_blank} hooks in each pallet to ensure any remaining state updates or checks are completed before the block is sealed and published. -2. **Verify information**: The block's digest and storage root in the header are checked against the initialized block to ensure consistency. -3. **Call `on_idle`**: The [`on_idle`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_idle){target=\_blank} hook is triggered to process any remaining tasks using the leftover weight from the block. - -## Block Authoring and Import - -Once the block is finalized, it is gossiped to other nodes in the network. Nodes follow this procedure: - -1. **Receive transactions**: The authoring node collects transactions from the network. -2. **Validate**: Transactions are checked for validity. -3. **Queue**: Valid transactions are placed in the transaction pool for execution. -4. **Execute**: State changes are made as the transactions are executed. -5. **Publish**: The finalized block is broadcast to the network. - -### Block Import Queue - -After a block is published, other nodes on the network can import it into their chain state. The block import queue is part of the outer node in every Polkadot SDK-based node and ensures incoming blocks are valid before adding them to the node's state. - -In most cases, you don't need to know details about how transactions are gossiped or how other nodes on the network import blocks. The following traits are relevant, however, if you plan to write any custom consensus logic or want a deeper dive into the block import queue: - -- **[`ImportQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.ImportQueue.html){target=\_blank}**: The trait that defines the block import queue. -- **[`Link`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Link.html){target=\_blank}**: The trait that defines the link between the block import queue and the network. -- **[`BasicQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/struct.BasicQueue.html){target=\_blank}**: A basic implementation of the block import queue. -- **[`Verifier`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Verifier.html){target=\_blank}**: The trait that defines the block verifier. -- **[`BlockImport`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/block_import/trait.BlockImport.html){target=\_blank}**: The trait that defines the block import process. - -These traits govern how blocks are validated and imported across the network, ensuring consistency and security. - -## Additional Resources - -To learn more about the block structure in the Polkadot SDK runtime, see the [`Block` reference](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.Block.html){target=\_blank} entry in the Rust Docs. - - ---- - -Page Title: Chain Data - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/chain-data/ -- Summary: Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. - -# Chain Data - -## Introduction - -Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you can ensure seamless communication between your applications and the blockchain. - -## Application Development - -You might not be directly involved in building frontend applications as a blockchain developer. However, most applications that run on a blockchain require some form of frontend or user-facing client to enable users or other programs to access and modify the data that the blockchain stores. For example, you might develop a browser-based, mobile, or desktop application that allows users to submit transactions, post articles, view their assets, or track previous activity. The backend for that application is configured in the runtime logic for your blockchain, but the frontend client makes the runtime features accessible to your users. - -For your custom chain to be useful to others, you'll need to provide a client application that allows users to view, interact with, or update information that the blockchain keeps track of. In this article, you'll learn how to expose information about your runtime so that client applications can use it, see examples of the information exposed, and explore tools and libraries that use it. - -## Understand Metadata - -Polkadot SDK-based blockchain networks are designed to expose their runtime information, allowing developers to learn granular details regarding pallets, RPC calls, and runtime APIs. The metadata also exposes their related documentation. The chain's metadata is [SCALE-encoded](/reference/parachains/data-encoding/){target=\_blank}, allowing for the development of browser-based, mobile, or desktop applications to support the chain's runtime upgrades seamlessly. It is also possible to develop applications compatible with multiple Polkadot SDK-based chains simultaneously. - -## Expose Runtime Information as Metadata - -To interact with a node or the state of the blockchain, you need to know how to connect to the chain and access the exposed runtime features. This interaction involves a Remote Procedure Call (RPC) through a node endpoint address, commonly through a secure web socket connection. - -An application developer typically needs to know the contents of the runtime logic, including the following details: - -- Version of the runtime the application is connecting to. -- Supported APIs. -- Implemented pallets. -- Defined functions and corresponding type signatures. -- Defined custom types. -- Exposed parameters users can set. - -As the Polkadot SDK is modular and provides a composable framework for building blockchains, there are limitless opportunities to customize the schema of properties. Each runtime can be configured with its properties, including function calls and types, which can be changed over time with runtime upgrades. - -The Polkadot SDK enables you to generate the runtime metadata schema to capture information unique to a runtime. The metadata for a runtime describes the pallets in use and types defined for a specific runtime version. The metadata includes information about each pallet's storage items, functions, events, errors, and constants. The metadata also provides type definitions for any custom types included in the runtime. - -Metadata provides a complete inventory of a chain's runtime. It is key to enabling client applications to interact with the node, parse responses, and correctly format message payloads sent back to that chain. - -## Generate Metadata - -To efficiently use the blockchain's networking resources and minimize the data transmitted over the network, the metadata schema is encoded using the [Parity SCALE Codec](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank}. This encoding is done automatically through the [`scale-info`](https://docs.rs/scale-info/latest/scale_info/){target=\_blank}crate. - -At a high level, generating the metadata involves the following steps: - -1. The pallets in the runtime logic expose callable functions, types, parameters, and documentation that need to be encoded in the metadata. -2. The `scale-info` crate collects type information for the pallets in the runtime, builds a registry of the pallets that exist in a particular runtime, and the relevant types for each pallet in the registry. The type information is detailed enough to enable encoding and decoding for every type. -3. The [`frame-metadata`](https://github.com/paritytech/frame-metadata){target=\_blank} crate describes the structure of the runtime based on the registry provided by the `scale-info` crate. -4. Nodes provide the RPC method `state_getMetadata` to return a complete description of all the types in the current runtime as a hex-encoded vector of SCALE-encoded bytes. - -## Retrieve Runtime Metadata - -The type information provided by the metadata enables applications to communicate with nodes using different runtime versions and across chains that expose different calls, events, types, and storage items. The metadata also allows libraries to generate a substantial portion of the code needed to communicate with a given node, enabling libraries like [`subxt`](https://github.com/paritytech/subxt){target=\_blank} to generate frontend interfaces that are specific to a target chain. - -### Use Polkadot.js - -Visit the [Polkadot.js Portal](https://polkadot.js.org/apps/#/rpc){target=\_blank} and select the **Developer** dropdown in the top banner. Select **RPC Calls** to make the call to request metadata. Follow these steps to make the RPC call: - -1. Select **state** as the endpoint to call. -2. Select **`getMetadata(at)`** as the method to call. -3. Click **Submit RPC call** to submit the call and return the metadata in JSON format. - -### Use Curl - -You can fetch the metadata for the network by calling the node's RPC endpoint. This request returns the metadata in bytes rather than human-readable JSON: - -```sh -curl -H "Content-Type: application/json" \ --d '{"id":1, "jsonrpc":"2.0", "method": "state_getMetadata"}' \ -https://rpc.polkadot.io - -``` - -### Use Subxt - -[`subxt`](https://github.com/paritytech/subxt){target=\_blank} may also be used to fetch the metadata of any data in a human-readable JSON format: - -```sh -subxt metadata --url wss://rpc.polkadot.io --format json > spec.json -``` - -Another option is to use the [`subxt` explorer web UI](https://paritytech.github.io/subxt-explorer/#/){target=\_blank}. - -## Client Applications and Metadata - -The metadata exposes the expected way to decode each type, meaning applications can send, retrieve, and process application information without manual encoding and decoding. Client applications must use the [SCALE codec library](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank} to encode and decode RPC payloads to use the metadata. Client applications use the metadata to interact with the node, parse responses, and format message payloads sent to the node. - -## Metadata Format - -Although the SCALE-encoded bytes can be decoded using the `frame-metadata` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} libraries, there are other tools, such as `subxt` and the Polkadot-JS API, that can convert the raw data to human-readable JSON format. - -The types and type definitions included in the metadata returned by the `state_getMetadata` RPC call depend on the runtime's metadata version. - -In general, the metadata includes the following information: - -- A constant identifying the file as containing metadata. -- The version of the metadata format used in the runtime. -- Type definitions for all types used in the runtime and generated by the `scale-info` crate. -- Pallet information for the pallets included in the runtime in the order that they are defined in the `construct_runtime` macro. - -!!!tip - Depending on the frontend library used (such as the [Polkadot API](https://papi.how/){target=\_blank}), they may format the metadata differently than the raw format shown. - -The following example illustrates a condensed and annotated section of metadata decoded and converted to JSON: - -```json -[ - 1635018093, - { - "V14": { - "types": { - "types": [{}] - }, - "pallets": [{}], - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [{}] - }, - "ty": 141 - } - } -] - -``` - -The constant `1635018093` is a magic number that identifies the file as a metadata file. The rest of the metadata is divided into the `types`, `pallets`, and `extrinsic` sections: - -- The `types` section contains an index of the types and information about each type's type signature. -- The `pallets` section contains information about each pallet in the runtime. -- The `extrinsic` section describes the type identifier and transaction format version that the runtime uses. - -Different extrinsic versions can have varying formats, especially when considering [signed transactions](/reference/parachains/blocks-transactions-fees/transactions/#signed-transactions){target=\_blank}. - -### Pallets - -The following is a condensed and annotated example of metadata for a single element in the `pallets` array (the [`sudo`](https://paritytech.github.io/polkadot-sdk/master/pallet_sudo/index.html){target=\_blank} pallet): - -```json -{ - "name": "Sudo", - "storage": { - "prefix": "Sudo", - "entries": [ - { - "name": "Key", - "modifier": "Optional", - "ty": { - "Plain": 0 - }, - "default": [0], - "docs": ["The `AccountId` of the sudo key."] - } - ] - }, - "calls": { - "ty": 117 - }, - "event": { - "ty": 42 - }, - "constants": [], - "error": { - "ty": 124 - }, - "index": 8 -} - -``` - -Every element metadata contains the name of the pallet it represents and information about its storage, calls, events, and errors. You can look up details about the definition of the calls, events, and errors by viewing the type index identifier. The type index identifier is the `u32` integer used to access the type information for that item. For example, the type index identifier for calls in the Sudo pallet is 117. If you view information for that type identifier in the `types` section of the metadata, it provides information about the available calls, including the documentation for each call. - -For example, the following is a condensed excerpt of the calls for the Sudo pallet: - -```json -{ - "id": 117, - "type": { - "path": ["pallet_sudo", "pallet", "Call"], - "params": [ - { - "name": "T", - "type": null - } - ], - "def": { - "variant": { - "variants": [ - { - "name": "sudo", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 0, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "sudo_unchecked_weight", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - }, - { - "name": "weight", - "type": 8, - "typeName": "Weight" - } - ], - "index": 1, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "set_key", - "fields": [ - { - "name": "new", - "type": 103, - "typeName": "AccountIdLookupOf" - } - ], - "index": 2, - "docs": [ - "Authenticates current sudo key, sets the given AccountId (`new`) as the new sudo" - ] - }, - { - "name": "sudo_as", - "fields": [ - { - "name": "who", - "type": 103, - "typeName": "AccountIdLookupOf" - }, - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 3, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Signed` origin from a given account" - ] - } - ] - } - } - } -} - -``` - -For each field, you can access type information and metadata for the following: - -- **Storage metadata**: Provides the information required to enable applications to get information for specific storage items. -- **Call metadata**: Includes information about the runtime calls defined by the `#[pallet]` macro including call names, arguments and documentation. -- **Event metadata**: Provides the metadata generated by the `#[pallet::event]` macro, including the name, arguments, and documentation for each pallet event. -- **Constants metadata**: Provides metadata generated by the `#[pallet::constant]` macro, including the name, type, and hex-encoded value of the constant. -- **Error metadata**: Provides metadata generated by the `#[pallet::error]` macro, including the name and documentation for each pallet error. - -!!!tip - Type identifiers change from time to time, so you should avoid relying on specific type identifiers in your applications. - -### Extrinsic - -The runtime generates extrinsic metadata and provides useful information about transaction format. When decoded, the metadata contains the transaction version and the list of signed extensions. - -For example: - -```json -{ - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [ - { - "identifier": "CheckNonZeroSender", - "ty": 132, - "additional_signed": 41 - }, - { - "identifier": "CheckSpecVersion", - "ty": 133, - "additional_signed": 4 - }, - { - "identifier": "CheckTxVersion", - "ty": 134, - "additional_signed": 4 - }, - { - "identifier": "CheckGenesis", - "ty": 135, - "additional_signed": 11 - }, - { - "identifier": "CheckMortality", - "ty": 136, - "additional_signed": 11 - }, - { - "identifier": "CheckNonce", - "ty": 138, - "additional_signed": 41 - }, - { - "identifier": "CheckWeight", - "ty": 139, - "additional_signed": 41 - }, - { - "identifier": "ChargeTransactionPayment", - "ty": 140, - "additional_signed": 41 - } - ] - }, - "ty": 141 -} - -``` - -The type system is [composite](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank}, meaning each type identifier contains a reference to a specific type or to another type identifier that provides information about the associated primitive types. - -For example, you can encode the `BitVec` type, but to decode it properly, you must know the types used for the `Order` and `Store` types. To find type information for `Order` and `Store`, you can use the path in the decoded JSON to locate their type identifiers. - -## Included RPC APIs - -A standard node comes with the following APIs to interact with a node: - -- **[`AuthorApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/author/trait.AuthorApiServer.html){target=\_blank}**: Make calls into a full node, including authoring extrinsics and verifying session keys. -- **[`ChainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/chain/trait.ChainApiServer.html){target=\_blank}**: Retrieve block header and finality information. -- **[`OffchainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/offchain/trait.OffchainApiServer.html){target=\_blank}**: Make RPC calls for off-chain workers. -- **[`StateApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/state/trait.StateApiServer.html){target=\_blank}**: Query information about on-chain state such as runtime version, storage items, and proofs. -- **[`SystemApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/system/trait.SystemApiServer.html){target=\_blank}**: Retrieve information about network state, such as connected peers and node roles. - -## Additional Resources - -The following tools can help you locate and decode metadata: - -- [Subxt Explorer](https://paritytech.github.io/subxt-explorer/#/){target=\_blank} -- [Metadata Portal 🌗](https://github.com/paritytech/metadata-portal){target=\_blank} -- [De[code] Sub[strate]](https://github.com/paritytech/desub){target=\_blank} - - --- Page Title: Contract Deployment @@ -1019,280 +585,6 @@ Both REVM and PolkaVM deployments may show significant differences between gas e Both backends support contract deployment effectively, with REVM offering drop-in Ethereum compatibility and PolkaVM providing a more structured two-step approach. For the majority of use cases—deploying standard contracts like tokens or applications—both backends work seamlessly. Advanced patterns like factory contracts may require adjustment for PolkaVM, but these adaptations are straightforward with proper planning. ---- - -Page Title: Cryptography - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/cryptography/ -- Summary: A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. - -# Cryptography - -## Introduction - -Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem. - -## Hash Functions - -Hash functions are fundamental to blockchain technology, creating a unique digital fingerprint for any piece of data, including simple text, images, or any other form of file. They map input data of any size to a fixed-size output (typically 32 bytes) using complex mathematical operations. Hashing is used to verify data integrity, create digital signatures, and provide a secure way to store passwords. This form of mapping is known as the ["pigeonhole principle,"](https://en.wikipedia.org/wiki/Pigeonhole_principle){target=\_blank} it is primarily implemented to efficiently and verifiably identify data from large sets. - -### Key Properties of Hash Functions - -- **Deterministic**: The same input always produces the same output. -- **Quick computation**: It's easy to calculate the hash value for any given input. -- **Pre-image resistance**: It's infeasible to generate the input data from its hash. -- **Small changes in input yield large changes in output**: Known as the ["avalanche effect"](https://en.wikipedia.org/wiki/Avalanche_effect){target=\_blank}. -- **Collision resistance**: The probabilities are extremely low to find two different inputs with the same hash. - -### Blake2 - -The Polkadot SDK utilizes Blake2, a state-of-the-art hashing method that offers: - -- Equal or greater security compared to [SHA-2](https://en.wikipedia.org/wiki/SHA-2){target=\_blank}. -- Significantly faster performance than other algorithms. - -These properties make Blake2 ideal for blockchain systems, reducing sync times for new nodes and lowering the resources required for validation. For detailed technical specifications about Blake2, see the [official Blake2 paper](https://www.blake2.net/blake2.pdf){target=\_blank}. - -## Types of Cryptography - -There are two different ways that cryptographic algorithms are implemented: symmetric cryptography and asymmetric cryptography. - -### Symmetric Cryptography - -Symmetric encryption is a branch of cryptography that isn't based on one-way functions, unlike asymmetric cryptography. It uses the same cryptographic key to encrypt plain text and decrypt the resulting ciphertext. - -Symmetric cryptography is a type of encryption that has been used throughout history, such as the Enigma Cipher and the Caesar Cipher. It is still widely used today and can be found in Web2 and Web3 applications alike. There is only one single key, and a recipient must also have access to it to access the contained information. - -#### Advantages {: #symmetric-advantages } - -- Fast and efficient for large amounts of data. -- Requires less computational power. - -#### Disadvantages {: #symmetric-disadvantages } - -- Key distribution can be challenging. -- Scalability issues in systems with many users. - -### Asymmetric Cryptography - -Asymmetric encryption is a type of cryptography that uses two different keys, known as a keypair: a public key, used to encrypt plain text, and a private counterpart, used to decrypt the ciphertext. - -The public key encrypts a fixed-length message that can only be decrypted with the recipient's private key and, sometimes, a set password. The public key can be used to cryptographically verify that the corresponding private key was used to create a piece of data without compromising the private key, such as with digital signatures. This has obvious implications for identity, ownership, and properties and is used in many different protocols across Web2 and Web3. - -#### Advantages {: #asymmetric-advantages } - -- Solves the key distribution problem. -- Enables digital signatures and secure key exchange. - -#### Disadvantages {: #asymmetric-disadvantages } - -- Slower than symmetric encryption. -- Requires more computational resources. - -### Trade-offs and Compromises - -Symmetric cryptography is faster and requires fewer bits in the key to achieve the same level of security that asymmetric cryptography provides. However, it requires a shared secret before communication can occur, which poses issues to its integrity and a potential compromise point. On the other hand, asymmetric cryptography doesn't require the secret to be shared ahead of time, allowing for far better end-user security. - -Hybrid symmetric and asymmetric cryptography is often used to overcome the engineering issues of asymmetric cryptography, as it is slower and requires more bits in the key to achieve the same level of security. It encrypts a key and then uses the comparatively lightweight symmetric cipher to do the "heavy lifting" with the message. - -## Digital Signatures - -Digital signatures are a way of verifying the authenticity of a document or message using asymmetric keypairs. They are used to ensure that a sender or signer's document or message hasn't been tampered with in transit, and for recipients to verify that the data is accurate and from the expected sender. - -Signing digital signatures only requires a low-level understanding of mathematics and cryptography. For a conceptual example -- when signing a check, it is expected that it cannot be cashed multiple times. This isn't a feature of the signature system but rather the check serialization system. The bank will check that the serial number on the check hasn't already been used. Digital signatures essentially combine these two concepts, allowing the signature to provide the serialization via a unique cryptographic fingerprint that cannot be reproduced. - -Unlike pen-and-paper signatures, knowledge of a digital signature cannot be used to create other signatures. Digital signatures are often used in bureaucratic processes, as they are more secure than simply scanning in a signature and pasting it onto a document. - -Polkadot SDK provides multiple different cryptographic schemes and is generic so that it can support anything that implements the [`Pair` trait](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Pair.html){target=\_blank}. - -### Example of Creating a Digital Signature - -The process of creating and verifying a digital signature involves several steps: - -1. The sender creates a hash of the message. -2. The hash is encrypted using the sender's private key, creating the signature. -3. The message and signature are sent to the recipient. -4. The recipient decrypts the signature using the sender's public key. -5. The recipient hashes the received message and compares it to the decrypted hash. - -If the hashes match, the signature is valid, confirming the message's integrity and the sender's identity. - -## Elliptic Curve - -Blockchain technology requires the ability to have multiple keys creating a signature for block proposal and validation. To this end, Elliptic Curve Digital Signature Algorithm (ECDSA) and Schnorr signatures are two of the most commonly used methods. While ECDSA is a far simpler implementation, Schnorr signatures are more efficient when it comes to multi-signatures. - -Schnorr signatures bring some noticeable features over the ECDSA/EdDSA schemes: - -- It is better for hierarchical deterministic key derivations. -- It allows for native multi-signature through [signature aggregation](https://bitcoincore.org/en/2017/03/23/schnorr-signature-aggregation/){target=\_blank}. -- It is generally more resistant to misuse. - -One sacrifice that is made when using Schnorr signatures over ECDSA is that both require 64 bytes, but only ECDSA signatures communicate their public key. - -### Various Implementations - -- **[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm){target=\_blank}**: Polkadot SDK provides an ECDSA signature scheme using the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1){target=\_blank} curve. This is the same cryptographic algorithm used to secure [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin){target=\_blank} and [Ethereum](https://en.wikipedia.org/wiki/Ethereum){target=\_blank}. - -- **[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519){target=\_blank}**: An EdDSA signature scheme using [Curve25519](https://en.wikipedia.org/wiki/Curve25519){target=\_blank}. It is carefully engineered at several levels of design and implementation to achieve very high speeds without compromising security. - -- **[SR25519](https://research.web3.foundation/Polkadot/security/keys/accounts-more){target=\_blank}**: Based on the same underlying curve as Ed25519. However, it uses Schnorr signatures instead of the EdDSA scheme. - - ---- - -Page Title: Data Encoding - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/data-encoding/ -- Summary: SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. - -# Data Encoding - -## Introduction - -The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data. - -The SCALE codec enables communication between the runtime and the outer node. This mechanism is designed for high-performance, copy-free data encoding and decoding in resource-constrained environments like the Polkadot SDK [Wasm runtime](/develop/parachains/deployment/build-deterministic-runtime/#introduction){target=\_blank}. - -It is not self-describing, meaning the decoding context must fully know the encoded data types. - -Parity's libraries utilize the [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} crate (a Rust implementation of the SCALE codec) to handle encoding and decoding for interactions between RPCs and the runtime. - -The `codec` mechanism is ideal for Polkadot SDK-based chains because: - -- It is lightweight compared to generic serialization frameworks like [`serde`](https://serde.rs/){target=\_blank}, which add unnecessary bulk to binaries. -- It doesn’t rely on Rust’s `libstd`, making it compatible with `no_std` environments like Wasm runtime. -- It integrates seamlessly with Rust, allowing easy derivation of encoding and decoding logic for new types using `#[derive(Encode, Decode)]`. - -Defining a custom encoding scheme in the Polkadot SDK-based chains, rather than using an existing Rust codec library, is crucial for enabling cross-platform and multi-language support. - -## SCALE Codec - -The codec is implemented using the following traits: - -- [`Encode`](#encode) -- [`Decode`](#decode) -- [`CompactAs`](#compactas) -- [`HasCompact`](#hascompact) -- [`EncodeLike`](#encodelike) - -### Encode - -The [`Encode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Encode.html){target=\_blank} trait handles data encoding into SCALE format and includes the following key functions: - -- **`size_hint(&self) -> usize`**: Estimates the number of bytes required for encoding to prevent multiple memory allocations. This should be inexpensive and avoid complex operations. Optional if the size isn’t known. -- **`encode_to(&self, dest: &mut T)`**: Encodes the data, appending it to a destination buffer. -- **`encode(&self) -> Vec`**: Encodes the data and returns it as a byte vector. -- **`using_encoded R>(&self, f: F) -> R`**: Encodes the data and passes it to a closure, returning the result. -- **`encoded_size(&self) -> usize`**: Calculates the encoded size. Should be used when the encoded data isn’t required. - -!!!tip - For best performance, value types should override `using_encoded`, and allocating types should override `encode_to`. It's recommended to implement `size_hint` for all types where possible. - -### Decode - -The [`Decode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Decode.html){target=\_blank} trait handles decoding SCALE-encoded data back into the appropriate types: - -- **`fn decode(value: &mut I) -> Result`**: Decodes data from the SCALE format, returning an error if decoding fails. - -### CompactAs - -The [`CompactAs`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.CompactAs.html){target=\_blank} trait wraps custom types for compact encoding: - -- **`encode_as(&self) -> &Self::As`**: Encodes the type as a compact type. -- **`decode_from(_: Self::As) -> Result`**: decodes from a compact encoded type. - -### HasCompact - -The [`HasCompact`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.HasCompact.html){target=\_blank} trait indicates a type supports compact encoding. - -### EncodeLike - -The [`EncodeLike`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.EncodeLike.html){target=\_blank} trait is used to ensure multiple types that encode similarly are accepted by the same function. When using `derive`, it is automatically implemented. - -### Data Types - -The table below outlines how the Rust implementation of the Parity SCALE codec encodes different data types. - -| Type | Description | Example SCALE Decoded Value | SCALE Encoded Value | -|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| -| Boolean | Boolean values are encoded using the least significant bit of a single byte. | `false` / `true` | `0x00` / `0x01` | -| Compact/general integers | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2^536) and is more efficient at encoding most values than the fixed-width version. | `unsigned integer 0` / `unsigned integer 1` / `unsigned integer 42` / `unsigned integer 69` / `unsigned integer 65535` / `BigInt(100000000000000)` | `0x00` / `0x04` / `0xa8` / `0x1501` / `0xfeff0300` / `0x0b00407a10f35a` | -| Enumerations (tagged-unions) | A fixed number of variants, each mutually exclusive and potentially implying a further value or series of values. Encoded as the first byte identifying the index of the variant that the value is. Any further bytes are used to encode any data that the variant implies. Thus, no more than 256 variants are supported. | `Int(42)` and `Bool(true)` where `enum IntOrBool { Int(u8), Bool(bool) }` | `0x002a` and `0x0101` | -| Fixed-width integers | Basic integers are encoded using a fixed-width little-endian (LE) format. | `signed 8-bit integer 69` / `unsigned 16-bit integer 42` / `unsigned 32-bit integer 16777215` | `0x45` / `0x2a00` / `0xffffff00` | -| Options | One or zero values of a particular type. | `Some` / `None` | `0x01` followed by the encoded value / `0x00` | -| Results | Results are commonly used enumerations which indicate whether certain operations were successful or unsuccessful. | `Ok(42)` / `Err(false)` | `0x002a` / `0x0100` | -| Strings | Strings are Vectors of bytes (Vec) containing a valid UTF8 sequence. | | | -| Structs | For structures, the values are named, but that is irrelevant for the encoding (names are ignored - only order matters). | `SortedVecAsc::from([3, 5, 2, 8])` | `[3, 2, 5, 8] ` | -| Tuples | A fixed-size series of values, each with a possibly different but predetermined and fixed type. This is simply the concatenation of each encoded value. | Tuple of compact unsigned integer and boolean: `(3, false)` | `0x0c00` | -| Vectors (lists, series, sets) | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. | Vector of unsigned `16`-bit integers: `[4, 8, 15, 16, 23, 42]` | `0x18040008000f00100017002a00` | - -## Encode and Decode Rust Trait Implementations - -Here's how the `Encode` and `Decode` traits are implemented: - - -```rust -use parity_scale_codec::{Encode, Decode}; - -[derive(Debug, PartialEq, Encode, Decode)] -enum EnumType { - #[codec(index = 15)] - A, - B(u32, u64), - C { - a: u32, - b: u64, - }, -} - -let a = EnumType::A; -let b = EnumType::B(1, 2); -let c = EnumType::C { a: 1, b: 2 }; - -a.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x0f"); -}); - -b.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -c.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -let mut da: &[u8] = b"\x0f"; -assert_eq!(EnumType::decode(&mut da).ok(), Some(a)); - -let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut db).ok(), Some(b)); - -let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut dc).ok(), Some(c)); - -let mut dz: &[u8] = &[0]; -assert_eq!(EnumType::decode(&mut dz).ok(), None); -``` - -## SCALE Codec Libraries - -Several SCALE codec implementations are available in various languages. Here's a list of them: - -- **AssemblyScript**: [`LimeChain/as-scale-codec`](https://github.com/LimeChain/as-scale-codec){target=\_blank} -- **C**: [`MatthewDarnell/cScale`](https://github.com/MatthewDarnell/cScale){target=\_blank} -- **C++**: [`qdrvm/scale-codec-cpp`](https://github.com/qdrvm/scale-codec-cpp){target=\_blank} -- **JavaScript**: [`polkadot-js/api`](https://github.com/polkadot-js/api){target=\_blank} -- **Dart**: [`leonardocustodio/polkadart`](https://github.com/leonardocustodio/polkadart){target=\_blank} -- **Haskell**: [`airalab/hs-web3`](https://github.com/airalab/hs-web3/tree/master/packages/scale){target=\_blank} -- **Golang**: [`itering/scale.go`](https://github.com/itering/scale.go){target=\_blank} -- **Java**: [`splix/polkaj`](https://github.com/splix/polkaj){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **Ruby**: [` wuminzhe/scale_rb`](https://github.com/wuminzhe/scale_rb){target=\_blank} -- **TypeScript**: [`parity-scale-codec-ts`](https://github.com/tjjfvi/subshape){target=\_blank}, [`scale-ts`](https://github.com/unstoppablejs/unstoppablejs/tree/main/packages/scale-ts#scale-ts){target=\_blank}, [`soramitsu/scale-codec-js-library`](https://github.com/soramitsu/scale-codec-js-library){target=\_blank}, [`subsquid/scale-codec`](https://github.com/subsquid/squid-sdk/tree/master/substrate/scale-codec){target=\_blank} - - --- Page Title: Deploy an ERC-20 to Polkadot Hub @@ -2375,370 +1667,130 @@ From here, follow the quick starts to get connected, iterate locally with your p --- -Page Title: Glossary +Page Title: Get Started with XCM -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md -- Canonical (HTML): https://docs.polkadot.com/reference/glossary/ -- Summary: Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ +- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. -# Glossary +# Get Started with XCM -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. +## Introduction -Additional glossaries from around the ecosystem you might find helpful: +Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. -- [Polkadot Wiki Glossary](https://wiki.polkadot.com/general/glossary){target=\_blank} -- [Polkadot SDK Glossary](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/glossary/index.html){target=\_blank} +With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. -## Authority - -The role in a blockchain that can participate in consensus mechanisms. - -- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final. -- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author). - -Authority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol. - -## Authority Round (Aura) - -A deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol. - -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. - -## Blind Assignment of Blockchain Extension (BABE) - -A [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block. - -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. - -## Block Author - -The node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_. - -## Byzantine Fault Tolerance (BFT) - -The ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack. - -### Byzantine Failure - -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. - -### Practical Byzantine Fault Tolerance (pBFT) - -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. - -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. - -### Preimage - -A preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\_blank}, the output, the hash, cannot be used to reveal the input, the preimage. - -## Call - -In the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object. - -## Chain Specification - -A chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains. - -## Collator - -An [author](#block-author) of a [parachain](#parachain) network. -They aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus). - -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. - -## Collective - -Most often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network. - -## Consensus - -Consensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship. - -See also [hybrid consensus](#hybrid-consensus). +## Messaging Format -## Consensus Algorithm +XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. -Ensures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft). +XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. -Consensus algorithms are generally concerned with ensuring two properties: +## The Four Principles of XCM -- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. -- **Liveness**: Indicating the ability of the chain to keep progressing. +XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: -## Consensus Engine +- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. +- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. +- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. +- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. -The node subsystem responsible for consensus tasks. +These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. -For detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} blog series. +## The XCM Tech Stack -See also [hybrid consensus](#hybrid-consensus). +![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) -## Coretime +The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. +## Core Functionalities of XCM -On-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety. +XCM enhances cross-consensus communication by introducing several powerful features: -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank}. +- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. +- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. +- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. -## Development Phrase +The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. +## XCM Example -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: +The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). +```rust +let message = Xcm(vec![ + WithdrawAsset((Here, amount).into()), + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } +]); ``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk -``` - -Many tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`. - -## Digest - -An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: - -- [Light clients](#light-client) for chain synchronization. -- Consensus engines for block verification. -- The runtime itself, in the case of pre-runtime digests. - -## Dispatchable - -Function objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations. - -## Events - -A means of recording that some particular [state](#state) transition happened. - -In the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization. - -## Executor - -A means of executing a function call in a given [runtime](#runtime) with a set of dependencies. -There are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_. - -- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes. - -- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain. - -## Existential Deposit - -The minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. - -If an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\_blank} to drop its references to that account. - -If the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\_blank}. - -## Extrinsic - -A general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder. - -It is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). - -For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. - -## Fork Choice Rule/Strategy - -A fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\_blank}, in which the chain with the most blocks is selected. - -## FRAME (Framework for Runtime Aggregation of Modularized Entities) - -Enables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes. - -[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank} - -## Full Node - -A node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization. - -## Genesis Configuration - -A mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file. - -## GRANDPA - -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. - -The [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\_blank}. - -## Header - -A structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization. - -## Hybrid Consensus - -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. - -Hybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa). - -## Inherent Transactions - -A special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block. - -Only the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified. - -## JSON-RPC - -A stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON. - -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. - -## Keystore - -A subsystem for managing keys for the purpose of producing new blocks. - -## Kusama - -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. - -Kusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\_blank} network and is referred to as [Polkadot's "wild cousin."](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\_blank}. - -As a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation. - -## libp2p - -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). - -Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. - -## Light Client - -A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. - -A light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\_blank} server, enabling blockchain users to interact with the network. -## Metadata - -Data that provides information about one or more aspects of a system. -The metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system. - -## Nominated Proof of Stake (NPoS) - -A method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes. - -## Oracle - -An entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services. - -## Origin - -A [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\_blank}. - -## Pallet - -A module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime). -Pallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item). - -## Parachain - -A parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_. -You can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\_blank}. - -## Paseo - -Paseo TestNet provisions testing on Polkadot's "production" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing. - -## Polkadot - -The [Polkadot network](https://polkadot.com/){target=\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain). - -## Polkadot Cloud - -Polkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance. - -## Polkadot Hub - -Polkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3. - -## PolkaVM - -PolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution. - -## Relay Chain - -Relay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another. - -## Rococo - -A [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead. - -## Runtime - -The runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function. - -## Slot - -A fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block. - -## Sovereign Account - -The unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem. - -The sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier. - -## SS58 Address Format - -A public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain - -The [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks - -## State Transition Function (STF) - -The logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime). - -## Storage Item - -[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime). -Learn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\_blank} reference document in the Polkadot SDK. - -## Substrate - -A flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\_blank}. - -## Transaction - -An [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}. - -## Transaction Era - -A definable period expressed as a range of block numbers during which a transaction can be included in a block. -Transaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero. - -## Trie (Patricia Merkle Tree) +The message consists of three instructions described as follows: -A data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set. +- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. -In Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays. + ```rust + WithdrawAsset((Here, amount).into()), + ``` -## Validator + - **`Here`**: The native parachain token. + - **`amount`**: The number of tokens that are transferred. -A validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance. + The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. -## WebAssembly (Wasm) +- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. + ```rust + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + ``` -[Wasm](https://webassembly.org/){target=\_blank} can be compiled from many languages, including -the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state. + - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. + - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. -## Weight +- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. -A convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block. -Polkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware. + ```rust + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } + ``` -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: + - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. + +This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. -- Block construction -- Network propagation -- Import and verification +## Overview -By defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements. +XCM revolutionizes cross-chain communication by enabling use cases such as: -## Westend +- Token transfers between blockchains. +- Asset locking for cross-chain smart contract interactions. +- Remote execution of functions on other blockchains. -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. +These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. --- @@ -3165,258 +2217,60 @@ To stop the node, press `Control-C` in the terminal. --- -Page Title: Interoperability +Page Title: JSON-RPC APIs -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/interoperability/ -- Summary: Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ +- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. -# Interoperability +# JSON-RPC APIs +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions. - -Polkadot’s design ensures that blockchains can transcend their individual limitations by working together as part of a unified system. This cooperative architecture is what sets Polkadot apart in the blockchain landscape. - -## Why Interoperability Matters - -The blockchain ecosystem is inherently fragmented. Different blockchains excel in specialized domains such as finance, gaming, or supply chain management, but these chains function in isolation without interoperability. This lack of connectivity stifles the broader utility of blockchain technology. - -Interoperability solves this problem by enabling blockchains to: - -- **Collaborate across networks**: Chains can interact to share assets, functionality, and data, creating synergies that amplify their individual strengths. -- **Achieve greater scalability**: Specialized chains can offload tasks to others, optimizing performance and resource utilization. -- **Expand use-case potential**: Cross-chain applications can leverage features from multiple blockchains, unlocking novel user experiences and solutions. - -In the Polkadot ecosystem, interoperability transforms a collection of isolated chains into a cohesive, efficient network, pushing the boundaries of what blockchains can achieve together. - -## Key Mechanisms for Interoperability - -At the core of Polkadot's cross-chain collaboration are foundational technologies designed to break down barriers between networks. These mechanisms empower blockchains to communicate, share resources, and operate as a cohesive ecosystem. - -### Cross-Consensus Messaging (XCM): The Backbone of Communication +Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. -Polkadot's Cross-Consensus Messaging (XCM) is the standard framework for interaction between parachains, relay chains, and, eventually, external blockchains. XCM provides a trustless, secure messaging format for exchanging assets, sharing data, and executing cross-chain operations. +This guide uses the Polkadot Hub TestNet endpoint: -Through XCM, decentralized applications can: +```text +https://testnet-passet-hub-eth-rpc.polkadot.io +``` -- Transfer tokens and other assets across chains. -- Coordinate complex workflows that span multiple blockchains. -- Enable seamless user experiences where underlying blockchain differences are invisible. -- XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem. +## Available Methods -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. +### eth_accounts -### Bridges: Connecting External Networks +Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. -While XCM enables interoperability within the Polkadot ecosystem, bridges extend this functionality to external blockchains such as Ethereum and Bitcoin. By connecting these networks, bridges allow Polkadot-based chains to access external liquidity, additional functionalities, and broader user bases. +**Parameters**: -With bridges, developers and users gain the ability to: +None. -- Integrate external assets into Polkadot-based applications. -- Combine the strengths of Polkadot’s scalability with the liquidity of other networks. -- Facilitate accurate multi-chain applications that transcend ecosystem boundaries. +**Example**: -For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. +```bash title="eth_accounts" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_accounts", + "params":[], + "id":1 +}' +``` -## The Polkadot Advantage +--- -Polkadot was purpose-built for interoperability. Unlike networks that add interoperability as an afterthought, Polkadot integrates it as a fundamental design principle. This approach offers several distinct advantages: +### eth_blockNumber -- **Developer empowerment**: Polkadot’s interoperability tools allow developers to build applications that leverage multiple chains’ capabilities without added complexity. -- **Enhanced ecosystem collaboration**: Chains in Polkadot can focus on their unique strengths while contributing to the ecosystem’s overall growth. -- **Future-proofing blockchain**: By enabling seamless communication, Polkadot ensures its ecosystem can adapt to evolving demands and technologies. +Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. -## Looking Ahead +**Parameters**: -Polkadot’s vision of interoperability extends beyond technical functionality, representing a shift towards a more collaborative blockchain landscape. By enabling chains to work together, Polkadot fosters innovation, efficiency, and accessibility, paving the way for a decentralized future where blockchains are not isolated competitors but interconnected collaborators. +None. - ---- - -Page Title: Introduction to XCM - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ -- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. - -# Introduction to XCM - -## Introduction - -Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. - -With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. - -## Messaging Format - -XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. - -XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. - -## The Four Principles of XCM - -XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: - -- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. -- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. -- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. -- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. - -These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. - -## The XCM Tech Stack - -![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) - -The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. - -## Core Functionalities of XCM - -XCM enhances cross-consensus communication by introducing several powerful features: - -- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. -- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. -- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. - -The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. - -## XCM Example - -The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). - -```rust -let message = Xcm(vec![ - WithdrawAsset((Here, amount).into()), - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } -]); -``` - -The message consists of three instructions described as follows: - -- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. - - ```rust - WithdrawAsset((Here, amount).into()), - ``` - - - **`Here`**: The native parachain token. - - **`amount`**: The number of tokens that are transferred. - - The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. - -- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. - - ```rust - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - ``` - - - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. - - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. - -- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. - - ```rust - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } - ``` - - - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. - -This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - -## Overview - -XCM revolutionizes cross-chain communication by enabling use cases such as: - -- Token transfers between blockchains. -- Asset locking for cross-chain smart contract interactions. -- Remote execution of functions on other blockchains. - -These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - - ---- - -Page Title: JSON-RPC APIs - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ -- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. - -# JSON-RPC APIs - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. - -This guide uses the Polkadot Hub TestNet endpoint: - -```text -https://testnet-passet-hub-eth-rpc.polkadot.io -``` - -## Available Methods - -### eth_accounts - -Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_accounts" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_accounts", - "params":[], - "id":1 -}' -``` - ---- - -### eth_blockNumber - -Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. - -**Parameters**: - -None. - -**Example**: +**Example**: ```bash title="eth_blockNumber" curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ @@ -4234,1350 +3088,136 @@ If an error occurs, the response will include an error object: --- -Page Title: Networks +Page Title: Overview of FRAME -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/networks/ -- Summary: Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md +- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ +- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. -# Networks +# Customize Your Runtime ## Introduction -The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's various networks and explain how they fit into the development workflow. +A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. -## Network Overview +This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. -Polkadot's development process is structured to ensure new features and upgrades are rigorously tested before being deployed on live production networks. The progression follows a well-defined path, starting from local environments and advancing through TestNets, ultimately reaching the Polkadot MainNet. The diagram below outlines the typical progression of the Polkadot development cycle: +## Understanding Your Runtime -``` mermaid -flowchart LR - id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] - id1[Local] --> id3[Paseo] --> id5[Polkadot] -``` +The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. -This flow ensures developers can thoroughly test and iterate without risking real tokens or affecting production networks. Testing tools like [Chopsticks](#chopsticks) and various TestNets make it easier to experiment safely before releasing to production. +Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. -A typical journey through the Polkadot core protocol development process might look like this: +## Runtime Architecture -1. **Local development node**: Development starts in a local environment, where developers can create, test, and iterate on upgrades or new features using a local development node. This stage allows rapid experimentation in an isolated setup without any external dependencies. +The following diagram shows how FRAME components work together to form your runtime: -2. **Westend**: After testing locally, upgrades are deployed to [Westend](#westend), Polkadot's primary TestNet. Westend simulates real-world conditions without using real tokens, making it the ideal place for rigorous feature testing before moving on to production networks. +![](/images/parachains/customize-runtime/index/frame-overview-01.webp) -3. **Kusama**: Once features have passed extensive testing on Westend, they move to Kusama, Polkadot's experimental and fast-moving "canary" network. Kusama operates as a high-fidelity testing ground with actual economic incentives, giving developers insights into how their features will perform in a real-world environment. +The main components are: -4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network. +- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. +- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. +- **`frame_system`**: Provides core runtime primitives and storage. +- **`frame_support`**: Utilities and macros that simplify pallet development. - In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. +## Building Blocks: Pallets -5. **Paseo**: For parachain and dApp developers, Paseo serves as a community-run TestNet that mirrors Polkadot's runtime. Like Westend for core protocol development, Paseo provides a testing ground for parachain development without affecting live networks. +[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. -!!!note - The Rococo TestNet deprecation date was October 14, 2024. Teams should use Westend for Polkadot protocol and feature testing and Paseo for chain development-related testing. +A pallet can implement virtually any blockchain feature you need: -## Polkadot Development Networks +- Expose new transactions that users can submit. +- Store data on-chain. +- Enforce business rules and validation logic. +- Emit events to notify users of state changes. +- Handle errors gracefully. -Development and testing are crucial to building robust dApps and parachains and performing network upgrades within the Polkadot ecosystem. To achieve this, developers can leverage various networks and tools that provide a risk-free environment for experimentation and validation before deploying features to live networks. These networks help avoid the costs and risks associated with real tokens, enabling testing for functionalities like governance, cross-chain messaging, and runtime upgrades. +### Pre-Built Pallets vs. Custom Pallets -## Kusama Network +FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. -Kusama is the experimental version of Polkadot, designed for developers who want to move quickly and test their applications in a real-world environment with economic incentives. Kusama serves as a production-grade testing ground where developers can deploy features and upgrades with the pressure of game theory and economics in mind. It mirrors Polkadot but operates as a more flexible space for innovation. +However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. -The native token for Kusama is KSM. For more information about KSM, visit the [Native Assets](https://wiki.polkadot.com/kusama/kusama-getting-started/){target=\_blank} page. +### Pallet Structure -## Test Networks +FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. -The following test networks provide controlled environments for testing upgrades and new features. TestNet tokens are available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}. +A typical pallet looks like this: -### Westend +```rust +pub use pallet::*; -Westend is Polkadot's primary permanent TestNet. Unlike temporary test networks, Westend is not reset to the genesis block, making it an ongoing environment for testing Polkadot core features. Managed by Parity Technologies, Westend ensures that developers can test features in a real-world simulation without using actual tokens. +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; -The native token for Westend is WND. More details about WND can be found on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_2){target=\_blank} page. + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); -### Paseo + #[pallet::config] // snip + #[pallet::event] // snip + #[pallet::error] // snip + #[pallet::storage] // snip + #[pallet::call] // snip +} +``` -[Paseo](https://github.com/paseo-network){target=\_blank} is a community-managed TestNet designed for parachain and dApp developers. It mirrors Polkadot's runtime and is maintained by Polkadot community members. Paseo provides a dedicated space for parachain developers to test their applications in a Polkadot-like environment without the risks associated with live networks. +Every pallet can implement these core macros: -The native token for Paseo is PAS. Additional information on PAS is available on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_1){target=\_blank} page. +- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. +- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. +- **`#[pallet::config]`**: Defines configuration and associated types. +- **`#[pallet::event]`**: Defines events emitted by your pallet. +- **`#[pallet::error]`**: Defines error types your pallet can return. +- **`#[pallet::storage]`**: Defines on-chain storage items. +- **`#[pallet::call]`**: Defines dispatchable functions (transactions). -## Local Test Networks +For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. -Local test networks are an essential part of the development cycle for blockchain developers using the Polkadot SDK. They allow for fast, iterative testing in controlled, private environments without connecting to public TestNets. Developers can quickly spin up local instances to experiment, debug, and validate their code before deploying to larger TestNets like Westend or Paseo. Two key tools for local network testing are Zombienet and Chopsticks. +## How Runtime Customization Works -### Zombienet +Customizing your runtime typically follows these patterns: -[Zombienet](https://github.com/paritytech/zombienet){target=\_blank} is a flexible testing framework for Polkadot SDK-based blockchains. It enables developers to create and manage ephemeral, short-lived networks. This feature makes Zombienet particularly useful for quick iterations, as it allows you to run multiple local networks concurrently, mimicking different runtime conditions. Whether you're developing a parachain or testing your custom blockchain logic, Zombienet gives you the tools to automate local testing. +**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. -Key features of Zombienet include: +**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. -- Creating dynamic, local networks with different configurations. -- Running parachains and relay chains in a simulated environment. -- Efficient testing of network components like cross-chain messaging and governance. +**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. -Zombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets. +**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. -### Chopsticks +The following diagram illustrates how pallets combine to form a complete runtime: -[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\_blank} is a tool designed to create forks of Polkadot SDK-based blockchains, allowing developers to interact with network forks as part of their testing process. This capability makes Chopsticks a powerful option for testing upgrades, runtime changes, or cross-chain applications in a forked network environment. +![](/images/parachains/customize-runtime/index/frame-overview-02.webp) -Key features of Chopsticks include: +## Starting Templates -- Forking live Polkadot SDK-based blockchains for isolated testing. -- Simulating cross-chain messages in a private, controlled setup. -- Debugging network behavior by interacting with the fork in real-time. +The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. -Chopsticks provides a controlled environment for developers to safely explore the effects of runtime changes. It ensures that network behavior is tested and verified before upgrades are deployed to live networks. +- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. +- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. ---- +- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. -Page Title: Node and Runtime - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/node-and-runtime/ -- Summary: Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. - -# Node and Runtime - -## Introduction - -Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network. - -Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. - -If the system were a monolithic protocol, any modification would require updating the entire system. Instead, Polkadot achieves true upgradeability by defining an immutable meta-protocol (the client) and a protocol (the runtime) that can be upgraded independently. - -This separation gives the [Polkadot Relay Chain](/polkadot-protocol/architecture/polkadot-chain){target=\_blank} and all connected [parachains](/polkadot-protocol/architecture/parachains){target=\_blank} an evolutionary advantage over other blockchain platforms. - -## Architectural Principles - -The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: - -- Client (Meta-protocol): - - Handles the foundational infrastructure of the blockchain. - - Manages runtime execution, networking, consensus, and other off-chain components. - - Provides an immutable base layer that ensures network stability. - - Upgradable only through hard forks. - -- Runtime (Protocol): - - Defines the blockchain's state transition logic. - - Determines the specific rules and behaviors of the blockchain. - - Compiled to WebAssembly (Wasm) for platform-independent execution. - - Capable of being upgraded without network-wide forking. - -### Advantages of this Architecture - -- **Forkless upgrades**: Runtime can be updated without disrupting the entire network. -- **Modularity**: Clear separation allows independent development of client and runtime. -- **Flexibility**: Enables rapid iteration and evolution of blockchain logic. -- **Performance**: WebAssembly compilation provides efficient, cross-platform execution. - -## Node (Client) - -The node, also known as the client, is the core component responsible for executing the Wasm runtime and orchestrating various essential blockchain components. It ensures the correct execution of the state transition function and manages multiple critical subsystems, including: - -- **Wasm execution**: Runs the blockchain runtime, which defines the state transition rules. -- **Database management**: Stores blockchain data. -- **Networking**: Facilitates peer-to-peer communication, block propagation, and transaction gossiping. -- **Transaction pool (Mempool)**: Manages pending transactions before they are included in a block. -- **Consensus mechanism**: Ensures agreement on the blockchain state across nodes. -- **RPC services**: Provides external interfaces for applications and users to interact with the node. - -## Runtime - -The runtime is more than just a set of rules. It's the fundamental logic engine that defines a blockchain's entire behavior. In Polkadot SDK-based blockchains, the runtime represents a complete, self-contained description of the blockchain's state transition function. - -### Characteristics - -The runtime is distinguished by three key characteristics: - -- **Business logic**: Defines the complete application-specific blockchain behavior. -- **WebAssembly compilation**: Ensures platform-independent, secure execution. -- **On-chain storage**: Stored within the blockchain's state, allowing dynamic updates. - -### Key Functions - -The runtime performs several critical functions, such as: - -- Define state transition rules. -- Implement blockchain-specific logic. -- Manage account interactions. -- Control transaction processing. -- Define governance mechanisms. -- Handle custom pallets and modules. - -## Communication Between Node and Runtime - -The client and runtime communicate exclusively using [SCALE-encoded](/polkadot-protocol/parachain-basics/data-encoding){target=\_blank} communication. This ensures efficient and compact data exchange between the two components. - -### Runtime APIs - -The Runtime API consists of well-defined functions and constants a client assumes are implemented in the Runtime Wasm blob. These APIs enable the client to interact with the runtime to execute blockchain operations and retrieve information. The client invokes these APIs to: - -- Build, execute, and finalize blocks. -- Access metadata. -- Access consensus related information. -- Handle transaction execution. - -### Host Functions - -During execution, the runtime can access certain external client functionalities via host functions. The specific functions the client exposes allow the runtime to perform operations outside the WebAssembly domain. Host functions enable the runtime to: - -- Perform cryptographic operations. -- Access the current blockchain state. -- Handle storage modifications. -- Allocate memory. - - ---- - -Page Title: On-Chain Governance Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md -- Canonical (HTML): https://docs.polkadot.com/reference/governance/ -- Summary: Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. - -# On-Chain Governance - -## Introduction - -Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model. - -This guide will explain the principles and structure of OpenGov and walk you through its key components, such as Origins, Tracks, and Delegation. You will learn about improvements over earlier governance systems, including streamlined voting processes and enhanced stakeholder participation. - -With OpenGov, Polkadot achieves a flexible, scalable, and democratic governance framework that allows multiple proposals to proceed simultaneously, ensuring the network evolves in alignment with its community's needs. - -## Governance Evolution - -Polkadot’s governance journey began with [Governance V1](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#governance-summary){target=\_blank}, a system that proved effective in managing treasury funds and protocol upgrades. However, it faced limitations, such as: - -- Slow voting cycles, causing delays in decision-making. -- Inflexibility in handling multiple referendums, restricting scalability. - -To address these challenges, Polkadot introduced OpenGov, a governance model designed for greater inclusivity, efficiency, and scalability. OpenGov replaces the centralized structures of Governance V1, such as the Council and Technical Committee, with a fully decentralized and dynamic framework. - -For a full comparison of the historic and current governance models, visit the [Gov1 vs. Polkadot OpenGov](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#gov1-vs-polkadot-opengov){target=\_blank} section of the Polkadot Wiki. - -## OpenGov Key Features - -OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: - -- **Decentralization**: Shifts all decision-making power to the public, ensuring a more democratic process. -- **Enhanced delegation**: Allows users to delegate their votes to trusted experts across specific governance tracks. -- **Simultaneous referendums**: Multiple proposals can progress at once, enabling faster decision-making. -- **Polkadot Technical Fellowship**: A broad, community-driven group replacing the centralized Technical Committee. - -This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. - -## Origins and Tracks - -In OpenGov, origins and tracks are central to managing proposals and votes. - -- **Origin**: Determines the authority level of a proposal (e.g., Treasury, Root) which decides the track of all referendums from that origin. -- **Track**: Define the procedural flow of a proposal, such as voting duration, approval thresholds, and enactment timelines. - -Developers must be aware that referendums from different origins and tracks will take varying amounts of time to reach approval and enactment. The [Polkadot Technical Fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} has the option to shorten this timeline by whitelisting a proposal and allowing it to be enacted through the [Whitelist Caller](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#whitelisted-caller){target=\_blank} origin. - -Visit [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#origins-and-tracks){target=\_blank} for details on current origins and tracks, associated terminology, and parameters. - -## Referendums - -In OpenGov, anyone can submit a referendum, fostering an open and participatory system. The timeline for a referendum depends on the privilege level of the origin with more significant changes offering more time for community voting and participation before enactment. - -The timeline for an individual referendum includes four distinct periods: - -- **Lead-in**: A minimum amount of time to allow for community participation, available room in the origin, and payment of the decision deposit. Voting is open during this period. -- **Decision**: Voting continues. -- **Confirmation**: Referendum must meet [approval and support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} criteria during entire period to avoid rejection. -- **Enactment**: Changes approved by the referendum are executed. - -### Vote on Referendums - -Voters can vote with their tokens on each referendum. Polkadot uses a voluntary token locking mechanism, called conviction voting, as a way for voters to increase their voting power. A token holder signals they have a stronger preference for approving a proposal based upon their willingness to lock up tokens. Longer voluntary token locks are seen as a signal of continual approval and translate to increased voting weight. - -See [Voting on a Referendum](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank} for a deeper look at conviction voting and related token locks. - -### Delegate Voting Power - -The OpenGov system also supports multi-role delegations, allowing token holders to assign their voting power on different tracks to entities with expertise in those areas. - -For example, if a token holder lacks the technical knowledge to evaluate proposals on the [Root track](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#root){target=\_blank}, they can delegate their voting power for that track to an expert they trust to vote in the best interest of the network. This ensures informed decision-making across tracks while maintaining flexibility for token holders. - -Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. - -### Cancel a Referendum - -Polkadot OpenGov has two origins for rejecting ongoing referendums: - -- [**Referendum Canceller**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-canceller){target=\_blank}: Cancels an active referendum when non-malicious errors occur and refunds the deposits to the originators. -- [**Referendum Killer**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-killer){target=\_blank}: Used for urgent, malicious cases this origin instantly terminates an active referendum and slashes deposits. - -See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. - -## Additional Resources - -- **[Democracy pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/democracy/src){target=\_blank}**: Handles administration of general stakeholder voting. -- **[Gov2: Polkadot’s Next Generation of Decentralised Governance](https://medium.com/polkadot-network/gov2-polkadots-next-generation-of-decentralised-governance-4d9ef657d11b){target=\_blank}**: Medium article by Gavin Wood. -- **[Polkadot Direction](https://matrix.to/#/#Polkadot-Direction:parity.io){target=\_blank}**: Matrix Element client. -- **[Polkassembly](https://polkadot.polkassembly.io/){target=\_blank}**: OpenGov dashboard and UI. -- **[Polkadot.js Apps Governance](https://polkadot.js.org/apps/#/referenda){target=\_blank}**: Overview of active referendums. - - ---- - -Page Title: Overview of FRAME - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md -- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ -- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. - -# Customize Your Runtime - -## Introduction - -A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. - -This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. - -## Understanding Your Runtime - -The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. - -Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. - -## Runtime Architecture - -The following diagram shows how FRAME components work together to form your runtime: - -![](/images/parachains/customize-runtime/index/frame-overview-01.webp) - -The main components are: - -- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. -- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. -- **`frame_system`**: Provides core runtime primitives and storage. -- **`frame_support`**: Utilities and macros that simplify pallet development. - -## Building Blocks: Pallets - -[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. - -A pallet can implement virtually any blockchain feature you need: - -- Expose new transactions that users can submit. -- Store data on-chain. -- Enforce business rules and validation logic. -- Emit events to notify users of state changes. -- Handle errors gracefully. - -### Pre-Built Pallets vs. Custom Pallets - -FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. - -However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. - -### Pallet Structure - -FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. - -A typical pallet looks like this: - -```rust -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - #[pallet::config] // snip - #[pallet::event] // snip - #[pallet::error] // snip - #[pallet::storage] // snip - #[pallet::call] // snip -} -``` - -Every pallet can implement these core macros: - -- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. -- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. -- **`#[pallet::config]`**: Defines configuration and associated types. -- **`#[pallet::event]`**: Defines events emitted by your pallet. -- **`#[pallet::error]`**: Defines error types your pallet can return. -- **`#[pallet::storage]`**: Defines on-chain storage items. -- **`#[pallet::call]`**: Defines dispatchable functions (transactions). - -For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. - -## How Runtime Customization Works - -Customizing your runtime typically follows these patterns: - -**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. - -**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. - -**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. - -**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. - -The following diagram illustrates how pallets combine to form a complete runtime: - -![](/images/parachains/customize-runtime/index/frame-overview-02.webp) - -## Starting Templates - -The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. - -- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. - -- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. - -- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. - -- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. - -## Key Customization Scenarios - -This section covers the most common customization patterns you'll encounter: - -- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. - -- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. - -- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. - -- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. - -- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. - - ---- - -Page Title: Overview of the Polkadot Relay Chain - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/ -- Summary: Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. - -# Overview - -## Introduction - -Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank}, and cross-chain interactions via its native [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank}. - -This guide covers key aspects of Polkadot’s architecture, including its high-level protocol structure, blockspace commoditization, and the role of its native token, DOT, in governance, staking, and resource allocation. - -## Polkadot 1.0 - -Polkadot 1.0 represents the state of Polkadot as of 2023, coinciding with the release of [Polkadot runtime v1.0.0](https://github.com/paritytech/polkadot/releases/tag/v1.0.0){target=\_blank}. This section will focus on Polkadot 1.0, along with philosophical insights into network resilience and blockspace. - -As a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including: - -- **Application-specific Layer-1 blockchains (parachains)**: Polkadot's sharded network allows for parallel transaction processing, with shards that can have unique state transition functions, enabling custom-built L1 chains optimized for specific applications. - -- **Shared security and scalability**: L1 chains connected to Polkadot benefit from its [Nominated Proof of Stake (NPoS)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#nominated-proof-of-stake){target=\_blank} system, providing security out-of-the-box without the need to bootstrap their own. - -- **Secure interoperability**: Polkadot's native interoperability enables seamless data and value exchange between parachains. This interoperability can also be used outside of the ecosystem for bridging with external networks. - -- **Resilient infrastructure**: Decentralized and scalable, Polkadot ensures ongoing support for development and community initiatives via its on-chain [treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} and governance. - -- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. - -- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. - - - [Polkadot Blockchain Academy](https://polkadot.com/blockchain-academy){target=\_blank} - - [EdX courses](https://www.edx.org/school/web3x){target=\_blank} - - Rust and Substrate courses (coming soon) - -### High-Level Architecture - -Polkadot features a chain that serves as the central component of the system. This chain is depicted as a ring encircled by several parachains that are connected to it. - -According to Polkadot's design, any blockchain that can compile to WebAssembly (Wasm) and adheres to the Parachains Protocol becomes a parachain on the Polkadot network. - -Here’s a high-level overview of the Polkadot protocol architecture: - -![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } - -Parachains propose blocks to Polkadot validators, who check for availability and validity before finalizing them. With the relay chain providing security, collators—full nodes of parachains—can focus on their tasks without needing strong incentives. - -The [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank} allows parachains to exchange messages freely, leveraging the chain's security for trust-free communication. - -In order to interact with chains that want to use their own finalization process (e.g., Bitcoin), Polkadot has [bridges](/reference/parachains/interoperability/#bridges-connecting-external-networks){target=\_blank} that offer two-way compatibility, meaning that transactions can be made between different parachains. - -### Polkadot's Additional Functionalities - -Historically, obtaining core slots on Polkadot chain relied upon crowdloans and auctions. Chain cores were leased through auctions for three-month periods, up to a maximum of two years. Crowdloans enabled users to securely lend funds to teams for lease deposits in exchange for pre-sale tokens, which is the only way to access slots on Polkadot 1.0. Auctions are now deprecated in favor of [coretime](/polkadot-protocol/architecture/system-chains/coretime/){target=\_blank}. - -Additionally, the chain handles [staking](https://wiki.polkadot.com/learn/learn-staking/){target=\_blank}, [accounts](/reference/parachains/accounts/){target=\_blank}, balances, and [governance](/reference/governance/){target=\_blank}. - -#### Agile Coretime - -The new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. - -[Agile coretime](/reference/polkadot-hub/consensus-and-security/agile-coretime/){target=\_blank} improves the efficient use of Polkadot's network resources and offers economic flexibility for developers, extending Polkadot's capabilities far beyond the original vision outlined in the [whitepaper](https://polkadot.com/papers/Polkadot-whitepaper.pdf){target=\_blank}. - -It enables parachains to purchase monthly "bulk" allocations of coretime (the time allocated for utilizing a core, measured in Polkadot relay chain blocks), ensuring heavy-duty parachains that can author a block every six seconds with [Asynchronous Backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} can reliably renew their coretime each month. Although six-second block times are now the default, parachains have the option of producing blocks less frequently. - -Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. - -### Polkadot's Resilience - -Decentralization is a vital component of blockchain networks, but it comes with trade-offs: - -- An overly decentralized network may face challenges in reaching consensus and require significant energy to operate. -- Also, a network that achieves consensus quickly risks centralization, making it easier to manipulate or attack. - -A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. - -Polkadot 1.0 currently achieves resilience through several strategies: - -- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. - -- **Decentralized nodes**: Designed to encourage operators to join the network. This program aims to expand and diversify the validators in the ecosystem who aim to become independent of the program during their term. Feel free to explore more about the program on the official [Decentralized Nodes](https://nodes.web3.foundation/){target=\_blank} page. - -- **On-chain treasury and governance**: Known as [OpenGov](/reference/governance/){target=\_blank}, this system allows every decision to be made through public referenda, enabling any token holder to cast a vote. - -### Polkadot's Blockspace - -Polkadot 1.0’s design allows for the commoditization of blockspace. - -Blockspace is a blockchain's capacity to finalize and commit operations, encompassing its security, computing, and storage capabilities. Its characteristics can vary across different blockchains, affecting security, flexibility, and availability. - -- **Security**: Measures the robustness of blockspace in Proof of Stake (PoS) networks linked to the stake locked on validator nodes, the variance in stake among validators, and the total number of validators. It also considers social centralization (how many validators are owned by single operators) and physical centralization (how many validators run on the same service provider). - -- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes. - -- **Availability**: Indicates how easily users can access blockspace. It should be easily accessible, allowing diverse business models to thrive, ideally regulated by a marketplace based on demand and supplemented by options for "second-hand" blockspace. - -Polkadot is built on core blockspace principles, but there's room for improvement. Tasks like balance transfers, staking, and governance are managed on the relay chain. - -Delegating these responsibilities to [system chains](/polkadot-protocol/architecture/system-chains/){target=\_blank} could enhance flexibility and allow the relay chain to concentrate on providing shared security and interoperability. - -For more information about blockspace, watch [Robert Habermeier’s interview](https://www.youtube.com/watch?v=e1vISppPwe4){target=\_blank} or read his [technical blog post](https://www.rob.tech/blog/polkadot-blockspace-over-blockchains/){target=\_blank}. - -## DOT Token - -DOT is the native token of the Polkadot network, much like BTC for Bitcoin and Ether for the Ethereum blockchain. DOT has 10 decimals, uses the Planck base unit, and has a balance type of `u128`. The same is true for Kusama's KSM token with the exception of having 12 decimals. - -### Redenomination of DOT - -Polkadot conducted a community poll, which ended on 27 July 2020 at block 888,888, to decide whether to redenominate the DOT token. The stakeholders chose to redenominate the token, changing the value of 1 DOT from 1e12 plancks to 1e10 plancks. - -Importantly, this did not affect the network's total number of base units (plancks); it only affects how a single DOT is represented. The redenomination became effective 72 hours after transfers were enabled, occurring at block 1,248,328 on 21 August 2020 around 16:50 UTC. - -### The Planck Unit - -The smallest unit of account balance on Polkadot SDK-based blockchains (such as Polkadot and Kusama) is called _Planck_, named after the Planck length, the smallest measurable distance in the physical universe. - -Similar to how BTC's smallest unit is the Satoshi and ETH's is the Wei, Polkadot's native token DOT equals 1e10 Planck, while Kusama's native token KSM equals 1e12 Planck. - -### Uses for DOT - -DOT serves three primary functions within the Polkadot network: - -- **Governance**: It is used to participate in the governance of the network. -- **Staking**: DOT is staked to support the network's operation and security. -- **Buying coretime**: Used to purchase coretime in-bulk or on-demand and access the chain to benefit from Polkadot's security and interoperability. - -Additionally, DOT can serve as a transferable token. For example, DOT, held in the treasury, can be allocated to teams developing projects that benefit the Polkadot ecosystem. - -## JAM and the Road Ahead - -The Join-Accumulate Machine (JAM) represents a transformative redesign of Polkadot's core architecture, envisioned as the successor to the current relay chain. Unlike traditional blockchain architectures, JAM introduces a unique computational model that processes work through two primary functions: - -- **Join**: Handles data integration. -- **Accumulate**: Folds computations into the chain's state. - -JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: - -- **Permissionless code execution**: JAM is designed to be more generic and flexible, allowing for permissionless code execution through services that can be deployed without governance approval. -- **More effective block time utilization**: JAM's efficient pipeline processing model places the prior state root in block headers instead of the posterior state root, enabling more effective utilization of block time for computations. - -This architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes. - - ---- - -Page Title: Parachains Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/ -- Summary: Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. - -# Parachains Overview - -## Introduction - -A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network. - -Unlike standalone blockchains that must bootstrap their own validator sets and security, parachains leverage Polkadot's pooled security model. This allows parachain developers to focus on their application-specific functionality rather than consensus and security infrastructure. Parachains can communicate with each other through Cross-Consensus Messaging (XCM), enabling seamless interoperability across the Polkadot ecosystem. - -Key capabilities that parachains provide include: - -- **Shared security**: Inherit security from Polkadot's validator set without maintaining your own. -- **Interoperability**: Communicate trustlessly with other parachains via XCM. -- **Scalability**: Process transactions in parallel with other parachains. -- **Customization**: Build application-specific logic tailored to your use case. -- **Upgradeability**: Upgrade runtime logic without hard forks. - -## Polkadot SDK: Parachain Architecture - -Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: - -![](/images/reference/parachains/index/overview-01.webp) - -- **[Substrate](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html){target=\_blank}**: The foundation providing core blockchain primitives and libraries. -- **[FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank}**: A modular framework for building your parachain's runtime logic. -- **[Cumulus](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html){target=\_blank}**: Essential libraries and pallets that enable parachain functionality. -- **[XCM (Cross Consensus Messaging)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/xcm/index.html){target=\_blank}**: The messaging format for communicating with other parachains and the relay chain. -- **[Polkadot](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/polkadot/index.html){target=\_blank}**: The relay chain that provides security and coordination. - -### Substrate: The Foundation - -Substrate provides the core infrastructure that every parachain is built upon. It handles the low-level blockchain functionality, allowing you to focus on your application's unique features. Substrate includes implementations for networking, database management, consensus participation, and the execution environment for your runtime. - -Every Polkadot SDK node consists of two main components: - -- **Client (Host)**: Handles infrastructure services. - - - Native binary that runs on validator and collator nodes. - - Executes the Wasm-compiled runtime. - - Manages networking, database, mempool, and block production. - - Interfaces with the relay chain for validation. - -- **Runtime (State Transition Function)**: Contains your business logic. - - - Defines how your Polkadot SDK node processes transactions. - - Compiled to [Wasm](https://webassembly.org/){target=\_blank} for deterministic execution. - - Stored on-chain and upgradeable via governance. - -```mermaid -%%{init: {'flowchart': {'padding': 5, 'nodeSpacing': 50, 'rankSpacing': 10}}}%% -graph TB - classDef title font-size:20px,font-weight:bold,stroke-width:0px - classDef clientStyle font-size:16px,font-weight:bold - classDef clientSubNodeStyle margin-top:10px - classDef runtimeCallExecutorStyle padding-top:10px - - subgraph sg1[Parachain
    Node] - direction TB - - I[RuntimeCall Executor] - B[Wasm Runtime - STF] - - subgraph sg2[Client] - direction TB - C[Network and Blockchain
    Infrastructure Services
    + Relay Chain Interface] - end - - I --> B - end - - class sg1 title - class sg2 clientStyle - class C clientSubNodeStyle - class I runtimeCallExecutorStyle - -``` - -### FRAME: Building Blocks for Your Runtime - -FRAME provides modular components called [pallets](/reference/glossary#pallet){target=\_blank} that you can compose to build your parachain's runtime. Each pallet provides specific functionality that you can customize and configure for your needs. This modular approach allows you to quickly assemble complex functionality without writing everything from scratch. - -```mermaid -graph LR - subgraph SP["Parachain Runtime"] - direction LR - Timestamp ~~~ Aura ~~~ ParachainSystem - Balances ~~~ TransactionPayment ~~~ Sudo - subgraph Timestamp["Timestamp"] - SS1[Custom Config] - end - subgraph Aura["Aura"] - SS2[Custom Config] - end - subgraph ParachainSystem["Parachain System"] - SS3[Custom Config] - end - subgraph Balances["Balances"] - SS4[Custom Config] - end - subgraph TransactionPayment["Transaction Payment"] - SS5[Custom Config] - end - subgraph Sudo["Sudo"] - SS6[Custom Config] - end - style Timestamp stroke:#FF69B4 - style Aura stroke:#FF69B4 - style ParachainSystem stroke:#FF69B4 - style Balances stroke:#FF69B4 - style TransactionPayment stroke:#FF69B4 - style Sudo stroke:#FF69B4 - style SS1 stroke-dasharray: 5 - style SS2 stroke-dasharray: 5 - style SS3 stroke-dasharray: 5 - style SS4 stroke-dasharray: 5 - style SS5 stroke-dasharray: 5 - style SS6 stroke-dasharray: 5 - - end - subgraph AP["Available FRAME Pallets"] - direction LR - A1[Aura]~~~A2[Parachain
    System]~~~A3[Transaction
    Payment]~~~A4[Sudo] - B1[Identity]~~~B2[Balances]~~~B3[Assets]~~~B4[EVM] - C1[Timestamp]~~~C2[Staking]~~~C3[Contracts]~~~C4[and more...] - end - AP --> SP -``` - -### Cumulus: Parachain-Specific Functionality - -Cumulus is what transforms a Polkadot SDK-based runtime into a parachain-capable runtime. It provides the essential components for communicating with the relay chain, participating in Polkadot's consensus, and handling parachain-specific operations like block validation and collation. - -Key Cumulus components include: - -- **Parachain system pallet**: Core parachain functionality and relay chain communication. -- **Collator consensus**: Block production logic for parachain collators. -- **Relay chain interface**: APIs for interacting with the Polkadot relay chain. -- **Validation data**: Handling proof-of-validity data required by relay chain validators. - -## Where to Go Next - -Building a parachain requires understanding the relationship between your chain and the Polkadot relay chain. The Polkadot SDK provides all the tools needed to design custom runtime logic, enable cross-chain communication, and deploy your parachain to production. - -The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. - -
    - -- Guide __Launch a Simple Parachain__ - - --- - - Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. - - [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) - - -- Guide __Customize Your Runtime__ - - --- - - Design your parachain's runtime logic and choose appropriate pallets for your use case. - - [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) - -- Guide __Interoperability__ - - --- - - Implement XCM for trustless cross-chain communication with other parachains. - - [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/) - -- Guide __Runtime Upgrades__ - - --- - - Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. - - [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) - -
    - - ---- - -Page Title: Polkadot SDK Accounts - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/accounts/ -- Summary: Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. - -# Accounts - -## Introduction - -Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains. - -This page will guide you through the essential aspects of accounts, including their data structure, balance types, reference counters, and address formats. You’ll learn how accounts are managed within the runtime, how balances are categorized, and how addresses are encoded and validated. - -## Account Data Structure - -Accounts are foundational to any blockchain, and the Polkadot SDK provides a flexible management system. This section explains how the Polkadot SDK defines accounts and manages their lifecycle through data structures within the runtime. - -### Account - -The [`Account` data type](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/type.Account.html){target=\_blank} is a storage map within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank} that links an account ID to its corresponding data. This structure is fundamental for mapping account-related information within the chain. - -The code snippet below shows how accounts are defined: - -```rs - /// The full account information for a particular account ID. - #[pallet::storage] - #[pallet::getter(fn account)] - pub type Account = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - AccountInfo, - ValueQuery, - >; -``` - -The preceding code block defines a storage map named `Account`. The `StorageMap` is a type of on-chain storage that maps keys to values. In the `Account` map, the key is an account ID, and the value is the account's information. Here, `T` represents the generic parameter for the runtime configuration, which is defined by the pallet's configuration trait (`Config`). - -The `StorageMap` consists of the following parameters: - -- **`_`**: Used in macro expansion and acts as a placeholder for the storage prefix type. Tells the macro to insert the default prefix during expansion. -- **`Blake2_128Concat`**: The hashing function applied to keys in the storage map. -- **`T: :AccountId`**: Represents the key type, which corresponds to the account’s unique ID. -- **`AccountInfo`**: The value type stored in the map. For each account ID, the map stores an `AccountInfo` struct containing: - - - **`T::Nonce`**: A nonce for the account, which is incremented with each transaction to ensure transaction uniqueness. - - **`T: :AccountData`**: Custom account data defined by the runtime configuration, which could include balances, locked funds, or other relevant information. - -- **`ValueQuery`**: Defines how queries to the storage map behave when no value is found; returns a default value instead of `None`. - -For a detailed explanation of storage maps, see the [`StorageMap`](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/struct.StorageMap.html){target=\_blank} entry in the Rust docs. - -### Account Info - -The `AccountInfo` structure is another key element within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank}, providing more granular details about each account's state. This structure tracks vital data, such as the number of transactions and the account’s relationships with other modules. - -```rs -/// Information of an account. -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct AccountInfo { - /// The number of transactions this account has sent. - pub nonce: Nonce, - /// The number of other modules that currently depend on this account's existence. The account - /// cannot be reaped until this is zero. - pub consumers: RefCount, - /// The number of other modules that allow this account to exist. The account may not be reaped - /// until this and `sufficients` are both zero. - pub providers: RefCount, - /// The number of modules that allow this account to exist for their own purposes only. The - /// account may not be reaped until this and `providers` are both zero. - pub sufficients: RefCount, - /// The additional data that belongs to this account. Used to store the balance(s) in a lot of - /// chains. - pub data: AccountData, -} -``` - -The `AccountInfo` structure includes the following components: - -- **`nonce`**: Tracks the number of transactions initiated by the account, which ensures transaction uniqueness and prevents replay attacks. -- **`consumers`**: Counts how many other modules or pallets rely on this account’s existence. The account cannot be removed from the chain (reaped) until this count reaches zero. -- **`providers`**: Tracks how many modules permit this account’s existence. An account can only be reaped once both `providers` and `sufficients` are zero. -- **`sufficients`**: Represents the number of modules that allow the account to exist for internal purposes, independent of any other modules. -- **`AccountData`**: A flexible data structure that can be customized in the runtime configuration, usually containing balances or other user-specific data. - -This structure helps manage an account's state and prevents its premature removal while it is still referenced by other on-chain data or modules. The [`AccountInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.AccountInfo.html){target=\_blank} structure can vary as long as it satisfies the trait bounds defined by the `AccountData` associated type in the [`frame-system::pallet::Config`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/trait.Config.html){target=\_blank} trait. - -### Account Reference Counters - -Polkadot SDK uses reference counters to track an account’s dependencies across different runtime modules. These counters ensure that accounts remain active while data is associated with them. - -The reference counters include: - -- **`consumers`**: Prevents account removal while other pallets still rely on the account. -- **`providers`**: Ensures an account is active before other pallets store data related to it. -- **`sufficients`**: Indicates the account’s independence, ensuring it can exist even without a native token balance, such as when holding sufficient alternative assets. - -#### Providers Reference Counters - -The `providers` counter ensures that an account is ready to be depended upon by other runtime modules. For example, it is incremented when an account has a balance above the existential deposit, which marks the account as active. - -The system requires this reference counter to be greater than zero for the `consumers` counter to be incremented, ensuring the account is stable before any dependencies are added. - -#### Consumers Reference Counters - -The `consumers` counter ensures that the account cannot be reaped until all references to it across the runtime have been removed. This check prevents the accidental deletion of accounts that still have active on-chain data. - -It is the user’s responsibility to clear out any data from other runtime modules if they wish to remove their account and reclaim their existential deposit. - -#### Sufficients Reference Counter - -The `sufficients` counter tracks accounts that can exist independently without relying on a native account balance. This is useful for accounts holding other types of assets, like tokens, without needing a minimum balance in the native token. - -For instance, the [Assets pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank}, may increment this counter for an account holding sufficient tokens. - -#### Account Deactivation - -In Polkadot SDK-based chains, an account is deactivated when its reference counters (such as `providers`, `consumers`, and `sufficient`) reach zero. These counters ensure the account remains active as long as other runtime modules or pallets reference it. - -When all dependencies are cleared and the counters drop to zero, the account becomes deactivated and may be removed from the chain (reaped). This is particularly important in Polkadot SDK-based blockchains, where accounts with balances below the existential deposit threshold are pruned from storage to conserve state resources. - -Each pallet that references an account has cleanup functions that decrement these counters when the pallet no longer depends on the account. Once these counters reach zero, the account is marked for deactivation. - -#### Updating Counters - -The Polkadot SDK provides runtime developers with various methods to manage account lifecycle events, such as deactivation or incrementing reference counters. These methods ensure that accounts cannot be reaped while still in use. - -The following helper functions manage these counters: - -- **`inc_consumers()`**: Increments the `consumer` reference counter for an account, signaling that another pallet depends on it. -- **`dec_consumers()`**: Decrements the `consumer` reference counter, signaling that a pallet no longer relies on the account. -- **`inc_providers()`**: Increments the `provider` reference counter, ensuring the account remains active. -- **`dec_providers()`**: Decrements the `provider` reference counter, allowing for account deactivation when no longer in use. -- **`inc_sufficients()`**: Increments the `sufficient` reference counter for accounts that hold sufficient assets. -- **`dec_sufficients()`**: Decrements the `sufficient` reference counter. - -To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. - -The `System` pallet offers three query functions to assist developers in tracking account states: - -- **[`can_inc_consumer()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_inc_consumer){target=\_blank}**: Checks if the account can safely increment the consumer reference. -- **[`can_dec_provider()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_dec_provider){target=\_blank}**: Ensures that no consumers exist before allowing the decrement of the provider counter. -- **[`is_provider_required()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.is_provider_required){target=\_blank}**: Verifies whether the account still has any active consumer references. - -This modular and flexible system of reference counters tightly controls the lifecycle of accounts in Polkadot SDK-based blockchains, preventing the accidental removal or retention of unneeded accounts. You can refer to the [System pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html){target=\_blank} for more details. - - -## Account Balance Types - -In the Polkadot ecosystem, account balances are categorized into different types based on how the funds are utilized and their availability. These balance types determine the actions that can be performed, such as transferring tokens, paying transaction fees, or participating in governance activities. Understanding these balance types helps developers manage user accounts and implement balance-dependent logic. - -!!! note "A more efficient distribution of account balance types is in development" - Soon, pallets in the Polkadot SDK will implement the [`Fungible` trait](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} (see the [tracking issue](https://github.com/paritytech/polkadot-sdk/issues/226){target=\_blank} for more details). For example, the [`transaction-storage`](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_storage/index.html){target=\_blank} pallet changed the implementation of the [`Currency`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/currency/index.html){target=\_blank} trait (see the [Refactor transaction storage pallet to use fungible traits](https://github.com/paritytech/polkadot-sdk/pull/1800){target=\_blank} PR for further details): - - ```rust - type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - ``` - - To the [`Fungible`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} trait: - - ```rust - type BalanceOf = <::Currency as FnInspect<::AccountId>>::Balance; - ``` - - This update will enable more efficient use of account balances, allowing the free balance to be utilized for on-chain activities such as setting proxies and managing identities. - -### Balance Types - -The five main balance types are: - -- **Free balance**: Represents the total tokens available to the account for any on-chain activity, including staking, governance, and voting. However, it may not be fully spendable or transferrable if portions of it are locked or reserved. -- **Locked balance**: Portions of the free balance that cannot be spent or transferred because they are tied up in specific activities like [staking](https://wiki.polkadot.com/learn/learn-staking/#nominating-validators){target=\_blank}, [vesting](https://wiki.polkadot.com/learn/learn-guides-transfers/#vested-transfers-with-the-polkadot-js-ui){target=\_blank}, or participating in [governance](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank}. While the tokens remain part of the free balance, they are non-transferable for the duration of the lock. -- **Reserved balance**: Funds locked by specific system actions, such as setting up an [identity](https://wiki.polkadot.com/learn/learn-identity/){target=\_blank}, creating [proxies](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}, or submitting [deposits for governance proposals](https://wiki.polkadot.com/learn/learn-guides-polkadot-opengov/#claiming-opengov-deposits){target=\_blank}. These tokens are not part of the free balance and cannot be spent unless they are unreserved. -- **Spendable balance**: The portion of the free balance that is available for immediate spending or transfers. It is calculated by subtracting the maximum of locked or reserved amounts from the free balance, ensuring that existential deposit limits are met. -- **Untouchable balance**: Funds that cannot be directly spent or transferred but may still be utilized for on-chain activities, such as governance participation or staking. These tokens are typically tied to certain actions or locked for a specific period. - -The spendable balance is calculated as follows: - -```text -spendable = free - max(locked - reserved, ED) -``` - -Here, `free`, `locked`, and `reserved` are defined above. The `ED` represents the [existential deposit](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank}, the minimum balance required to keep an account active and prevent it from being reaped. You may find you can't see all balance types when looking at your account via a wallet. Wallet providers often display only spendable, locked, and reserved balances. - -### Locks - -Locks are applied to an account's free balance, preventing that portion from being spent or transferred. Locks are automatically placed when an account participates in specific on-chain activities, such as staking or governance. Although multiple locks may be applied simultaneously, they do not stack. Instead, the largest lock determines the total amount of locked tokens. - -Locks follow these basic rules: - -- If different locks apply to varying amounts, the largest lock amount takes precedence. -- If multiple locks apply to the same amount, the lock with the longest duration governs when the balance can be unlocked. - -#### Locks Example - -Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: - -- 80 DOT is staked with a 28-day lock period. -- 24 DOT is locked for governance with a 1x conviction and a 7-day lock period. -- 4 DOT is locked for governance with a 6x conviction and a 224-day lock period. - -In this case, the total locked amount is 80 DOT because only the largest lock (80 DOT from staking) governs the locked balance. These 80 DOT will be released at different times based on the lock durations. In this example, the 24 DOT locked for governance will be released first since the shortest lock period is seven days. The 80 DOT stake with a 28-day lock period is released next. Now, all that remains locked is the 4 DOT for governance. After 224 days, all 80 DOT (minus the existential deposit) will be free and transferable. - -![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) - -#### Edge Cases for Locks - -In scenarios where multiple convictions and lock periods are active, the lock duration and amount are determined by the longest period and largest amount. For example, if you delegate with different convictions and attempt to undelegate during an active lock period, the lock may be extended for the full amount of tokens. For a detailed discussion on edge case lock behavior, see this [Stack Exchange post](https://substrate.stackexchange.com/questions/5067/delegating-and-undelegating-during-the-lock-period-extends-it-for-the-initial-am){target=\_blank}. - -### Balance Types on Polkadot.js - -Polkadot.js provides a user-friendly interface for managing and visualizing various account balances on Polkadot and Kusama networks. When interacting with Polkadot.js, you will encounter multiple balance types that are critical for understanding how your funds are distributed and restricted. This section explains how different balances are displayed in the Polkadot.js UI and what each type represents. - -![](/images/reference/parachains/accounts/accounts-02.webp) - -The most common balance types displayed on Polkadot.js are: - -- **Total balance**: The total number of tokens available in the account. This includes all tokens, whether they are transferable, locked, reserved, or vested. However, the total balance does not always reflect what can be spent immediately. In this example, the total balance is 0.6274 KSM. - -- **Transferable balance**: Shows how many tokens are immediately available for transfer. It is calculated by subtracting the locked and reserved balances from the total balance. For example, if an account has a total balance of 0.6274 KSM and a transferable balance of 0.0106 KSM, only the latter amount can be sent or spent freely. - -- **Vested balance**: Tokens that allocated to the account but released according to a specific schedule. Vested tokens remain locked and cannot be transferred until fully vested. For example, an account with a vested balance of 0.2500 KSM means that this amount is owned but not yet transferable. - -- **Locked balance**: Tokens that are temporarily restricted from being transferred or spent. These locks typically result from participating in staking, governance, or vested transfers. In Polkadot.js, locked balances do not stack—only the largest lock is applied. For instance, if an account has 0.5500 KSM locked for governance and staking, the locked balance would display 0.5500 KSM, not the sum of all locked amounts. - -- **Reserved balance**: Refers to tokens locked for specific on-chain actions, such as setting an identity, creating a proxy, or making governance deposits. Reserved tokens are not part of the free balance, but can be freed by performing certain actions. For example, removing an identity would unreserve those funds. - -- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period. - -- **Redeemable balance**: The number of tokens that have completed the unbonding period and are ready to be unlocked and transferred again. For example, if an account has a redeemable balance of 0.1000 KSM, those tokens are now available for spending. - -- **Democracy balance**: Reflects the number of tokens locked for governance activities, such as voting on referenda. These tokens are locked for the duration of the governance action and are only released after the lock period ends. - -By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. - -## Address Formats - -The SS58 address format is a core component of the Polkadot SDK that enables accounts to be uniquely identified across Polkadot-based networks. This format is a modified version of Bitcoin's Base58Check encoding, specifically designed to accommodate the multi-chain nature of the Polkadot ecosystem. SS58 encoding allows each chain to define its own set of addresses while maintaining compatibility and checksum validation for security. - -### Basic Format - -SS58 addresses consist of three main components: - -```text -base58encode(concat(,
    , )) -``` - -- **Address type**: A byte or set of bytes that define the network (or chain) for which the address is intended. This ensures that addresses are unique across different Polkadot SDK-based chains. -- **Address**: The public key of the account encoded as bytes. -- **Checksum**: A hash-based checksum which ensures that addresses are valid and unaltered. The checksum is derived from the concatenated address type and address components, ensuring integrity. - -The encoding process transforms the concatenated components into a Base58 string, providing a compact and human-readable format that avoids easily confused characters (e.g., zero '0', capital 'O', lowercase 'l'). This encoding function ([`encode`](https://docs.rs/bs58/latest/bs58/fn.encode.html){target=\_blank}) is implemented exactly as defined in Bitcoin and IPFS specifications, using the same alphabet as both implementations. - -For more details about the SS58 address format implementation, see the [`Ss58Codec`](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Ss58Codec.html){target=\_blank} trait in the Rust Docs. - -### Address Type - -The address type defines how an address is interpreted and to which network it belongs. Polkadot SDK uses different prefixes to distinguish between various chains and address formats: - -- **Address types `0-63`**: Simple addresses, commonly used for network identifiers. -- **Address types `64-127`**: Full addresses that support a wider range of network identifiers. -- **Address types `128-255`**: Reserved for future address format extensions. - -For example, Polkadot’s main network uses an address type of 0, while Kusama uses 2. This ensures that addresses can be used without confusion between networks. - -The address type is always encoded as part of the SS58 address, making it easy to quickly identify the network. Refer to the [SS58 registry](https://github.com/paritytech/ss58-registry){target=\_blank} for the canonical listing of all address type identifiers and how they map to Polkadot SDK-based networks. - -### Address Length - -SS58 addresses can have different lengths depending on the specific format. Address lengths range from as short as 3 to 35 bytes, depending on the complexity of the address and network requirements. This flexibility allows SS58 addresses to adapt to different chains while providing a secure encoding mechanism. - -| Total | Type | Raw account | Checksum | -|-------|------|-------------|----------| -| 3 | 1 | 1 | 1 | -| 4 | 1 | 2 | 1 | -| 5 | 1 | 2 | 2 | -| 6 | 1 | 4 | 1 | -| 7 | 1 | 4 | 2 | -| 8 | 1 | 4 | 3 | -| 9 | 1 | 4 | 4 | -| 10 | 1 | 8 | 1 | -| 11 | 1 | 8 | 2 | -| 12 | 1 | 8 | 3 | -| 13 | 1 | 8 | 4 | -| 14 | 1 | 8 | 5 | -| 15 | 1 | 8 | 6 | -| 16 | 1 | 8 | 7 | -| 17 | 1 | 8 | 8 | -| 35 | 1 | 32 | 2 | - -SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. - -### Checksum Types - -A checksum is applied to validate SS58 addresses. Polkadot SDK uses a Blake2b-512 hash function to calculate the checksum, which is appended to the address before encoding. The checksum length can vary depending on the address format (e.g., 1-byte, 2-byte, or longer), providing varying levels of validation strength. - -The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. - -### Validating Addresses - -SS58 addresses can be validated using the subkey command-line interface or the Polkadot.js API. These tools help ensure an address is correctly formatted and valid for the intended network. The following sections will provide an overview of how validation works with these tools. - -#### Using Subkey - -[Subkey](https://paritytech.github.io/polkadot-sdk/master/subkey/index.html){target=\_blank} is a CLI tool provided by Polkadot SDK for generating and managing keys. It can inspect and validate SS58 addresses. - -The `inspect` command gets a public key and an SS58 address from the provided secret URI. The basic syntax for the `subkey inspect` command is: - -```bash -subkey inspect [flags] [options] uri -``` - -For the `uri` command-line argument, you can specify the secret seed phrase, a hex-encoded private key, or an SS58 address. If the input is a valid address, the `subkey` program displays the corresponding hex-encoded public key, account identifier, and SS58 addresses. - -For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: - -```bash -subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" -``` - -The command displays output similar to the following: - -
    - subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" - Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account: - Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849 - Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR - Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - SS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR -
    - -The `subkey` program assumes an address is based on a public/private key pair. If you inspect an address, the command returns the 32-byte account identifier. - -However, not all addresses in Polkadot SDK-based networks are based on keys. - -Depending on the command-line options you specify and the input you provided, the command output might also display the network for which the address has been encoded. For example: - -```bash -subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" -``` - -The command displays output similar to the following: - -
    - subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" - Public Key URI `12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU` is account: - Network ID/Version: polkadot - Public key (hex): 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Account ID: 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Public key (SS58): 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU - SS58 Address: 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU -
    - -#### Using Polkadot.js API - -To verify an address in JavaScript or TypeScript projects, you can use the functions built into the [Polkadot.js API](https://polkadot.js.org/docs/){target=\_blank}. For example: - -```js -// Import Polkadot.js API dependencies -const { decodeAddress, encodeAddress } = require('@polkadot/keyring'); -const { hexToU8a, isHex } = require('@polkadot/util'); - -// Specify an address to test. -const address = 'INSERT_ADDRESS_TO_TEST'; - -// Check address -const isValidSubstrateAddress = () => { - try { - encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); - - return true; - } catch (error) { - return false; - } -}; - -// Query result -const isValid = isValidSubstrateAddress(); -console.log(isValid); - -``` - -If the function returns `true`, the specified address is a valid address. - -#### Other SS58 Implementations - -Support for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries. - -- **Crystal**: [`wyhaines/base58.cr`](https://github.com/wyhaines/base58.cr){target=\_blank} -- **Go**: [`itering/subscan-plugin`](https://github.com/itering/subscan-plugin){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **TypeScript**: [`subsquid/squid-sdk`](https://github.com/subsquid/squid-sdk){target=\_blank} - - ---- - -Page Title: Randomness - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/randomness/ -- Summary: Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. - -# Randomness - -## Introduction - -Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as "random" numbers on a computer are actually pseudo-random. These numbers rely on an initial "seed," which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\_blank}, [heart rates](https://mdpi.altmetric.com/details/47574324){target=\_blank}, or even [lava lamps](https://en.wikipedia.org/wiki/Lavarand){target=\_blank}. While this may seem random, given the same "seed," the same sequence of numbers will always be generated. - -In a global blockchain network, relying on real-world entropy for randomness isn’t feasible because these inputs vary by time and location. If nodes use different inputs, blockchains can fork. Hence, real-world randomness isn't suitable for use as a seed in blockchain systems. - -Currently, two primary methods for generating randomness in blockchains are used: [`RANDAO`](#randao) and [`VRF`](#vrf) (Verifiable Random Function). Polkadot adopts the `VRF` approach for its randomness. - -## VRF - -A Verifiable Random Function (VRF) is a cryptographic function that generates a random number and proof that ensures the submitter produced the number. This proof allows anyone to verify the validity of the random number. - -Polkadot's VRF is similar to the one used in [**Ouroboros Praos**](https://eprint.iacr.org/2017/573.pdf){target=\_blank}, which secures randomness for block production in systems like [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe){target=\_blank} (Polkadot’s block production mechanism). - -The key difference is that Polkadot's VRF doesn’t rely on a central clock—avoiding the issue of whose clock to trust. Instead, it uses its own past results and slot numbers to simulate time and determine future outcomes. - -### How VRF Works - -Slots on Polkadot are discrete units of time, each lasting six seconds, and can potentially hold a block. Multiple slots form an epoch, with 2400 slots making up one four-hour epoch. - -In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: - -1. A "secret key," unique to each validator, is used for the die roll. -2. An epoch randomness value, derived from the hash of VRF outputs from blocks two epochs ago (N-2), so past randomness influences the current epoch (N). -3. The current slot number. - -This process helps maintain fair randomness across the network. - -Here is a graphical representation: - -![](/images/reference/parachains/randomness/randomness-01.webp) - -The VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). - -The result is checked by the validator against a protocol threshold. If it's below the threshold, the validator becomes a candidate for block production in that slot. - -The validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`. - -So, VRF can be expressed like: - -`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)` - -Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. - -After executing the VRF, the `RESULT` is compared to a protocol-defined `THRESHOLD`. If the `RESULT` is below the `THRESHOLD`, the validator becomes a valid candidate to propose a block for that slot. Otherwise, the validator skips the slot. - -As a result, there may be multiple validators eligible to propose a block for a slot. In this case, the block accepted by other nodes will prevail, provided it is on the chain with the latest finalized block as determined by the GRANDPA finality gadget. It's also possible for no block producers to be available for a slot, in which case the AURA consensus takes over. AURA is a fallback mechanism that randomly selects a validator to produce a block, running in parallel with BABE and only stepping in when no block producers exist for a slot. Otherwise, it remains inactive. - -Because validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. - -To verify resolution of this issue and that Polkadot block times remain near constant-time, see the [PoS Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} page of this documentation. - -## RANDAO - -An alternative on-chain randomness method is Ethereum's RANDAO, where validators perform thousands of hashes on a seed and publish the final hash during a round. The collective input from all validators forms the random number, and as long as one honest validator participates, the randomness is secure. - -To enhance security, RANDAO can optionally be combined with a Verifiable Delay Function (VDF), ensuring that randomness can't be predicted or manipulated during computation. - -For more information about RANDAO, see the [Randomness - RANDAO](https://eth2book.info/capella/part2/building_blocks/randomness/){target=\_blank} section of the Upgrading Ethereum documentation. - -## VDFs - -Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. - -They produce a unique result that can be quickly verified publicly. When combined with RANDAO, feeding RANDAO's output into a VDF introduces a delay that nullifies an attacker's chance to influence the randomness. - -However, VDF likely requires specialized ASIC devices to run separately from standard nodes. - -!!!warning - While only one is needed to secure the system, and they will be open-source and inexpensive, running VDF devices involves significant costs without direct incentives, adding friction for blockchain users. - -## Additional Resources - -For more information about the reasoning for choices made along with proofs, see Polkadot's research on blockchain randomness and sortition in the [Block production](https://research.web3.foundation/Polkadot/protocols/block-production){target=\_blank} entry of the Polkadot Wiki. - -For a discussion with Web3 Foundation researchers about when and under what conditions Polkadot's randomness can be utilized, see the [Discussion on Randomness used in Polkadot](https://github.com/use-ink/ink/issues/57){target=\_blank} issue on GitHub. - - ---- - -Page Title: Register a Local Asset - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md -- Canonical (HTML): https://docs.polkadot.com/chain-interactions/token-operations/register-local-asset/ -- Summary: Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. - -# Register a Local Asset on Asset Hub - -## Introduction - -As detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation. - -This guide will take you through the steps of registering a local asset on the Asset Hub parachain. - -## Prerequisites - -Before you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and a funded wallet with DOT or KSM. - -- For Polkadot Asset Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata. -- For Kusama Asset Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata. - -You need to ensure that your Asset Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees. - -## Steps to Register a Local Asset - -To register a local asset on the Asset Hub parachain, follow these steps: - -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. - - - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`. - - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider. - -2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. - - ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) - -3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column. - - ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) - -4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. - - ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) - -5. Fill in the required fields in the **Create Asset** form: - - 1. **creator account**: The account to be used for creating this asset and setting up the initial metadata. - 2. **asset name**: The descriptive name of the asset you are registering. - 3. **asset symbol**: The symbol that will be used to represent the asset. - 4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface. - 5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested. - 6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id. - 7. Click on the **Next** button. - - ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp) - -6. Choose the accounts for the roles listed below: - - 1. **admin account**: The account designated for continuous administration of the token. - 2. **issuer account**: The account that will be used for issuing this token. - 3. **freezer account**: The account that will be used for performing token freezing operations. - 4. Click on the **Create** button. - - ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp) - -7. Click on the **Sign and Submit** button to complete the asset registration process. - - ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) - -## Verify Asset Registration - -After completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets){target=\_blank} section of the Polkadot.js Apps interface. - -![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp) - -!!! tip - Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field. - -In this way, you have successfully registered a local asset on the Asset Hub parachain. +- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. -For an in-depth explanation about Asset Hub and its features, see the [Asset Hub](/chain-interactions/token-operations/convert-assets/){target=\_blank} entry in the Polkadot Wiki. +## Key Customization Scenarios -## Test Setup Environment +This section covers the most common customization patterns you'll encounter: -You can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank} documentation. +- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. -To set up a test environment, execute the following command: +- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` +- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. -The above command will spawn a lazy fork of Polkadot Asset Hub with the latest block data from the network. If you need to test Kusama Asset Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. +- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. -An Asset Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet. +- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. --- @@ -5836,507 +3476,115 @@ This page contains a list of all relevant tutorials and guides to help you get s | Title | Difficulty | Tools | Description | |---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| | [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. | -| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | - -## Port Ethereum DApps - -| Title | Difficulty | Tools | Description | -|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| -| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | - - ---- - -Page Title: Smart Contracts Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ -- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. - -# Smart Contracts on Polkadot - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. - -Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. - -These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. - -## Native Smart Contracts - -### Introduction - -Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. - -### Smart Contract Development - -The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. - -Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. - -### Technical Architecture - -PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: - -- Enhanced performance for smart contract execution. -- Improved gas efficiency for complex operations. -- Native compatibility with Polkadot's runtime environment. -- Optimized storage and state management. - -### Development Tools and Resources - -Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: - -- Contract development in Solidity or Rust. -- Support for standard Ethereum development libraries. -- Integration with widely used development environments. -- Access to blockchain explorers and indexing solutions. -- Compatibility with contract monitoring and management tools. - -### Cross-Chain Capabilities - -Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. - -### Use Cases - -Polkadot Hub's smart contract platform is suitable for a wide range of applications: - -- DeFi protocols leveraging _cross-chain capabilities_. -- NFT platforms utilizing Polkadot's native token standards. -- Governance systems integrated with Polkadot's democracy mechanisms. -- Cross-chain bridges and asset management solutions. - -## Other Smart Contract Environments - -Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: - -- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). - -- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. - - -Each environment provides unique advantages based on developer preferences and application requirements. - -## Where to Go Next - -Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. - -Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. - -
    - -- Guide __Libraries__ - - --- - - Explore essential libraries to optimize smart contract development and interaction. - - [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) - -- Guide __Dev Environments__ - - --- - - Set up your development environment for seamless contract deployment and testing. - - [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) - -
    - - ---- - -Page Title: Technical Reference Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md -- Canonical (HTML): https://docs.polkadot.com/reference/ -- Summary: Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. - -## Introduction - -The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need. - -Polkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\_blank} to the [governance](/reference/glossary#governance){target=\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants. - -This guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem. - -## Polkadot Hub - -[Polkadot Hub](/reference/polkadot-hub/){target=\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain. - -The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: - -- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications. -- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem. -- **Staking**: Participate in network security and earn rewards by staking DOT. -- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov. -- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities. -- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem. -- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations. - -## Parachains - -[Parachains](/reference/parachains/){target=\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers: - -- **Accounts**: Deep dive into account types, storage, and management on parachains. -- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms. -- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus. -- **Chain data**: Explore data structures, storage layouts, and state management. -- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains. -- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility. -- **Networks**: Learn about networking protocols and peer-to-peer communication. -- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\_blank}, the standard for cross-chain communication. -- **Randomness**: Understand how randomness is generated and used in Polkadot chains. -- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. - -## On-Chain Governance - -[On-Chain governance](/reference/governance/){target=\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details: - -- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums. -- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity. -- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance. -- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system. - -## Glossary - -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: - -- Blockchain concepts (blocks, transactions, state) -- Consensus mechanisms (validators, collators, finality) -- Polkadot-specific terms (relay chain, parachain, XCM, FRAME) -- Network components (nodes, runtimes, storage) -- Governance terminology (origins, tracks, referendums) - -## Tools - -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: - -- **Light clients**: Lightweight solutions for interacting with the network without running full nodes. -- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\_blank} and [PAPI](/reference/tools/papi/){target=\_blank} for building applications. -- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\_blank} and other Rust-based libraries for SDK development. -- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\_blank} for Python developers. -- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\_blank}, and [Omninode](/reference/tools/omninode/){target=\_blank} for smart contract and parachain testing. -- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\_blank} for substrate interaction. -- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\_blank} for XCM integration and asset transfers. - -## Where to Go Next - -For detailed exploration of specific areas, proceed to any of the main sections: - -
    - -- Learn **Polkadot Hub** - - --- - - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. - - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) - -- Learn **Parachains** - - --- - - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. - - [:octicons-arrow-right-24: Reference](/reference/parachains/) - -- Learn **On-Chain Governance** - - --- - - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. - - [:octicons-arrow-right-24: Reference](/reference/governance/) - -- Guide **Glossary** - - --- - - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. - - [:octicons-arrow-right-24: Reference](/reference/glossary/) - -- Guide **Tools** - - --- - - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. - - [:octicons-arrow-right-24: Reference](/reference/tools/) - -
    - - ---- - -Page Title: Transactions - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/ -- Summary: Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. - -# Transactions - -## Introduction - -Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions. - -This guide walks you through the different transaction types and how they're formatted, validated, and processed within the Polkadot ecosystem. You'll also learn how to customize transaction formats and construct transactions for FRAME-based runtimes, ensuring a complete understanding of how transactions are built and executed in Polkadot SDK-based chains. - -## What Is a Transaction? - -In the Polkadot SDK, transactions represent operations that modify the chain's state, bundled into blocks for execution. The term extrinsic is often used to refer to any data that originates outside the runtime and is included in the chain. While other blockchain systems typically refer to these operations as "transactions," the Polkadot SDK adopts the broader term "extrinsic" to capture the wide variety of data types that can be added to a block. - -There are three primary types of transactions (extrinsics) in the Polkadot SDK: - -- **Signed transactions**: Signed by the submitting account, often carrying transaction fees. -- **Unsigned transactions**: Submitted without a signature, often requiring custom validation logic. -- **Inherent transactions**: Typically inserted directly into blocks by block authoring nodes, without gossiping between peers. - -Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. - -### Signed Transactions - -Signed transactions require an account's signature and typically involve submitting a request to execute a runtime call. The signature serves as a form of cryptographic proof that the sender has authorized the action, using their private key. These transactions often involve a transaction fee to cover the cost of execution and incentivize block producers. - -Signed transactions are the most common type of transaction and are integral to user-driven actions, such as token transfers. For instance, when you transfer tokens from one account to another, the sending account must sign the transaction to authorize the operation. - -For example, the [`pallet_balances::Call::transfer_allow_death`](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/pallet/struct.Pallet.html#method.transfer_allow_death){target=\_blank} extrinsic in the Balances pallet allows you to transfer tokens. Since your account initiates this transaction, your account key is used to sign it. You'll also be responsible for paying the associated transaction fee, with the option to include an additional tip to incentivize faster inclusion in the block. - -### Unsigned Transactions - -Unsigned transactions do not require a signature or account-specific data from the sender. Unlike signed transactions, they do not come with any form of economic deterrent, such as fees, which makes them susceptible to spam or replay attacks. Custom validation logic must be implemented to mitigate these risks and ensure these transactions are secure. - -Unsigned transactions typically involve scenarios where including a fee or signature is unnecessary or counterproductive. However, due to the absence of fees, they require careful validation to protect the network. For example, [`pallet_im_online::Call::heartbeat`](https://paritytech.github.io/polkadot-sdk/master/pallet_im_online/pallet/struct.Pallet.html#method.heartbeat){target=\_blank} extrinsic allows validators to send a heartbeat signal, indicating they are active. Since only validators can make this call, the logic embedded in the transaction ensures that the sender is a validator, making the need for a signature or fee redundant. - -Unsigned transactions are more resource-intensive than signed ones because custom validation is required, but they play a crucial role in certain operational scenarios, especially when regular user accounts aren't involved. - -### Inherent Transactions - -Inherent transactions are a specialized type of unsigned transaction that is used primarily for block authoring. Unlike signed or other unsigned transactions, inherent transactions are added directly by block producers and are not broadcasted to the network or stored in the transaction queue. They don't require signatures or the usual validation steps and are generally used to insert system-critical data directly into blocks. - -A key example of an inherent transaction is inserting a timestamp into each block. The [`pallet_timestamp::Call::now`](https://paritytech.github.io/polkadot-sdk/master/pallet_timestamp/pallet/struct.Pallet.html#method.now-1){target=\_blank} extrinsic allows block authors to include the current time in the block they are producing. Since the block producer adds this information, there is no need for transaction validation, like signature verification. The validation in this case is done indirectly by the validators, who check whether the timestamp is within an acceptable range before finalizing the block. - -Another example is the [`paras_inherent::Call::enter`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/paras_inherent/pallet/struct.Pallet.html#method.enter){target=\_blank} extrinsic, which enables parachain collator nodes to send validation data to the relay chain. This inherent transaction ensures that the necessary parachain data is included in each block without the overhead of gossiped transactions. - -Inherent transactions serve a critical role in block authoring by allowing important operational data to be added directly to the chain without needing the validation processes required for standard transactions. - -## Transaction Formats - -Understanding the structure of signed and unsigned transactions is crucial for developers building on Polkadot SDK-based chains. Whether you're optimizing transaction processing, customizing formats, or interacting with the transaction pool, knowing the format of extrinsics, Polkadot's term for transactions, is essential. - -### Types of Transaction Formats - -In Polkadot SDK-based chains, extrinsics can fall into three main categories: - -- **Unchecked extrinsics**: Typically used for signed transactions that require validation. They contain a signature and additional data, such as a nonce and information for fee calculation. Unchecked extrinsics are named as such because they require validation checks before being accepted into the transaction pool. -- **Checked extrinsics**: Typically used for inherent extrinsics (unsigned transactions); these don't require signature verification. Instead, they carry information such as where the extrinsic originates and any additional data required for the block authoring process. -- **Opaque extrinsics**: Used when the format of an extrinsic is not yet fully committed or finalized. They are still decodable, but their structure can be flexible depending on the context. - -### Signed Transaction Data Structure - -A signed transaction typically includes the following components: - -- **Signature**: Verifies the authenticity of the transaction sender. -- **Call**: The actual function or method call the transaction is requesting (for example, transferring funds). -- **Nonce**: Tracks the number of prior transactions sent from the account, helping to prevent replay attacks. -- **Tip**: An optional incentive to prioritize the transaction in block inclusion. -- **Additional data**: Includes details such as spec version, block hash, and genesis hash to ensure the transaction is valid within the correct runtime and chain context. - -Here's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime: - -``` code - + + -``` - -Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. - -### Signed Extensions - -Polkadot SDK also provides the concept of [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}, which allow developers to extend extrinsics with additional data or validation logic before they are included in a block. The [`SignedExtension`](https://paritytech.github.io/try-runtime-cli/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} set helps enforce custom rules or protections, such as ensuring the transaction's validity or calculating priority. - -The transaction queue regularly calls signed extensions to verify a transaction's validity before placing it in the ready queue. This safeguard ensures transactions won't fail in a block. Signed extensions are commonly used to enforce validation logic and protect the transaction pool from spam and replay attacks. - -In FRAME, a signed extension can hold any of the following types by default: - -- **[`AccountId`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/types_common/type.AccountId.html){target=\_blank}**: To encode the sender's identity. -- **[`Call`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Call){target=\_blank}**: To encode the pallet call to be dispatched. This data is used to calculate transaction fees. -- **[`AdditionalSigned`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.AdditionalSigned){target=\_blank}**: To handle any additional data to go into the signed payload allowing you to attach any custom logic prior to dispatching a transaction. -- **[`Pre`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Pre){target=\_blank}**: To encode the information that can be passed from before a call is dispatched to after it gets dispatched. - -Signed extensions can enforce checks like: - -- **[`CheckSpecVersion`](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/extensions/check_spec_version.rs.html){target=\_blank}**: Ensures the transaction is compatible with the runtime's current version. -- **[`CheckWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.CheckWeight.html){target=\_blank}**: Calculates the weight (or computational cost) of the transaction, ensuring the block doesn't exceed the maximum allowed weight. - -These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. - -## Transaction Construction - -Building transactions in the Polkadot SDK involves constructing a payload that can be verified, signed, and submitted for inclusion in a block. Each runtime in the Polkadot SDK has its own rules for validating and executing transactions, but there are common patterns for constructing a signed transaction. - -### Construct a Signed Transaction - -A signed transaction in the Polkadot SDK includes various pieces of data to ensure security, prevent replay attacks, and prioritize processing. Here's an overview of how to construct one: - -1. **Construct the unsigned payload**: Gather the necessary information for the call, including: - - - **Pallet index**: Identifies the pallet where the runtime function resides. - - **Function index**: Specifies the particular function to call in the pallet. - - **Parameters**: Any additional arguments required by the function call. - -2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: - - - **Transaction nonce**: Unique identifier to prevent replay attacks. - - **Era information**: Defines how long the transaction is valid before it's dropped from the pool. - - **Block hash**: Ensures the transaction doesn't execute on the wrong chain or fork. - -3. **Sign the payload**: Using the sender's private key, sign the payload to ensure that the transaction can only be executed by the account holder. -4. **Serialize the signed payload**: Once signed, the transaction must be serialized into a binary format, ensuring the data is compact and easy to transmit over the network. -5. **Submit the serialized transaction**: Finally, submit the serialized transaction to the network, where it will enter the transaction pool and wait for processing by an authoring node. - -The following is an example of how a signed transaction might look: - -``` rust -node_runtime::UncheckedExtrinsic::new_signed( - function.clone(), // some call - sp_runtime::AccountId32::from(sender.public()).into(), // some sending account - node_runtime::Signature::Sr25519(signature.clone()), // the account's signature - extra.clone(), // the signed extensions -) -``` - -### Transaction Encoding - -Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: - -- **`[1]`**: Compact encoded length in bytes of the entire transaction. -- **`[2]`**: A u8 containing 1 byte to indicate whether the transaction is signed or unsigned (1 bit) and the encoded transaction version ID (7 bits). -- **`[3]`**: If signed, this field contains an account ID, an SR25519 signature, and some extra data. -- **`[4]`**: Encoded call data, including pallet and function indices and any required arguments. - -This encoded format ensures consistency and efficiency in processing transactions across the network. By adhering to this format, applications can construct valid transactions and pass them to the network for execution. - -To learn more about how compact encoding works using SCALE, see the [SCALE Codec](https://github.com/paritytech/parity-scale-codec){target=\_blank} README on GitHub. - -### Customize Transaction Construction - -Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: +| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | -- **Custom pallets**: You can define new pallets with custom function calls, each with its own parameters and validation logic. -- **Signed extensions**: Developers can implement custom extensions that modify how transactions are prioritized, validated, or included in blocks. +## Port Ethereum DApps -By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. +| Title | Difficulty | Tools | Description | +|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| +| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | -## Lifecycle of a Transaction -In the Polkadot SDK, transactions are often referred to as extrinsics because the data in transactions originates outside of the runtime. These transactions contain data that initiates changes to the chain state. The most common type of extrinsic is a signed transaction, which is cryptographically verified and typically incurs a fee. This section focuses on how signed transactions are processed, validated, and ultimately included in a block. +--- -### Define Transaction Properties +Page Title: Smart Contracts Overview -The Polkadot SDK runtime defines key transaction properties, such as: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ +- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. -- **Transaction validity**: Ensures the transaction meets all runtime requirements. -- **Signed or unsigned**: Identifies whether a transaction needs to be signed by an account. -- **State changes**: Determines how the transaction modifies the state of the chain. +# Smart Contracts on Polkadot -Pallets, which compose the runtime's logic, define the specific transactions that your chain supports. When a user submits a transaction, such as a token transfer, it becomes a signed transaction, verified by the user's account signature. If the account has enough funds to cover fees, the transaction is executed, and the chain's state is updated accordingly. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -### Process on a Block Authoring Node +Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. -In Polkadot SDK-based networks, some nodes are authorized to author blocks. These nodes validate and process transactions. When a transaction is sent to a node that can produce blocks, it undergoes a lifecycle that involves several stages, including validation and execution. Non-authoring nodes gossip the transaction across the network until an authoring node receives it. The following diagram illustrates the lifecycle of a transaction that's submitted to a network and processed by an authoring node. +Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. -![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } +These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. -### Validate and Queue +## Native Smart Contracts -Once a transaction reaches an authoring node, it undergoes an initial validation process to ensure it meets specific conditions defined in the runtime. This validation includes checks for: +### Introduction -- **Correct nonce**: Ensures the transaction is sequentially valid for the account. -- **Sufficient funds**: Confirms the account can cover any associated transaction fees. -- **Signature validity**: Verifies that the sender's signature matches the transaction data. +Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. -After these checks, valid transactions are placed in the transaction pool, where they are queued for inclusion in a block. The transaction pool regularly re-validates queued transactions to ensure they remain valid before being processed. To reach consensus, two-thirds of the nodes must agree on the order of the transactions executed and the resulting state change. Transactions are validated and queued on the local node in a transaction pool to prepare for consensus. +### Smart Contract Development -#### Transaction Pool +The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. -The transaction pool is responsible for managing valid transactions. It ensures that only transactions that pass initial validity checks are queued. Transactions that fail validation, expire, or become invalid for other reasons are removed from the pool. +Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. -The transaction pool organizes transactions into two queues: +### Technical Architecture -- **Ready queue**: Transactions that are valid and ready to be included in a block. -- **Future queue**: Transactions that are not yet valid but could be in the future, such as transactions with a nonce too high for the current state. +PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: -Details on how the transaction pool validates transactions, including fee and signature handling, can be found in the [`validate_transaction`](https://paritytech.github.io/polkadot-sdk/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction){target=\_blank} method. +- Enhanced performance for smart contract execution. +- Improved gas efficiency for complex operations. +- Native compatibility with Polkadot's runtime environment. +- Optimized storage and state management. -#### Invalid Transactions +### Development Tools and Resources -If a transaction is invalid, for example, due to an invalid signature or insufficient funds, it is rejected and won't be added to the block. Invalid transactions might be rejected for reasons such as: +Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: -- The transaction has already been included in a block. -- The transaction's signature does not match the sender. -- The transaction is too large to fit in the current block. +- Contract development in Solidity or Rust. +- Support for standard Ethereum development libraries. +- Integration with widely used development environments. +- Access to blockchain explorers and indexing solutions. +- Compatibility with contract monitoring and management tools. -### Transaction Ordering and Priority +### Cross-Chain Capabilities -When a node is selected as the next block author, it prioritizes transactions based on weight, length, and tip amount. The goal is to fill the block with high-priority transactions without exceeding its maximum size or computational limits. Transactions are ordered as follows: +Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. -- **Inherents first**: Inherent transactions, such as block timestamp updates, are always placed first. -- **Nonce-based ordering**: Transactions from the same account are ordered by their nonce. -- **Fee-based ordering**: Among transactions with the same nonce or priority level, those with higher fees are prioritized. +### Use Cases -### Transaction Execution +Polkadot Hub's smart contract platform is suitable for a wide range of applications: -Once a block author selects transactions from the pool, the transactions are executed in priority order. As each transaction is processed, the state changes are written directly to the chain's storage. It's important to note that these changes are not cached, meaning a failed transaction won't revert earlier state changes, which could leave the block in an inconsistent state. +- DeFi protocols leveraging _cross-chain capabilities_. +- NFT platforms utilizing Polkadot's native token standards. +- Governance systems integrated with Polkadot's democracy mechanisms. +- Cross-chain bridges and asset management solutions. -Events are also written to storage. Runtime logic should not emit an event before performing the associated actions. If the associated transaction fails after the event was emitted, the event will not revert. +## Other Smart Contract Environments -## Transaction Mortality +Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: -Transactions in the network can be configured as either mortal (with expiration) or immortal (without expiration). Every transaction payload contains a block checkpoint (reference block number and hash) and an era/validity period that determines how many blocks after the checkpoint the transaction remains valid. +- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). -When a transaction is submitted, the network validates it against these parameters. If the transaction is not included in a block within the specified validity window, it is automatically removed from the transaction queue. +- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. -- **Mortal transactions**: Have a finite lifespan and will expire after a specified number of blocks. For example, a transaction with a block checkpoint of 1000 and a validity period of 64 blocks will be valid from blocks 1000 to 1064. -- **Immortal transactions**: Never expire and remain valid indefinitely. To create an immortal transaction, set the block checkpoint to 0 (genesis block), use the genesis hash as a reference, and set the validity period to 0. +Each environment provides unique advantages based on developer preferences and application requirements. -However, immortal transactions pose significant security risks through replay attacks. If an account is reaped (balance drops to zero, account removed) and later re-funded, malicious actors can replay old immortal transactions. +## Where to Go Next -The blockchain maintains only a limited number of prior block hashes for reference validation, called `BlockHashCount`. If your validity period exceeds `BlockHashCount`, the effective validity period becomes the minimum of your specified period and the block hash count. +Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. -## Unique Identifiers for Extrinsics +Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. -Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. +
    -Key differences from traditional blockchains: +- Guide __Libraries__ -- Transaction hashes serve only as fingerprints of transaction information. -- Multiple valid transactions can share the same hash. -- Hash uniqueness assumptions lead to serious issues. + --- -For example, when an account is reaped (removed due to insufficient balance) and later recreated, it resets to nonce 0, allowing identical transactions to be valid at different points: + Explore essential libraries to optimize smart contract development and interaction. -| Block | Extrinsic Index | Hash | Origin | Nonce | Call | Result | -|-------|----------------|------|-----------|-------|---------------------|-------------------------------| -| 100 | 0 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Account A reaped | -| 150 | 5 | 0x02 | Account B | 4 | Transfer 7 DOT to A | Account A created (nonce = 0) | -| 200 | 2 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Successful transaction | + [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) -Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. +- Guide __Dev Environments__ -Additional complexity comes from Polkadot SDK's origin abstraction. Origins can represent collectives, governance bodies, or other non-account entities that don't maintain nonces like regular accounts and might dispatch identical calls multiple times with the same hash values. Each execution occurs in different chain states with different results. + --- -The correct way to uniquely identify an extrinsic on a Polkadot SDK-based chain is to use the block ID (height or hash) and the extrinsic index. Since the Polkadot SDK defines blocks as headers plus ordered arrays of extrinsics, the index position within a canonical block provides guaranteed uniqueness. + Set up your development environment for seamless contract deployment and testing. -## Additional Resources + [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) -For a video overview of the lifecycle of transactions and the types of transactions that exist, see the [Transaction lifecycle](https://www.youtube.com/watch?v=3pfM0GOp02c){target=\_blank} seminar from Parity Tech. +
    --- @@ -6444,436 +3692,3 @@ The system maintains precise conversion mechanisms between: - Different resource metrics within the multi-dimensional model. This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. - - ---- - -Page Title: Transactions Weights and Fees - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/ -- Summary: Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. - -# Transactions Weights and Fees - -## Introductions - -When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop the network from producing new blocks. To protect blockchain resources from being drained or overloaded, you need to manage how they are made available and how they are consumed. The resources to be aware of include: - -- Memory usage -- Storage input and output -- Computation -- Transaction and block size -- State database size - -The Polkadot SDK provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource. Two of the most important mechanisms available to block authors are weights and transaction fees. - -[Weights](/reference/glossary/#weight){target=\_blank} manage the time it takes to validate a block and characterize the time it takes to execute the calls in the block's body. By controlling the execution time a block can consume, weights set limits on storage input, output, and computation. - -Some of the weight allowed for a block is consumed as part of the block's initialization and finalization. The weight might also be used to execute mandatory inherent extrinsic calls. To help ensure blocks don’t consume too much execution time and prevent malicious users from overloading the system with unnecessary calls, weights are combined with transaction fees. - -[Transaction fees](/reference/parachains/blocks-transactions-fees/transactions/#transaction-fees){target=\_blank} provide an economic incentive to limit execution time, computation, and the number of calls required to perform operations. Transaction fees are also used to make the blockchain economically sustainable because they are typically applied to transactions initiated by users and deducted before a transaction request is executed. - -## How Fees are Calculated - -The final fee for a transaction is calculated using the following parameters: - -- **`base fee`**: This is the minimum amount a user pays for a transaction. It is declared a base weight in the runtime and converted to a fee using the [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} conversion. -- **`weight fee`**: A fee proportional to the execution time (input and output and computation) that a transaction consumes. -- **`length fee`**: A fee proportional to the encoded length of the transaction. -- **`tip`**: An optional tip to increase the transaction’s priority, giving it a higher chance to be included in the transaction queue. - -The base fee and proportional weight and length fees constitute the inclusion fee. The inclusion fee is the minimum fee that must be available for a transaction to be included in a block. - -```text -inclusion fee = base fee + weight fee + length fee -``` - -Transaction fees are withdrawn before the transaction is executed. After the transaction is executed, the weight can be adjusted to reflect the resources used. If a transaction uses fewer resources than expected, the transaction fee is corrected, and the adjusted transaction fee is deposited. - -## Using the Transaction Payment Pallet - -The [Transaction Payment pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/transaction-payment){target=\_blank} provides the basic logic for calculating the inclusion fee. You can also use the Transaction Payment pallet to: - -- Convert a weight value into a deductible fee based on a currency type using [`Config::WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank}. -- Update the fee for the next block by defining a multiplier based on the chain’s final state at the end of the previous block using [`Config::FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank}. -- Manage the withdrawal, refund, and deposit of transaction fees using [`Config::OnChargeTransaction`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.OnChargeTransaction){target=\_blank}. - -You can learn more about these configuration traits in the [Transaction Payment documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_payment/index.html){target=\_blank}. - -### Understanding the Inclusion Fee - -The formula for calculating the inclusion fee is as follows: - -```text -inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] -``` - -And then, for calculating the final fee: - -```text -final_fee = inclusion_fee + tip -``` - -In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. - -- The `base_fee` derived from the base weight covers inclusion overhead like signature verification. -- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic. -- The `weight_fee` fee is calculated using two parameters: - - The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics. - - The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity. - -To convert the weight to `Currency`, the runtime must define a `WeightToFee` struct that implements a conversion function, [`Convert`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/struct.Pallet.html#method.weight_to_fee){target=\_blank}. - -Note that the extrinsic sender is charged the inclusion fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution. - -### Accounts with an Insufficient Balance - -If an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum existential deposit—then you should ensure the transaction is canceled so that no fee is deducted and the transaction does not begin execution. - -The Polkadot SDK doesn't enforce this rollback behavior. However, this scenario would be rare because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block. - -### Fee Multipliers - -The inclusion fee formula always results in the same fee for the same input. However, weight can be dynamic and—based on how [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} is defined—the final fee can include some degree of variability. -The Transaction Payment pallet provides the [`FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank} configurable parameter to account for this variability. - -The Polkadot network inspires the default update function and implements a targeted adjustment in which a target saturation level of block weight is defined. If the previous block is more saturated, the fees increase slightly. Similarly, if the last block has fewer transactions than the target, fees are decreased by a small amount. For more information about fee multiplier adjustments, see the [Web3 Research Page](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank}. - -## Transactions with Special Requirements - -Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: - -- Bonds are a type of fee that might be returned or slashed after some on-chain event. For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior. -- Deposits are fees that might be returned later. For example, you might require users to pay a deposit to execute an operation that uses storage. The user’s deposit could be returned if a subsequent operation frees up storage. -- Burn operations are used to pay for a transaction based on its internal logic. For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased state size. -- Limits enable you to enforce constant or configurable limits on specific operations. For example, the default [Staking pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/staking){target=\_blank} only allows nominators to nominate 16 validators to limit the complexity of the validator election process. - -It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. - -## Default Weight Annotations - -All dispatchable functions in the Polkadot SDK must specify a weight. The way of doing that is using the annotation-based system that lets you combine fixed values for database read/write weight and/or fixed values based on benchmarks. The most basic example would look like this: - -```rust -#[pallet::weight(100_000)] -fn my_dispatchable() { - // ... -} -``` - -Note that the [`ExtrinsicBaseWeight`](https://crates.parity.io/frame_support/weights/constants/struct.ExtrinsicBaseWeight.html){target=\_blank} is automatically added to the declared weight to account for the costs of simply including an empty extrinsic into a block. - -### Weights and Database Read/Write Operations - -To make weight annotations independent of the deployed database backend, they are defined as a constant and then used in the annotations when expressing database accesses performed by the dispatchable: - -```rust -#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] -fn my_dispatchable() { - // ... -} -``` - -This dispatchable allows one database to read and two to write, in addition to other things that add the additional 20,000. Database access is generally every time a value declared inside the [`#[pallet::storage]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} block is accessed. However, unique accesses are counted because after a value is accessed, it is cached, and reaccessing it does not result in a database operation. That is: - -- Multiple reads of the exact value count as one read. -- Multiple writes of the exact value count as one write. -- Multiple reads of the same value, followed by a write to that value, count as one read and one write. -- A write followed by a read-only counts as one write. - -### Dispatch Classes - -Dispatches are broken into three classes: - -- Normal -- Operational -- Mandatory - -If a dispatch is not defined as `Operational` or `Mandatory` in the weight annotation, the dispatch is identified as `Normal` by default. You can specify that the dispatchable uses another class like this: - -```rust -#[pallet::dispatch((DispatchClass::Operational))] -fn my_dispatchable() { - // ... -} -``` - -This tuple notation also allows you to specify a final argument determining whether the user is charged based on the annotated weight. If you don't specify otherwise, `Pays::Yes` is assumed: - -```rust -#[pallet::dispatch(DispatchClass::Normal, Pays::No)] -fn my_dispatchable() { - // ... -} -``` - -#### Normal Dispatches - -Dispatches in this class represent normal user-triggered transactions. These types of dispatches only consume a portion of a block's total weight limit. For information about the maximum portion of a block that can be consumed for normal dispatches, see [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Normal dispatches are sent to the transaction pool. - -#### Operational Dispatches - -Unlike normal dispatches, which represent the usage of network capabilities, operational dispatches are those that provide network capabilities. Operational dispatches can consume the entire weight limit of a block. They are not bound by the [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Dispatches in this class are given maximum priority and are exempt from paying the [`length_fee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/){target=\_blank}. - -#### Mandatory Dispatches - -Mandatory dispatches are included in a block even if they cause the block to surpass its weight limit. You can only use the mandatory dispatch class for inherent transactions that the block author submits. This dispatch class is intended to represent functions in the block validation process. Because these dispatches are always included in a block regardless of the function weight, the validation process must prevent malicious nodes from abusing the function to craft valid but impossibly heavy blocks. You can typically accomplish this by ensuring that: - -- The operation performed is always light. -- The operation can only be included in a block once. - -To make it more difficult for malicious nodes to abuse mandatory dispatches, they cannot be included in blocks that return errors. This dispatch class serves the assumption that it is better to allow an overweight block to be created than not to allow any block to be created at all. - -### Dynamic Weights - -In addition to purely fixed weights and constants, the weight calculation can consider the input arguments of a dispatchable. The weight should be trivially computable from the input arguments with some basic arithmetic: - -```rust -use frame_support:: { - dispatch:: { - DispatchClass::Normal, - Pays::Yes, - }, - weights::Weight, -}; - -#[pallet::weight(FunctionOf( - |args: (&Vec,)| args.0.len().saturating_mul(10_000), - ) -] -fn handle_users(origin, calls: Vec) { - // Do something per user -} -``` - -## Post Dispatch Weight Correction - -Depending on the execution logic, a dispatchable function might consume less weight than was prescribed pre-dispatch. To correct weight, the function declares a different return type and returns its actual weight: - -```rust -#[pallet::weight(10_000 + 500_000_000)] -fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo { - let was_heavy = do_calculation(input); - - if (was_heavy) { - // None means "no correction" from the weight annotation. - Ok(None.into()) - } else { - // Return the actual weight consumed. - Ok(Some(10_000).into()) - } -} -``` - -## Custom Fees - -You can also define custom fee systems through custom weight functions or inclusion fee functions. - -### Custom Weights - -Instead of using the default weight annotations, you can create a custom weight calculation type using the weights module. The custom weight calculation type must implement the following traits: - -- [`WeighData`](https://crates.parity.io/frame_support/weights/trait.WeighData.html){target=\_blank} to determine the weight of the dispatch. -- [`ClassifyDispatch`](https://crates.parity.io/frame_support/weights/trait.ClassifyDispatch.html){target=\_blank} to determine the class of the dispatch. -- [`PaysFee`](https://crates.parity.io/frame_support/weights/trait.PaysFee.html){target=\_blank} to determine whether the sender of the dispatch pays fees. - -The Polkadot SDK then bundles the output information of the three traits into the [`DispatchInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.DispatchInfo.html){target=\_blank} struct and provides it by implementing the [`GetDispatchInfo`](https://docs.rs/frame-support/latest/frame_support/dispatch/trait.GetDispatchInfo.html){target=\_blank} for all `Call` variants and opaque extrinsic types. This is used internally by the System and Executive modules. - -`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over T, which gets resolved into the tuple of all dispatch arguments except for the origin. The following example illustrates a struct that calculates the weight as `m * len(args)`, where `m` is a given multiplier and args is the concatenated tuple of all dispatch arguments. In this example, the dispatch class is `Operational` if the transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length exceeds 10 bytes. - -```rust -struct LenWeight(u32); -impl WeighData for LenWeight { - fn weigh_data(&self, target: T) -> Weight { - let multiplier = self.0; - let encoded_len = target.encode().len() as u32; - multiplier * encoded_len - } -} - -impl ClassifyDispatch for LenWeight { - fn classify_dispatch(&self, target: T) -> DispatchClass { - let encoded_len = target.encode().len() as u32; - if encoded_len > 100 { - DispatchClass::Operational - } else { - DispatchClass::Normal - } - } -} - -impl PaysFee { - fn pays_fee(&self, target: T) -> Pays { - let encoded_len = target.encode().len() as u32; - if encoded_len > 10 { - Pays::Yes - } else { - Pays::No - } - } -} -``` - -A weight calculator function can also be coerced to the final type of the argument instead of defining it as a vague type that can be encoded. The code would roughly look like this: - -```rust -struct CustomWeight; -impl WeighData<(&u32, &u64)> for CustomWeight { - fn weigh_data(&self, target: (&u32, &u64)) -> Weight { - ... - } -} - -// given a dispatch: -#[pallet::call] -impl, I: 'static> Pallet { - #[pallet::weight(CustomWeight)] - fn foo(a: u32, b: u64) { ... } -} -``` - -In this example, the `CustomWeight` can only be used in conjunction with a dispatch with a particular signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because there aren't any assumptions about ``. - -#### Custom Inclusion Fee - -The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. - -```rust -// Assume this is the balance type -type Balance = u64; - -// Assume we want all the weights to have a `100 + 2 * w` conversion to fees -struct CustomWeightToFee; -impl WeightToFee for CustomWeightToFee { - fn convert(w: Weight) -> Balance { - let a = Balance::from(100); - let b = Balance::from(2); - let w = Balance::from(w); - a + b * w - } -} - -parameter_types! { - pub const ExtrinsicBaseWeight: Weight = 10_000_000; -} - -impl frame_system::Config for Runtime { - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; -} - -parameter_types! { - pub const TransactionByteFee: Balance = 10; -} - -impl transaction_payment::Config { - type TransactionByteFee = TransactionByteFee; - type WeightToFee = CustomWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} - -struct TargetedFeeAdjustment(sp_std::marker::PhantomData); -impl> WeightToFee for TargetedFeeAdjustment { - fn convert(multiplier: Fixed128) -> Fixed128 { - // Don't change anything. Put any fee update info here. - multiplier - } -} -``` - -## Additional Resources - -You now know the weight system, how it affects transaction fee computation, and how to specify weights for your dispatchable calls. The next step is determining the correct weight for your dispatchable operations. You can use Substrate benchmarking functions and frame-benchmarking calls to test your functions with different parameters and empirically determine the proper weight in their worst-case scenarios. - -- [Benchmark](/parachains/customize-runtime/pallet-development/benchmark-pallet/) -- [`SignedExtension`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} -- [Custom weights for the Example pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/examples/basic/src/weights.rs){target=\_blank} -- [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} - - ---- - -Page Title: XCM Tools - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/xcm-tools/ -- Summary: Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. - -# XCM Tools - -## Introduction - -As described in the [Interoperability](/develop/interoperability){target=\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem. - -As XCM is central to enabling communication between blockchains, developers need robust tools to help interact with, build, and test XCM messages. Several XCM tools simplify working with the protocol by providing libraries, frameworks, and utilities that enhance the development process, ensuring that applications built within the Polkadot ecosystem can efficiently use cross-chain functionalities. - -## Popular XCM Tools - -### Moonsong Labs XCM Tools - -[Moonsong Labs XCM Tools](https://github.com/Moonsong-Labs/xcm-tools){target=\_blank} provides a collection of scripts for managing and testing XCM operations between Polkadot SDK-based runtimes. These tools allow performing tasks like asset registration, channel setup, and XCM initialization. Key features include: - -- **Asset registration**: Registers assets, setting units per second (up-front fees), and configuring error (revert) codes. -- **XCM initializer**: Initializes XCM, sets default XCM versions, and configures revert codes for XCM-related precompiles. -- **HRMP manipulator**: Manages HRMP channel actions, including opening, accepting, or closing channels. -- **XCM-Transactor-Info-Setter**: Configures transactor information, including extra weight and fee settings. -- **Decode XCM**: Decodes XCM messages on the relay chain or parachains to help interpret cross-chain communication. - -To get started, clone the repository and install the required dependencies: - -```bash -git clone https://github.com/Moonsong-Labs/xcm-tools && -cd xcm-tools && -yarn install -``` - -For a full overview of each script, visit the [scripts](https://github.com/Moonsong-Labs/xcm-tools/tree/main/scripts){target=\_blank} directory or refer to the [official documentation](https://github.com/Moonsong-Labs/xcm-tools/blob/main/README.md){target=\_blank} on GitHub. - -### ParaSpell - -[ParaSpell](/reference/tools/paraspell/){target=\_blank} is a collection of open-source XCM tools that streamline cross-chain asset transfers and interactions across the Polkadot and Kusama ecosystems. It provides developers with an intuitive interface to build, test, and deploy interoperable dApps, featuring message composition, decoding, and practical utilities for parachain interactions that simplify debugging and cross-chain communication optimization. - -### Astar XCM Tools - -The [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks: - -- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command. -- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments. -- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs. - -To start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\_blank} and compile the xcm-tools package: - -```bash -git clone https://github.com/AstarNetwork/Astar && -cd Astar && -cargo build --release -p xcm-tools -``` - -After compiling, verify the setup with the following command: - -```bash -./target/release/xcm-tools --help -``` -For more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\_blank}. - -### Chopsticks - -The Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\_blank} about XCM. - -### Moonbeam XCM SDK - -The [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank} of the origin or destination assets or which extrinsics are used on which networks. - -The SDK consists of two main packages: - -- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem. -- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum. - -Key features include: - -- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection. -- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems. -- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality. -- **Comprehensive documentation**: Includes usage guides and API references for both packages. - -For detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\_blank}. diff --git a/.ai/categories/parachains.md b/.ai/categories/parachains.md index 309865038..cf727d514 100644 --- a/.ai/categories/parachains.md +++ b/.ai/categories/parachains.md @@ -1837,440 +1837,6 @@ Now that you've added the pallet to your runtime, you can follow these steps to - [frame-omni-bencher Tool](https://paritytech.github.io/polkadot-sdk/master/frame_omni_bencher/index.html){target=\_blank} ---- - -Page Title: Blocks - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/ -- Summary: Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. - -# Blocks - -## Introduction - -In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the network. By understanding these concepts, developers can better grasp how blockchains maintain security, consistency, and performance within the Polkadot ecosystem. - -## What is a Block? - -In the Polkadot SDK, a block is a fundamental unit that encapsulates both the header and an array of transactions. The block header includes critical metadata to ensure the integrity and sequence of the blockchain. Here's a breakdown of its components: - -- **Block height**: Indicates the number of blocks created in the chain so far. -- **Parent hash**: The hash of the previous block, providing a link to maintain the blockchain's immutability. -- **Transaction root**: Cryptographic digest summarizing all transactions in the block. -- **State root**: A cryptographic digest representing the post-execution state. -- **Digest**: Additional information that can be attached to a block, such as consensus-related messages. - -Each transaction is part of a series that is executed according to the runtime's rules. The transaction root is a cryptographic digest of this series, which prevents alterations and enables succinct verification by light clients. This verification process allows light clients to confirm whether a transaction exists in a block with only the block header, avoiding downloading the entire block. - -## Block Production - -When an authoring node is authorized to create a new block, it selects transactions from the transaction queue based on priority. This step, known as block production, relies heavily on the executive module to manage the initialization and finalization of blocks. The process is summarized as follows: - -### Initialize Block - -The block initialization process begins with a series of function calls that prepare the block for transaction execution: - -1. **Call `on_initialize`**: The executive module calls the [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hook from the system pallet and other runtime pallets to prepare for the block's transactions. -2. **Coordinate runtime calls**: Coordinates function calls in the order defined by the transaction queue. -3. **Verify information**: Once [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} functions are executed, the executive module checks the parent hash in the block header and the trie root to verify information is consistent. - -### Finalize Block - -Once transactions are processed, the block must be finalized before being broadcast to the network. The finalization steps are as follows: - -1. **Call `on_finalize`**: The executive module calls the [`on_finalize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_finalize){target=\_blank} hooks in each pallet to ensure any remaining state updates or checks are completed before the block is sealed and published. -2. **Verify information**: The block's digest and storage root in the header are checked against the initialized block to ensure consistency. -3. **Call `on_idle`**: The [`on_idle`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_idle){target=\_blank} hook is triggered to process any remaining tasks using the leftover weight from the block. - -## Block Authoring and Import - -Once the block is finalized, it is gossiped to other nodes in the network. Nodes follow this procedure: - -1. **Receive transactions**: The authoring node collects transactions from the network. -2. **Validate**: Transactions are checked for validity. -3. **Queue**: Valid transactions are placed in the transaction pool for execution. -4. **Execute**: State changes are made as the transactions are executed. -5. **Publish**: The finalized block is broadcast to the network. - -### Block Import Queue - -After a block is published, other nodes on the network can import it into their chain state. The block import queue is part of the outer node in every Polkadot SDK-based node and ensures incoming blocks are valid before adding them to the node's state. - -In most cases, you don't need to know details about how transactions are gossiped or how other nodes on the network import blocks. The following traits are relevant, however, if you plan to write any custom consensus logic or want a deeper dive into the block import queue: - -- **[`ImportQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.ImportQueue.html){target=\_blank}**: The trait that defines the block import queue. -- **[`Link`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Link.html){target=\_blank}**: The trait that defines the link between the block import queue and the network. -- **[`BasicQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/struct.BasicQueue.html){target=\_blank}**: A basic implementation of the block import queue. -- **[`Verifier`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Verifier.html){target=\_blank}**: The trait that defines the block verifier. -- **[`BlockImport`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/block_import/trait.BlockImport.html){target=\_blank}**: The trait that defines the block import process. - -These traits govern how blocks are validated and imported across the network, ensuring consistency and security. - -## Additional Resources - -To learn more about the block structure in the Polkadot SDK runtime, see the [`Block` reference](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.Block.html){target=\_blank} entry in the Rust Docs. - - ---- - -Page Title: Chain Data - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/chain-data/ -- Summary: Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. - -# Chain Data - -## Introduction - -Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you can ensure seamless communication between your applications and the blockchain. - -## Application Development - -You might not be directly involved in building frontend applications as a blockchain developer. However, most applications that run on a blockchain require some form of frontend or user-facing client to enable users or other programs to access and modify the data that the blockchain stores. For example, you might develop a browser-based, mobile, or desktop application that allows users to submit transactions, post articles, view their assets, or track previous activity. The backend for that application is configured in the runtime logic for your blockchain, but the frontend client makes the runtime features accessible to your users. - -For your custom chain to be useful to others, you'll need to provide a client application that allows users to view, interact with, or update information that the blockchain keeps track of. In this article, you'll learn how to expose information about your runtime so that client applications can use it, see examples of the information exposed, and explore tools and libraries that use it. - -## Understand Metadata - -Polkadot SDK-based blockchain networks are designed to expose their runtime information, allowing developers to learn granular details regarding pallets, RPC calls, and runtime APIs. The metadata also exposes their related documentation. The chain's metadata is [SCALE-encoded](/reference/parachains/data-encoding/){target=\_blank}, allowing for the development of browser-based, mobile, or desktop applications to support the chain's runtime upgrades seamlessly. It is also possible to develop applications compatible with multiple Polkadot SDK-based chains simultaneously. - -## Expose Runtime Information as Metadata - -To interact with a node or the state of the blockchain, you need to know how to connect to the chain and access the exposed runtime features. This interaction involves a Remote Procedure Call (RPC) through a node endpoint address, commonly through a secure web socket connection. - -An application developer typically needs to know the contents of the runtime logic, including the following details: - -- Version of the runtime the application is connecting to. -- Supported APIs. -- Implemented pallets. -- Defined functions and corresponding type signatures. -- Defined custom types. -- Exposed parameters users can set. - -As the Polkadot SDK is modular and provides a composable framework for building blockchains, there are limitless opportunities to customize the schema of properties. Each runtime can be configured with its properties, including function calls and types, which can be changed over time with runtime upgrades. - -The Polkadot SDK enables you to generate the runtime metadata schema to capture information unique to a runtime. The metadata for a runtime describes the pallets in use and types defined for a specific runtime version. The metadata includes information about each pallet's storage items, functions, events, errors, and constants. The metadata also provides type definitions for any custom types included in the runtime. - -Metadata provides a complete inventory of a chain's runtime. It is key to enabling client applications to interact with the node, parse responses, and correctly format message payloads sent back to that chain. - -## Generate Metadata - -To efficiently use the blockchain's networking resources and minimize the data transmitted over the network, the metadata schema is encoded using the [Parity SCALE Codec](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank}. This encoding is done automatically through the [`scale-info`](https://docs.rs/scale-info/latest/scale_info/){target=\_blank}crate. - -At a high level, generating the metadata involves the following steps: - -1. The pallets in the runtime logic expose callable functions, types, parameters, and documentation that need to be encoded in the metadata. -2. The `scale-info` crate collects type information for the pallets in the runtime, builds a registry of the pallets that exist in a particular runtime, and the relevant types for each pallet in the registry. The type information is detailed enough to enable encoding and decoding for every type. -3. The [`frame-metadata`](https://github.com/paritytech/frame-metadata){target=\_blank} crate describes the structure of the runtime based on the registry provided by the `scale-info` crate. -4. Nodes provide the RPC method `state_getMetadata` to return a complete description of all the types in the current runtime as a hex-encoded vector of SCALE-encoded bytes. - -## Retrieve Runtime Metadata - -The type information provided by the metadata enables applications to communicate with nodes using different runtime versions and across chains that expose different calls, events, types, and storage items. The metadata also allows libraries to generate a substantial portion of the code needed to communicate with a given node, enabling libraries like [`subxt`](https://github.com/paritytech/subxt){target=\_blank} to generate frontend interfaces that are specific to a target chain. - -### Use Polkadot.js - -Visit the [Polkadot.js Portal](https://polkadot.js.org/apps/#/rpc){target=\_blank} and select the **Developer** dropdown in the top banner. Select **RPC Calls** to make the call to request metadata. Follow these steps to make the RPC call: - -1. Select **state** as the endpoint to call. -2. Select **`getMetadata(at)`** as the method to call. -3. Click **Submit RPC call** to submit the call and return the metadata in JSON format. - -### Use Curl - -You can fetch the metadata for the network by calling the node's RPC endpoint. This request returns the metadata in bytes rather than human-readable JSON: - -```sh -curl -H "Content-Type: application/json" \ --d '{"id":1, "jsonrpc":"2.0", "method": "state_getMetadata"}' \ -https://rpc.polkadot.io - -``` - -### Use Subxt - -[`subxt`](https://github.com/paritytech/subxt){target=\_blank} may also be used to fetch the metadata of any data in a human-readable JSON format: - -```sh -subxt metadata --url wss://rpc.polkadot.io --format json > spec.json -``` - -Another option is to use the [`subxt` explorer web UI](https://paritytech.github.io/subxt-explorer/#/){target=\_blank}. - -## Client Applications and Metadata - -The metadata exposes the expected way to decode each type, meaning applications can send, retrieve, and process application information without manual encoding and decoding. Client applications must use the [SCALE codec library](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank} to encode and decode RPC payloads to use the metadata. Client applications use the metadata to interact with the node, parse responses, and format message payloads sent to the node. - -## Metadata Format - -Although the SCALE-encoded bytes can be decoded using the `frame-metadata` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} libraries, there are other tools, such as `subxt` and the Polkadot-JS API, that can convert the raw data to human-readable JSON format. - -The types and type definitions included in the metadata returned by the `state_getMetadata` RPC call depend on the runtime's metadata version. - -In general, the metadata includes the following information: - -- A constant identifying the file as containing metadata. -- The version of the metadata format used in the runtime. -- Type definitions for all types used in the runtime and generated by the `scale-info` crate. -- Pallet information for the pallets included in the runtime in the order that they are defined in the `construct_runtime` macro. - -!!!tip - Depending on the frontend library used (such as the [Polkadot API](https://papi.how/){target=\_blank}), they may format the metadata differently than the raw format shown. - -The following example illustrates a condensed and annotated section of metadata decoded and converted to JSON: - -```json -[ - 1635018093, - { - "V14": { - "types": { - "types": [{}] - }, - "pallets": [{}], - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [{}] - }, - "ty": 141 - } - } -] - -``` - -The constant `1635018093` is a magic number that identifies the file as a metadata file. The rest of the metadata is divided into the `types`, `pallets`, and `extrinsic` sections: - -- The `types` section contains an index of the types and information about each type's type signature. -- The `pallets` section contains information about each pallet in the runtime. -- The `extrinsic` section describes the type identifier and transaction format version that the runtime uses. - -Different extrinsic versions can have varying formats, especially when considering [signed transactions](/reference/parachains/blocks-transactions-fees/transactions/#signed-transactions){target=\_blank}. - -### Pallets - -The following is a condensed and annotated example of metadata for a single element in the `pallets` array (the [`sudo`](https://paritytech.github.io/polkadot-sdk/master/pallet_sudo/index.html){target=\_blank} pallet): - -```json -{ - "name": "Sudo", - "storage": { - "prefix": "Sudo", - "entries": [ - { - "name": "Key", - "modifier": "Optional", - "ty": { - "Plain": 0 - }, - "default": [0], - "docs": ["The `AccountId` of the sudo key."] - } - ] - }, - "calls": { - "ty": 117 - }, - "event": { - "ty": 42 - }, - "constants": [], - "error": { - "ty": 124 - }, - "index": 8 -} - -``` - -Every element metadata contains the name of the pallet it represents and information about its storage, calls, events, and errors. You can look up details about the definition of the calls, events, and errors by viewing the type index identifier. The type index identifier is the `u32` integer used to access the type information for that item. For example, the type index identifier for calls in the Sudo pallet is 117. If you view information for that type identifier in the `types` section of the metadata, it provides information about the available calls, including the documentation for each call. - -For example, the following is a condensed excerpt of the calls for the Sudo pallet: - -```json -{ - "id": 117, - "type": { - "path": ["pallet_sudo", "pallet", "Call"], - "params": [ - { - "name": "T", - "type": null - } - ], - "def": { - "variant": { - "variants": [ - { - "name": "sudo", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 0, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "sudo_unchecked_weight", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - }, - { - "name": "weight", - "type": 8, - "typeName": "Weight" - } - ], - "index": 1, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "set_key", - "fields": [ - { - "name": "new", - "type": 103, - "typeName": "AccountIdLookupOf" - } - ], - "index": 2, - "docs": [ - "Authenticates current sudo key, sets the given AccountId (`new`) as the new sudo" - ] - }, - { - "name": "sudo_as", - "fields": [ - { - "name": "who", - "type": 103, - "typeName": "AccountIdLookupOf" - }, - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 3, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Signed` origin from a given account" - ] - } - ] - } - } - } -} - -``` - -For each field, you can access type information and metadata for the following: - -- **Storage metadata**: Provides the information required to enable applications to get information for specific storage items. -- **Call metadata**: Includes information about the runtime calls defined by the `#[pallet]` macro including call names, arguments and documentation. -- **Event metadata**: Provides the metadata generated by the `#[pallet::event]` macro, including the name, arguments, and documentation for each pallet event. -- **Constants metadata**: Provides metadata generated by the `#[pallet::constant]` macro, including the name, type, and hex-encoded value of the constant. -- **Error metadata**: Provides metadata generated by the `#[pallet::error]` macro, including the name and documentation for each pallet error. - -!!!tip - Type identifiers change from time to time, so you should avoid relying on specific type identifiers in your applications. - -### Extrinsic - -The runtime generates extrinsic metadata and provides useful information about transaction format. When decoded, the metadata contains the transaction version and the list of signed extensions. - -For example: - -```json -{ - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [ - { - "identifier": "CheckNonZeroSender", - "ty": 132, - "additional_signed": 41 - }, - { - "identifier": "CheckSpecVersion", - "ty": 133, - "additional_signed": 4 - }, - { - "identifier": "CheckTxVersion", - "ty": 134, - "additional_signed": 4 - }, - { - "identifier": "CheckGenesis", - "ty": 135, - "additional_signed": 11 - }, - { - "identifier": "CheckMortality", - "ty": 136, - "additional_signed": 11 - }, - { - "identifier": "CheckNonce", - "ty": 138, - "additional_signed": 41 - }, - { - "identifier": "CheckWeight", - "ty": 139, - "additional_signed": 41 - }, - { - "identifier": "ChargeTransactionPayment", - "ty": 140, - "additional_signed": 41 - } - ] - }, - "ty": 141 -} - -``` - -The type system is [composite](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank}, meaning each type identifier contains a reference to a specific type or to another type identifier that provides information about the associated primitive types. - -For example, you can encode the `BitVec` type, but to decode it properly, you must know the types used for the `Order` and `Store` types. To find type information for `Order` and `Store`, you can use the path in the decoded JSON to locate their type identifiers. - -## Included RPC APIs - -A standard node comes with the following APIs to interact with a node: - -- **[`AuthorApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/author/trait.AuthorApiServer.html){target=\_blank}**: Make calls into a full node, including authoring extrinsics and verifying session keys. -- **[`ChainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/chain/trait.ChainApiServer.html){target=\_blank}**: Retrieve block header and finality information. -- **[`OffchainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/offchain/trait.OffchainApiServer.html){target=\_blank}**: Make RPC calls for off-chain workers. -- **[`StateApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/state/trait.StateApiServer.html){target=\_blank}**: Query information about on-chain state such as runtime version, storage items, and proofs. -- **[`SystemApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/system/trait.SystemApiServer.html){target=\_blank}**: Retrieve information about network state, such as connected peers and node roles. - -## Additional Resources - -The following tools can help you locate and decode metadata: - -- [Subxt Explorer](https://paritytech.github.io/subxt-explorer/#/){target=\_blank} -- [Metadata Portal 🌗](https://github.com/paritytech/metadata-portal){target=\_blank} -- [De[code] Sub[strate]](https://github.com/paritytech/desub){target=\_blank} - - --- Page Title: Contract Deployment @@ -3133,394 +2699,120 @@ These components form the foundation for developing sophisticated blockchain log --- -Page Title: Cryptography +Page Title: Deploy an ERC-20 to Polkadot Hub -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/cryptography/ -- Summary: A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/ +- Summary: Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Hardhat. -# Cryptography +# Deploy an ERC-20 to Polkadot Hub ## Introduction -Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem. - -## Hash Functions - -Hash functions are fundamental to blockchain technology, creating a unique digital fingerprint for any piece of data, including simple text, images, or any other form of file. They map input data of any size to a fixed-size output (typically 32 bytes) using complex mathematical operations. Hashing is used to verify data integrity, create digital signatures, and provide a secure way to store passwords. This form of mapping is known as the ["pigeonhole principle,"](https://en.wikipedia.org/wiki/Pigeonhole_principle){target=\_blank} it is primarily implemented to efficiently and verifiably identify data from large sets. - -### Key Properties of Hash Functions - -- **Deterministic**: The same input always produces the same output. -- **Quick computation**: It's easy to calculate the hash value for any given input. -- **Pre-image resistance**: It's infeasible to generate the input data from its hash. -- **Small changes in input yield large changes in output**: Known as the ["avalanche effect"](https://en.wikipedia.org/wiki/Avalanche_effect){target=\_blank}. -- **Collision resistance**: The probabilities are extremely low to find two different inputs with the same hash. +[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. -### Blake2 +This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Hardhat](https://hardhat.org/){target=\_blank}, an Ethereum development environment. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. -The Polkadot SDK utilizes Blake2, a state-of-the-art hashing method that offers: +## Prerequisites -- Equal or greater security compared to [SHA-2](https://en.wikipedia.org/wiki/SHA-2){target=\_blank}. -- Significantly faster performance than other algorithms. +Before starting, make sure you have: -These properties make Blake2 ideal for blockchain systems, reducing sync times for new nodes and lowering the resources required for validation. For detailed technical specifications about Blake2, see the [official Blake2 paper](https://www.blake2.net/blake2.pdf){target=\_blank}. +- Basic understanding of Solidity programming and fungible tokens. +- Node.js v22.13.1 or later. +- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -## Types of Cryptography +## Set Up Your Project -There are two different ways that cryptographic algorithms are implemented: symmetric cryptography and asymmetric cryptography. +This tutorial uses a [Hardhat ERC-20 template](https://github.com/polkadot-developers/revm-hardhat-examples/tree/master/erc20-hardhat){target=\_blank} that contains all the necessary files. To get started, take the following steps: -### Symmetric Cryptography +1. Clone the GitHub repository locally: -Symmetric encryption is a branch of cryptography that isn't based on one-way functions, unlike asymmetric cryptography. It uses the same cryptographic key to encrypt plain text and decrypt the resulting ciphertext. + ```bash + git clone https://github.com/polkadot-developers/revm-hardhat-examples/ + cd revm-hardhat-examples/erc20-hardhat + ``` -Symmetric cryptography is a type of encryption that has been used throughout history, such as the Enigma Cipher and the Caesar Cipher. It is still widely used today and can be found in Web2 and Web3 applications alike. There is only one single key, and a recipient must also have access to it to access the contained information. +2. Install the dependencies: -#### Advantages {: #symmetric-advantages } + ```bash + npm i + ``` -- Fast and efficient for large amounts of data. -- Requires less computational power. +This will fetch all the necessary packages to help you deploy an ERC-20 with Hardhat to Polkadot. -#### Disadvantages {: #symmetric-disadvantages } +## Configure Hardhat -- Key distribution can be challenging. -- Scalability issues in systems with many users. +Once you've [setup your project](#set-up-your-project), you can configure the `hardhat.config.ts` to your needs. This tutorial has the file prepared to deploy to the Polkadot TestNet. -### Asymmetric Cryptography +To store and use private keys or network URLs, you can use Hardhat's configuration variables. This can be set via tasks in the **vars** scope. For example, to store the private key to deploy to the Polkadot TestNet, run the following command: -Asymmetric encryption is a type of cryptography that uses two different keys, known as a keypair: a public key, used to encrypt plain text, and a private counterpart, used to decrypt the ciphertext. +```bash +npx hardhat vars set TESTNET_PRIVATE_KEY +``` -The public key encrypts a fixed-length message that can only be decrypted with the recipient's private key and, sometimes, a set password. The public key can be used to cryptographically verify that the corresponding private key was used to create a piece of data without compromising the private key, such as with digital signatures. This has obvious implications for identity, ownership, and properties and is used in many different protocols across Web2 and Web3. +The command will initiate a wizard in which you'll have to enter the value to be stored: -#### Advantages {: #asymmetric-advantages } +
    + npx hardhat vars set TESTNET_PRIVATE_KEY + ✔ Enter value: · ••••••••• + The configuration variable has been stored in /Users/albertoviera/Library/Preferences/hardhat-nodejs/vars.json +
    -- Solves the key distribution problem. -- Enables digital signatures and secure key exchange. +??? warning "Key Encryption" + This solution just prevents variables to be included in the code repository. You should find a solution that encrypts private keys and access them securely. -#### Disadvantages {: #asymmetric-disadvantages } +You can now use the account related to this private key by importing it into the Hardhat configuration file: -- Slower than symmetric encryption. -- Requires more computational resources. +```ts title="hardhat.config.ts" hl_lines="1 17" -### Trade-offs and Compromises +const config: HardhatUserConfig = { + solidity: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + networks: { + polkadotTestnet: { + url: vars.get("TESTNET_URL", "http://127.0.0.1:8545"), + accounts: vars.has("TESTNET_PRIVATE_KEY") ? [vars.get("TESTNET_PRIVATE_KEY")] : [], + }, + }, + mocha: { + timeout: 40000, + }, +}; -Symmetric cryptography is faster and requires fewer bits in the key to achieve the same level of security that asymmetric cryptography provides. However, it requires a shared secret before communication can occur, which poses issues to its integrity and a potential compromise point. On the other hand, asymmetric cryptography doesn't require the secret to be shared ahead of time, allowing for far better end-user security. +export default config; +``` -Hybrid symmetric and asymmetric cryptography is often used to overcome the engineering issues of asymmetric cryptography, as it is slower and requires more bits in the key to achieve the same level of security. It encrypts a key and then uses the comparatively lightweight symmetric cipher to do the "heavy lifting" with the message. +## Compile your Contract -## Digital Signatures +Once you've configured Hardhat, you can compile the contract. -Digital signatures are a way of verifying the authenticity of a document or message using asymmetric keypairs. They are used to ensure that a sender or signer's document or message hasn't been tampered with in transit, and for recipients to verify that the data is accurate and from the expected sender. +In this tutorial, a simple ERC-20 is provided. Therefore, to compile the contract you can run the following command: -Signing digital signatures only requires a low-level understanding of mathematics and cryptography. For a conceptual example -- when signing a check, it is expected that it cannot be cashed multiple times. This isn't a feature of the signature system but rather the check serialization system. The bank will check that the serial number on the check hasn't already been used. Digital signatures essentially combine these two concepts, allowing the signature to provide the serialization via a unique cryptographic fingerprint that cannot be reproduced. +```bash +npx hardhat compile +``` -Unlike pen-and-paper signatures, knowledge of a digital signature cannot be used to create other signatures. Digital signatures are often used in bureaucratic processes, as they are more secure than simply scanning in a signature and pasting it onto a document. +If everything compiles successfully, you should see the following output: -Polkadot SDK provides multiple different cryptographic schemes and is generic so that it can support anything that implements the [`Pair` trait](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Pair.html){target=\_blank}. +
    + npx hardhat compile + Generating typings for: 23 artifacts in dir: typechain-types for target: ethers-v6 + Successfully generated 62 typings! + Compiled 21 Solidity files successfully (evm target: paris). +
    -### Example of Creating a Digital Signature +## Test your Contract -The process of creating and verifying a digital signature involves several steps: +Hardhat has a native feature to test contracts. You can run tests against the local Hardhat development node, but it could have some technical differences to Polkadot. Therefore, in this tutorial, you'll be testing against the Polkadot TestNet -1. The sender creates a hash of the message. -2. The hash is encrypted using the sender's private key, creating the signature. -3. The message and signature are sent to the recipient. -4. The recipient decrypts the signature using the sender's public key. -5. The recipient hashes the received message and compares it to the decrypted hash. - -If the hashes match, the signature is valid, confirming the message's integrity and the sender's identity. - -## Elliptic Curve - -Blockchain technology requires the ability to have multiple keys creating a signature for block proposal and validation. To this end, Elliptic Curve Digital Signature Algorithm (ECDSA) and Schnorr signatures are two of the most commonly used methods. While ECDSA is a far simpler implementation, Schnorr signatures are more efficient when it comes to multi-signatures. - -Schnorr signatures bring some noticeable features over the ECDSA/EdDSA schemes: - -- It is better for hierarchical deterministic key derivations. -- It allows for native multi-signature through [signature aggregation](https://bitcoincore.org/en/2017/03/23/schnorr-signature-aggregation/){target=\_blank}. -- It is generally more resistant to misuse. - -One sacrifice that is made when using Schnorr signatures over ECDSA is that both require 64 bytes, but only ECDSA signatures communicate their public key. - -### Various Implementations - -- **[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm){target=\_blank}**: Polkadot SDK provides an ECDSA signature scheme using the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1){target=\_blank} curve. This is the same cryptographic algorithm used to secure [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin){target=\_blank} and [Ethereum](https://en.wikipedia.org/wiki/Ethereum){target=\_blank}. - -- **[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519){target=\_blank}**: An EdDSA signature scheme using [Curve25519](https://en.wikipedia.org/wiki/Curve25519){target=\_blank}. It is carefully engineered at several levels of design and implementation to achieve very high speeds without compromising security. - -- **[SR25519](https://research.web3.foundation/Polkadot/security/keys/accounts-more){target=\_blank}**: Based on the same underlying curve as Ed25519. However, it uses Schnorr signatures instead of the EdDSA scheme. - - ---- - -Page Title: Data Encoding - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/data-encoding/ -- Summary: SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. - -# Data Encoding - -## Introduction - -The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data. - -The SCALE codec enables communication between the runtime and the outer node. This mechanism is designed for high-performance, copy-free data encoding and decoding in resource-constrained environments like the Polkadot SDK [Wasm runtime](/develop/parachains/deployment/build-deterministic-runtime/#introduction){target=\_blank}. - -It is not self-describing, meaning the decoding context must fully know the encoded data types. - -Parity's libraries utilize the [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} crate (a Rust implementation of the SCALE codec) to handle encoding and decoding for interactions between RPCs and the runtime. - -The `codec` mechanism is ideal for Polkadot SDK-based chains because: - -- It is lightweight compared to generic serialization frameworks like [`serde`](https://serde.rs/){target=\_blank}, which add unnecessary bulk to binaries. -- It doesn’t rely on Rust’s `libstd`, making it compatible with `no_std` environments like Wasm runtime. -- It integrates seamlessly with Rust, allowing easy derivation of encoding and decoding logic for new types using `#[derive(Encode, Decode)]`. - -Defining a custom encoding scheme in the Polkadot SDK-based chains, rather than using an existing Rust codec library, is crucial for enabling cross-platform and multi-language support. - -## SCALE Codec - -The codec is implemented using the following traits: - -- [`Encode`](#encode) -- [`Decode`](#decode) -- [`CompactAs`](#compactas) -- [`HasCompact`](#hascompact) -- [`EncodeLike`](#encodelike) - -### Encode - -The [`Encode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Encode.html){target=\_blank} trait handles data encoding into SCALE format and includes the following key functions: - -- **`size_hint(&self) -> usize`**: Estimates the number of bytes required for encoding to prevent multiple memory allocations. This should be inexpensive and avoid complex operations. Optional if the size isn’t known. -- **`encode_to(&self, dest: &mut T)`**: Encodes the data, appending it to a destination buffer. -- **`encode(&self) -> Vec`**: Encodes the data and returns it as a byte vector. -- **`using_encoded R>(&self, f: F) -> R`**: Encodes the data and passes it to a closure, returning the result. -- **`encoded_size(&self) -> usize`**: Calculates the encoded size. Should be used when the encoded data isn’t required. - -!!!tip - For best performance, value types should override `using_encoded`, and allocating types should override `encode_to`. It's recommended to implement `size_hint` for all types where possible. - -### Decode - -The [`Decode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Decode.html){target=\_blank} trait handles decoding SCALE-encoded data back into the appropriate types: - -- **`fn decode(value: &mut I) -> Result`**: Decodes data from the SCALE format, returning an error if decoding fails. - -### CompactAs - -The [`CompactAs`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.CompactAs.html){target=\_blank} trait wraps custom types for compact encoding: - -- **`encode_as(&self) -> &Self::As`**: Encodes the type as a compact type. -- **`decode_from(_: Self::As) -> Result`**: decodes from a compact encoded type. - -### HasCompact - -The [`HasCompact`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.HasCompact.html){target=\_blank} trait indicates a type supports compact encoding. - -### EncodeLike - -The [`EncodeLike`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.EncodeLike.html){target=\_blank} trait is used to ensure multiple types that encode similarly are accepted by the same function. When using `derive`, it is automatically implemented. - -### Data Types - -The table below outlines how the Rust implementation of the Parity SCALE codec encodes different data types. - -| Type | Description | Example SCALE Decoded Value | SCALE Encoded Value | -|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| -| Boolean | Boolean values are encoded using the least significant bit of a single byte. | `false` / `true` | `0x00` / `0x01` | -| Compact/general integers | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2^536) and is more efficient at encoding most values than the fixed-width version. | `unsigned integer 0` / `unsigned integer 1` / `unsigned integer 42` / `unsigned integer 69` / `unsigned integer 65535` / `BigInt(100000000000000)` | `0x00` / `0x04` / `0xa8` / `0x1501` / `0xfeff0300` / `0x0b00407a10f35a` | -| Enumerations (tagged-unions) | A fixed number of variants, each mutually exclusive and potentially implying a further value or series of values. Encoded as the first byte identifying the index of the variant that the value is. Any further bytes are used to encode any data that the variant implies. Thus, no more than 256 variants are supported. | `Int(42)` and `Bool(true)` where `enum IntOrBool { Int(u8), Bool(bool) }` | `0x002a` and `0x0101` | -| Fixed-width integers | Basic integers are encoded using a fixed-width little-endian (LE) format. | `signed 8-bit integer 69` / `unsigned 16-bit integer 42` / `unsigned 32-bit integer 16777215` | `0x45` / `0x2a00` / `0xffffff00` | -| Options | One or zero values of a particular type. | `Some` / `None` | `0x01` followed by the encoded value / `0x00` | -| Results | Results are commonly used enumerations which indicate whether certain operations were successful or unsuccessful. | `Ok(42)` / `Err(false)` | `0x002a` / `0x0100` | -| Strings | Strings are Vectors of bytes (Vec) containing a valid UTF8 sequence. | | | -| Structs | For structures, the values are named, but that is irrelevant for the encoding (names are ignored - only order matters). | `SortedVecAsc::from([3, 5, 2, 8])` | `[3, 2, 5, 8] ` | -| Tuples | A fixed-size series of values, each with a possibly different but predetermined and fixed type. This is simply the concatenation of each encoded value. | Tuple of compact unsigned integer and boolean: `(3, false)` | `0x0c00` | -| Vectors (lists, series, sets) | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. | Vector of unsigned `16`-bit integers: `[4, 8, 15, 16, 23, 42]` | `0x18040008000f00100017002a00` | - -## Encode and Decode Rust Trait Implementations - -Here's how the `Encode` and `Decode` traits are implemented: - - -```rust -use parity_scale_codec::{Encode, Decode}; - -[derive(Debug, PartialEq, Encode, Decode)] -enum EnumType { - #[codec(index = 15)] - A, - B(u32, u64), - C { - a: u32, - b: u64, - }, -} - -let a = EnumType::A; -let b = EnumType::B(1, 2); -let c = EnumType::C { a: 1, b: 2 }; - -a.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x0f"); -}); - -b.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -c.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -let mut da: &[u8] = b"\x0f"; -assert_eq!(EnumType::decode(&mut da).ok(), Some(a)); - -let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut db).ok(), Some(b)); - -let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut dc).ok(), Some(c)); - -let mut dz: &[u8] = &[0]; -assert_eq!(EnumType::decode(&mut dz).ok(), None); -``` - -## SCALE Codec Libraries - -Several SCALE codec implementations are available in various languages. Here's a list of them: - -- **AssemblyScript**: [`LimeChain/as-scale-codec`](https://github.com/LimeChain/as-scale-codec){target=\_blank} -- **C**: [`MatthewDarnell/cScale`](https://github.com/MatthewDarnell/cScale){target=\_blank} -- **C++**: [`qdrvm/scale-codec-cpp`](https://github.com/qdrvm/scale-codec-cpp){target=\_blank} -- **JavaScript**: [`polkadot-js/api`](https://github.com/polkadot-js/api){target=\_blank} -- **Dart**: [`leonardocustodio/polkadart`](https://github.com/leonardocustodio/polkadart){target=\_blank} -- **Haskell**: [`airalab/hs-web3`](https://github.com/airalab/hs-web3/tree/master/packages/scale){target=\_blank} -- **Golang**: [`itering/scale.go`](https://github.com/itering/scale.go){target=\_blank} -- **Java**: [`splix/polkaj`](https://github.com/splix/polkaj){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **Ruby**: [` wuminzhe/scale_rb`](https://github.com/wuminzhe/scale_rb){target=\_blank} -- **TypeScript**: [`parity-scale-codec-ts`](https://github.com/tjjfvi/subshape){target=\_blank}, [`scale-ts`](https://github.com/unstoppablejs/unstoppablejs/tree/main/packages/scale-ts#scale-ts){target=\_blank}, [`soramitsu/scale-codec-js-library`](https://github.com/soramitsu/scale-codec-js-library){target=\_blank}, [`subsquid/scale-codec`](https://github.com/subsquid/squid-sdk/tree/master/substrate/scale-codec){target=\_blank} - - ---- - -Page Title: Deploy an ERC-20 to Polkadot Hub - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/ -- Summary: Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Hardhat. - -# Deploy an ERC-20 to Polkadot Hub - -## Introduction - -[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. - -This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Hardhat](https://hardhat.org/){target=\_blank}, an Ethereum development environment. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. - -## Prerequisites - -Before starting, make sure you have: - -- Basic understanding of Solidity programming and fungible tokens. -- Node.js v22.13.1 or later. -- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. - -## Set Up Your Project - -This tutorial uses a [Hardhat ERC-20 template](https://github.com/polkadot-developers/revm-hardhat-examples/tree/master/erc20-hardhat){target=\_blank} that contains all the necessary files. To get started, take the following steps: - -1. Clone the GitHub repository locally: - - ```bash - git clone https://github.com/polkadot-developers/revm-hardhat-examples/ - cd revm-hardhat-examples/erc20-hardhat - ``` - -2. Install the dependencies: - - ```bash - npm i - ``` - -This will fetch all the necessary packages to help you deploy an ERC-20 with Hardhat to Polkadot. - -## Configure Hardhat - -Once you've [setup your project](#set-up-your-project), you can configure the `hardhat.config.ts` to your needs. This tutorial has the file prepared to deploy to the Polkadot TestNet. - -To store and use private keys or network URLs, you can use Hardhat's configuration variables. This can be set via tasks in the **vars** scope. For example, to store the private key to deploy to the Polkadot TestNet, run the following command: - -```bash -npx hardhat vars set TESTNET_PRIVATE_KEY -``` - -The command will initiate a wizard in which you'll have to enter the value to be stored: - -
    - npx hardhat vars set TESTNET_PRIVATE_KEY - ✔ Enter value: · ••••••••• - The configuration variable has been stored in /Users/albertoviera/Library/Preferences/hardhat-nodejs/vars.json -
    - -??? warning "Key Encryption" - This solution just prevents variables to be included in the code repository. You should find a solution that encrypts private keys and access them securely. - -You can now use the account related to this private key by importing it into the Hardhat configuration file: - -```ts title="hardhat.config.ts" hl_lines="1 17" - -const config: HardhatUserConfig = { - solidity: { - version: "0.8.28", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - networks: { - polkadotTestnet: { - url: vars.get("TESTNET_URL", "http://127.0.0.1:8545"), - accounts: vars.has("TESTNET_PRIVATE_KEY") ? [vars.get("TESTNET_PRIVATE_KEY")] : [], - }, - }, - mocha: { - timeout: 40000, - }, -}; - -export default config; -``` - -## Compile your Contract - -Once you've configured Hardhat, you can compile the contract. - -In this tutorial, a simple ERC-20 is provided. Therefore, to compile the contract you can run the following command: - -```bash -npx hardhat compile -``` - -If everything compiles successfully, you should see the following output: - -
    - npx hardhat compile - Generating typings for: 23 artifacts in dir: typechain-types for target: ethers-v6 - Successfully generated 62 typings! - Compiled 21 Solidity files successfully (evm target: paris). -
    - -## Test your Contract - -Hardhat has a native feature to test contracts. You can run tests against the local Hardhat development node, but it could have some technical differences to Polkadot. Therefore, in this tutorial, you'll be testing against the Polkadot TestNet - -This example has a predefined test file located in [`test/Token.test.js`](https://github.com/polkadot-developers/revm-hardhat-examples/blob/master/erc20-hardhat/test/MyToken.test.ts){target=\_blank}, that runs the following tests: +This example has a predefined test file located in [`test/Token.test.js`](https://github.com/polkadot-developers/revm-hardhat-examples/blob/master/erc20-hardhat/test/MyToken.test.ts){target=\_blank}, that runs the following tests: 1. The token was deployed by verifying its **name** and **symbol**. 2. The token has the right owner configured. @@ -4685,380 +3977,89 @@ PolkaVM differs from the EVM in two key ways that make it faster, more hardware- --- -Page Title: E2E Testing with Moonwall +Page Title: Fork a Parachain Using Chopsticks -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/moonwall/ -- Summary: Enhance blockchain end-to-end testing with Moonwall's standardized environment setup, comprehensive configuration management, and simple network interactions. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md +- Canonical (HTML): https://docs.polkadot.com/parachains/testing/fork-a-parachain/ +- Summary: Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. -# E2E Testing with Moonwall +# Fork a Parachain Using Chopsticks ## Introduction -Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations. +[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network. -Moonwall consolidates this complexity by providing the following: +This guide walks you through installing Chopsticks and provides information on configuring a local blockchain fork. By streamlining testing and experimentation, Chopsticks empowers developers to innovate and accelerate their blockchain projects within the Polkadot ecosystem. -- A centralized configuration management system that explicitly defines all network parameters. -- A standardized approach to environment setup across different Substrate-based chains. -- Built-in utilities for common testing scenarios and network interactions. +For additional support and information, please reach out through [GitHub Issues](https://github.com/AcalaNetwork/chopsticks/issues){target=_blank}. -Developers can focus on writing meaningful tests rather than managing infrastructure complexities or searching through documentation for configuration options. +!!! warning + Chopsticks uses [Smoldot](https://github.com/smol-dot/smoldot){target=_blank} light client, which only supports the native Polkadot SDK API. Consequently, a Chopsticks-based fork doesn't support Ethereum JSON-RPC calls, meaning you cannot use it to fork your chain and connect Metamask. ## Prerequisites Before you begin, ensure you have the following installed: -- [Node.js](https://nodejs.org/en/){target=\_blank} (version 20.10 or higher). -- A package manager such as [npm](https://www.npmjs.com/){target=\_blank}, [yarn](https://yarnpkg.com/){target=\_blank}, or [pnpm](https://pnpm.io/){target=\_blank}. - -## Install Moonwall +- [Node.js](https://nodejs.org/en/){target=\_blank}. +- A package manager such as [npm](https://www.npmjs.com/){target=\_blank}, which should be installed with Node.js by default, or [Yarn](https://yarnpkg.com/){target=\_blank}. -Moonwall can be installed globally for system-wide access or locally within specific projects. This section covers both installation methods. +## Install Chopsticks -!!! tip - This documentation corresponds to Moonwall version `5.15.0`. To avoid compatibility issues with the documented features, ensure you're using the matching version. +You can install Chopsticks globally or locally in your project. Choose the option that best fits your development workflow. This documentation explains the features of Chopsticks version `1.2.2`. Make sure you're using the correct version to match these instructions. ### Global Installation -Global installation provides system-wide access to the Moonwall CLI, making it ideal for developers working across multiple blockchain projects. Install it by running one of the following commands: - -=== "npm" - - ```bash - npm install -g @moonwall/cli@5.15.0 - ``` - -=== "pnpm" - - ```bash - pnpm -g install @moonwall/cli@5.15.0 - ``` - -=== "yarn" +To install Chopsticks globally, allowing you to use it across multiple projects, run: - ```bash - yarn global add @moonwall/cli@5.15.0 - ``` +```bash +npm i -g @acala-network/chopsticks@1.2.2 +``` -Now, you can run the `moonwall` command from your terminal. +Now, you should be able to run the `chopsticks` command from your terminal. ### Local Installation -Local installation is recommended for better dependency management and version control within a specific project. First, initialize your project: +To use Chopsticks in a specific project, first create a new directory and initialize a Node.js project: ```bash -mkdir my-moonwall-project -cd my-moonwall-project +mkdir my-chopsticks-project +cd my-chopsticks-project npm init -y ``` -Then, install it as a local dependency: - -=== "npm" - - ```bash - npm install @moonwall/cli@5.15.0 - ``` - -=== "pnpm" - - ```bash - pnpm install @moonwall/cli@5.15.0 - ``` - -=== "yarn" - - ```bash - yarn add @moonwall/cli@5.15.0 - ``` +Then, install Chopsticks as a local dependency: -## Initialize Moonwall +```bash +npm i @acala-network/chopsticks@1.2.2 +``` -The `moonwall init` command launches an interactive wizard to create your configuration file: +Finally, you can run Chopsticks using the `npx` command. To see all available options and commands, run it with the `--help` flag: ```bash -moonwall init +npx @acala-network/chopsticks --help ``` -During setup, you will see prompts for the following parameters: +## Configure Chopsticks -- **`label`**: Identifies your test configuration. -- **`global timeout`**: Maximum time (ms) for test execution. -- **`environment name`**: Name for your testing environment. -- **`network foundation`**: Type of blockchain environment to use. -- **`tests directory`**: Location of your test files. +To run Chopsticks, you need to configure some parameters. This can be set either through using a configuration file or the command line interface (CLI). The parameters that can be configured are as follows: -Select `Enter` to accept defaults or input custom values. You should see something like this: +- **`genesis`**: The link to a parachain's raw genesis file to build the fork from, instead of an endpoint. +- **`timestamp`**: Timestamp of the block to fork from. +- **`endpoint`**: The endpoint of the parachain to fork. +- **`block`**: Use to specify at which block hash or number to replay the fork. +- **`wasm-override`**: Path of the Wasm to use as the parachain runtime, instead of an endpoint's runtime. +- **`db`**: Path to the name of the file that stores or will store the parachain's database. +- **`config`**: Path or URL of the config file. +- **`port`**: The port to expose an endpoint on. +- **`build-block-mode`**: How blocks should be built in the fork: batch, manual, instant. +- **`import-storage`**: A pre-defined JSON/YAML storage path to override in the parachain's storage. +- **`allow-unresolved-imports`**: Whether to allow Wasm unresolved imports when using a Wasm to build the parachain. +- **`html`**: Include to generate storage diff preview between blocks. +- **`mock-signature-host`**: Mock signature host so that any signature starts with `0xdeadbeef` and filled by `0xcd` is considered valid. -
    - moonwall init - ✔ Provide a label for the config file moonwall_config - ✔ Provide a global timeout value 30000 - ✔ Provide a name for this environment default_env - ✔ What type of network foundation is this? dev - ✔ Provide the path for where tests for this environment are kept tests/ - ? Would you like to generate this config? (no to restart from beginning) (Y/n) -
    +### Configuration File -The wizard generates a `moonwall.config` file: - -```json -{ - "label": "moonwall_config", - "defaultTestTimeout": 30000, - "environments": [ - { - "name": "default_env", - "testFileDir": ["tests/"], - "foundation": { - "type": "dev" - } - } - ] -} - -``` - -The default configuration requires specific details about your blockchain node and test requirements: - -- The `foundation` object defines how your test blockchain node will be launched and managed. The dev foundation, which runs a local node binary, is used for local development. - - For more information about available options, check the [Foundations](https://moonsong-labs.github.io/moonwall/guide/intro/foundations.html){target=\_blank} section. - -- The `connections` array specifies how your tests will interact with the blockchain node. This typically includes provider configuration and endpoint details. - - A provider is a tool that allows you or your application to connect to a blockchain network and simplifies the low-level details of the process. A provider handles submitting transactions, reading state, and more. For more information on available providers, check the [Providers supported](https://moonsong-labs.github.io/moonwall/guide/intro/providers.html#providers-supported){target=\_blank} page in the Moonwall documentation. - -Here's a complete configuration example for testing a local node using Polkadot.js as a provider: - -```json -{ - "label": "moonwall_config", - "defaultTestTimeout": 30000, - "environments": [ - { - "name": "default_env", - "testFileDir": ["tests/"], - "foundation": { - "launchSpec": [ - { - "binPath": "./node-template", - "newRpcBehaviour": true, - "ports": { "rpcPort": 9944 } - } - ], - "type": "dev" - }, - "connections": [ - { - "name": "myconnection", - "type": "polkadotJs", - "endpoints": ["ws://127.0.0.1:9944"] - } - ] - } - ] -} - -``` - -## Writing Tests - -Moonwall uses the [`describeSuite`](https://github.com/Moonsong-Labs/moonwall/blob/7568048c52e9f7844f38fb4796ae9e1b9205fdaa/packages/cli/src/lib/runnerContext.ts#L65){target=\_blank} function to define test suites, like using [Mocha](https://mochajs.org/){target=\_blank}. Each test suite requires the following: - -- **`id`**: Unique identifier for the suite. -- **`title`**: Descriptive name for the suite. -- **`foundationMethods`**: Specifies the testing environment (e.g., `dev` for local node testing). -- **`testCases`**: A callback function that houses the individual test cases of this suite. - -The following example shows how to test a balance transfer between two accounts: - -```ts -import '@polkadot/api-augment'; -import { describeSuite, expect } from '@moonwall/cli'; -import { Keyring } from '@polkadot/api'; - -describeSuite({ - id: 'D1', - title: 'Demo suite', - foundationMethods: 'dev', - testCases: ({ it, context, log }) => { - it({ - id: 'T1', - title: 'Test Case', - test: async () => { - // Set up polkadot.js API and testing accounts - let api = context.polkadotJs(); - let alice = new Keyring({ type: 'sr25519' }).addFromUri('//Alice'); - let charlie = new Keyring({ type: 'sr25519' }).addFromUri('//Charlie'); - - // Query Charlie's account balance before transfer - const balanceBefore = (await api.query.system.account(charlie.address)) - .data.free; - - // Before transfer, Charlie's account balance should be 0 - expect(balanceBefore.toString()).toEqual('0'); - log('Balance before: ' + balanceBefore.toString()); - - // Transfer from Alice to Charlie - const amount = 1000000000000000; - await api.tx.balances - .transferAllowDeath(charlie.address, amount) - .signAndSend(alice); - - // Wait for the transaction to be included in a block. - // This is necessary because the balance is not updated immediately. - // Block time is 6 seconds. - await new Promise((resolve) => setTimeout(resolve, 6000)); - - // Query Charlie's account balance after transfer - const balanceAfter = (await api.query.system.account(charlie.address)) - .data.free; - - // After transfer, Charlie's account balance should be 1000000000000000 - expect(balanceAfter.toString()).toEqual(amount.toString()); - log('Balance after: ' + balanceAfter.toString()); - }, - }); - }, -}); - -``` - -This test demonstrates several key concepts: - -- Initializing the Polkadot.js API through Moonwall's context and setting up test accounts. -- Querying on-chain state. -- Executing transactions. -- Waiting for block inclusion. -- Verifying results using assertions. - -## Running the Tests - -Execute your tests using the `test` Moonwall CLI command. For the default environment setup run: - -```bash -moonwall test default_env -c moonwall.config -``` - -The test runner will output detailed results showing: - -- Test suite execution status. -- Individual test case results. -- Execution time. -- Detailed logs and error messages (if any). - -Example output: -
    - moonwall test default_env -c moonwall.config - stdout | tests/test1.ts > 🗃️ D1 Demo suite > 📁 D1T1 Test Case - 2025-01-21T19:27:55.624Z test:default_env Balance before: 0 - - stdout | tests/test1.ts > 🗃️ D1 Demo suite > 📁 D1T1 Test Case - 2025-01-21T19:28:01.637Z test:default_env Balance after: 1000000000000000 - - ✓ default_env tests/test1.ts (1 test) 6443ms - ✓ 🗃️ D1 Demo suite > 📁 D1T1 Test Case 6028ms - - Test Files 1 passed (1) - Tests 1 passed (1) - Start at 16:27:53 - Duration 7.95s (transform 72ms, setup 0ms, collect 1.31s, tests 6.44s, environment 0ms, prepare 46ms) - - ✅ All tests passed -
    - -## Where to Go Next - -For a comprehensive guide to Moonwall's full capabilities, available configurations, and advanced usage, see the official [Moonwall](https://moonsong-labs.github.io/moonwall/){target=\_blank} documentation. - - ---- - -Page Title: Get Started - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md -- Canonical (HTML): https://docs.polkadot.com/parachains/testing/fork-a-parachain/ -- Summary: Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. - -# Get Started - -## Introduction - -[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network. - -This guide walks you through installing Chopsticks and provides information on configuring a local blockchain fork. By streamlining testing and experimentation, Chopsticks empowers developers to innovate and accelerate their blockchain projects within the Polkadot ecosystem. - -For additional support and information, please reach out through [GitHub Issues](https://github.com/AcalaNetwork/chopsticks/issues){target=_blank}. - -!!! warning - Chopsticks uses [Smoldot](https://github.com/smol-dot/smoldot){target=_blank} light client, which only supports the native Polkadot SDK API. Consequently, a Chopsticks-based fork doesn't support Ethereum JSON-RPC calls, meaning you cannot use it to fork your chain and connect Metamask. - -## Prerequisites - -Before you begin, ensure you have the following installed: - -- [Node.js](https://nodejs.org/en/){target=\_blank}. -- A package manager such as [npm](https://www.npmjs.com/){target=\_blank}, which should be installed with Node.js by default, or [Yarn](https://yarnpkg.com/){target=\_blank}. - -## Install Chopsticks - -You can install Chopsticks globally or locally in your project. Choose the option that best fits your development workflow. This documentation explains the features of Chopsticks version `1.2.2`. Make sure you're using the correct version to match these instructions. - -### Global Installation - -To install Chopsticks globally, allowing you to use it across multiple projects, run: - -```bash -npm i -g @acala-network/chopsticks@1.2.2 -``` - -Now, you should be able to run the `chopsticks` command from your terminal. - -### Local Installation - -To use Chopsticks in a specific project, first create a new directory and initialize a Node.js project: - -```bash -mkdir my-chopsticks-project -cd my-chopsticks-project -npm init -y -``` - -Then, install Chopsticks as a local dependency: - -```bash -npm i @acala-network/chopsticks@1.2.2 -``` - -Finally, you can run Chopsticks using the `npx` command. To see all available options and commands, run it with the `--help` flag: - -```bash -npx @acala-network/chopsticks --help -``` - -## Configure Chopsticks - -To run Chopsticks, you need to configure some parameters. This can be set either through using a configuration file or the command line interface (CLI). The parameters that can be configured are as follows: - -- **`genesis`**: The link to a parachain's raw genesis file to build the fork from, instead of an endpoint. -- **`timestamp`**: Timestamp of the block to fork from. -- **`endpoint`**: The endpoint of the parachain to fork. -- **`block`**: Use to specify at which block hash or number to replay the fork. -- **`wasm-override`**: Path of the Wasm to use as the parachain runtime, instead of an endpoint's runtime. -- **`db`**: Path to the name of the file that stores or will store the parachain's database. -- **`config`**: Path or URL of the config file. -- **`port`**: The port to expose an endpoint on. -- **`build-block-mode`**: How blocks should be built in the fork: batch, manual, instant. -- **`import-storage`**: A pre-defined JSON/YAML storage path to override in the parachain's storage. -- **`allow-unresolved-imports`**: Whether to allow Wasm unresolved imports when using a Wasm to build the parachain. -- **`html`**: Include to generate storage diff preview between blocks. -- **`mock-signature-host`**: Mock signature host so that any signature starts with `0xdeadbeef` and filled by `0xcd` is considered valid. - -### Configuration File - -The Chopsticks source repository includes a collection of [YAML](https://yaml.org/){target=\_blank} files that can be used to set up various Polkadot SDK chains locally. You can download these configuration files from the [repository's `configs` folder](https://github.com/AcalaNetwork/chopsticks/tree/master/configs){target=\_blank}. +The Chopsticks source repository includes a collection of [YAML](https://yaml.org/){target=\_blank} files that can be used to set up various Polkadot SDK chains locally. You can download these configuration files from the [repository's `configs` folder](https://github.com/AcalaNetwork/chopsticks/tree/master/configs){target=\_blank}. An example of a configuration file for Polkadot is as follows: @@ -5271,7337 +4272,4672 @@ These are the methods that can be invoked and their parameters: --- -Page Title: Get Started +Page Title: Get Started with Parachain Development -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md -- Canonical (HTML): https://docs.polkadot.com/parachains/testing/run-a-parachain-network/ -- Summary: Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/get-started/ +- Summary: Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. # Get Started -## Introduction - -Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance. +The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. -This guide will outline the different installation methods for Zombienet, provide step-by-step instructions for setting up on various platforms, and highlight essential provider-specific features and requirements. +## Quick Start Guides -By following this guide, Zombienet will be up and running quickly, ready to streamline your blockchain testing and development workflows. +Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. -## Install Zombienet +| Tutorial | Tools | Description | +| :--------------------------------------------------------------------------------------------: | :----------------------------: | :---------------------------------------------------------------------: | +| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | Learn how to set up and run the Polkadot SDK Parachain Template locally | +| [Launch a Local Parachain](/parachains/testing/run-a-parachain-network/) | Zombienet, Chopsticks | Set up a local development environment for testing | +| [Connect to Polkadot](/chain-interactions/query-on-chain-data/query-sdks/) | Polkadot.js, Substrate Connect | Connect your application to Polkadot networks | +| [Fork an Existing Parachain](/parachains/testing/fork-a-parachain/) | Chopsticks | Create a local fork of a live parachain for testing | -Zombienet releases are available on the [Zombienet repository](https://github.com/paritytech/zombienet){target=\_blank}. +## Launch a Simple Parachain -Multiple options are available for installing Zombienet, depending on the user's preferences and the environment where it will be used. The following section will guide you through the installation process for each option. +Learn the fundamentals of launching and deploying a parachain to the Polkadot network. -=== "Use the executable" +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------: | +| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | +| [Deploy to Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/) | Step-by-step tutorial to deploying your parachain to Polkadot | +| [Obtain Coretime](/parachains/launch-a-parachain/obtain-coretime/) | Learn how to acquire blockspace using Polkadot's coretime model (RegionX) | - Install Zombienet using executables by visiting the [latest release](https://github.com/paritytech/zombienet/releases){target=\_blank} page and selecting the appropriate asset for your operating system. You can download the executable and move it to a directory in your PATH. +## Customize Your Runtime - Each release includes executables for Linux and macOS. Executables are generated using [pkg](https://github.com/vercel/pkg){target=\_blank}, which allows the Zombienet CLI to operate without requiring Node.js to be installed. +Build custom functionality for your parachain by composing and creating pallets. - Then, ensure the downloaded file is executable: +| Tutorial | Description | +| :-------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------: | +| [Add Existing Pallets to the Runtime](/parachains/customize-runtime/add-existing-pallets/) | Integrate pre-built pallets from the FRAME ecosystem | +| [Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/) | Configure and use multiple instances of the same pallet | +| [Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/) | Enable smart contract capabilities using Contracts or EVM pallets | - ```bash - chmod +x zombienet-macos-arm64 - ``` +### Pallet Development - Finally, you can run the following command to check if the installation was successful. If so, it will display the version of the installed Zombienet: +Deep dive into creating and managing custom pallets for your parachain. - ```bash - ./zombienet-macos-arm64 version - ``` +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------: | +| [Create a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/) | Build a pallet from scratch with custom logic | +| [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/) | Set up a mock runtime environment for testing | +| [Pallet Unit Testing](/parachains/customize-runtime/pallet-development/pallet-testing/) | Write comprehensive tests for your pallet logic | +| [Add Your Custom Pallet to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/) | Integrate your custom pallet into your parachain runtime | +| [Benchmark the Custom Pallet](/parachains/customize-runtime/pallet-development/benchmark-pallet/) | Measure and optimize pallet performance with benchmarking | - If you want to add the `zombienet` executable to your PATH, you can move it to a directory in your PATH, such as `/usr/local/bin`: +## Testing - ```bash - mv zombienet-macos-arm64 /usr/local/bin/zombienet - ``` +Test your parachain in various environments before production deployment. - Now you can refer to the `zombienet` executable directly. +| Tutorial | Description | +| :---------------------------------------------------------------------: | :-----------------------------------------------------: | +| [Fork a Parachain](/parachains/testing/fork-a-parachain/) | Use Chopsticks to create a local fork for testing | +| [Run a Parachain Network](/parachains/testing/run-a-parachain-network/) | Launch a complete parachain test network with Zombienet | - ```bash - zombienet version - ``` +## Runtime Upgrades and Maintenance -=== "Use Nix" +Manage your parachain's lifecycle with forkless upgrades and maintenance operations. - For Nix users, the Zombienet repository provides a [`flake.nix`](https://github.com/paritytech/zombienet/blob/main/flake.nix){target=\_blank} file to install Zombienet making it easy to incorporate Zombienet into Nix-based projects. - - To install Zombienet utilizing Nix, users can run the following command, triggering the fetching of the flake and subsequently installing the Zombienet package: +| Tutorial | Description | +| :-----------------------------------------------------------------------: | :--------------------------------------------------: | +| [Runtime Upgrades](/parachains/runtime-maintenance/runtime-upgrades/) | Perform forkless runtime upgrades via governance | +| [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/) | Safely migrate storage when updating runtime logic | +| [Unlock Parachains](/parachains/runtime-maintenance/unlock-parachains/) | Understand parachain lifecycle and unlock mechanisms | - ```bash - nix run github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION -- \ - spawn INSERT_ZOMBIENET_CONFIG_FILE_NAME.toml - ``` +## Interoperability - Replace the `INSERT_ZOMBIENET_VERSION` with the desired version of Zombienet and the `INSERT_ZOMBIENET_CONFIG_FILE_NAME` with the name of the configuration file you want to use. +Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). - To run the command above, you need to have [Flakes](https://nixos.wiki/wiki/Flakes#Enable_flakes){target=\_blank} enabled. +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: | +| [Open HRMP Channels Between Parachains](/parachains/interoperability/channels-between-parachains/) | Establish communication channels with other parachains | +| [Open HRMP Channels with System Parachains](/parachains/interoperability/channels-with-system-parachains/) | Connect with Asset Hub and other system parachains | - Alternatively, you can also include the Zombienet binary in the PATH for the current shell using the following command: - - ```bash - nix shell github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION - ``` +## Integrations -=== "Use Docker" +Integrate your parachain with essential ecosystem tools and services. - Zombienet can also be run using Docker. The Zombienet repository provides a Docker image that can be used to run the Zombienet CLI. To run Zombienet using Docker, you can use the following command: - - ```bash - docker run -it --rm \ - -v $(pwd):/home/nonroot/zombie-net/host-current-files \ - paritytech/zombienet - ``` - - The command above will run the Zombienet CLI inside a Docker container and mount the current directory to the `/home/nonroot/zombie-net/host-current-files` directory. This allows Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path. +| Tutorial | Description | +| :--------------------------------------------: | :----------------------------------------------------: | +| [Wallets](/parachains/integrations/wallets/) | Integrate wallet support for user interactions | +| [Indexers](/parachains/integrations/indexers/) | Set up indexing solutions for querying blockchain data | +| [Oracles](/parachains/integrations/oracles/) | Connect your parachain to off-chain data sources | - Inside the Docker container, you can run the Zombienet CLI commands. First, you need to set up Zombienet to download the necessary binaries: +## Additional Resources - ```bash - npm run zombie -- setup polkadot polkadot-parachain - ``` +- [Polkadot SDK Documentation](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/index.html) +- [Polkadot Wiki - Parachains](https://wiki.polkadot.network/docs/learn-parachains/) - After that, you need to add those binaries to the PATH: - ```bash - export PATH=/home/nonroot/zombie-net:$PATH - ``` +--- - Finally, you can run the Zombienet CLI commands. For example, to spawn a network using a specific configuration file, you can run the following command: +Page Title: Get Started with Smart Contracts - ```bash - npm run zombie -- -p native spawn host-current-files/minimal.toml - ``` +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/get-started/ +- Summary: Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. - The command above mounts the current directory to the `/workspace` directory inside the Docker container, allowing Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path. +# Get Started -## Providers +This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need. -Zombienet supports different backend providers for running the nodes. At this moment, [Kubernetes](https://kubernetes.io/){target=\_blank}, [Podman](https://podman.io/){target=\_blank}, and local providers are supported, which can be declared as `kubernetes`, `podman`, or `native`, respectively. +## Quick Starts -To use a particular provider, you can specify it in the network file or use the `--provider` flag in the CLI: +Kick off development fast with curated links for connecting, funding, exploring, and deploying your first contract. -```bash -zombienet spawn network.toml --provider INSERT_PROVIDER -``` +| Quick Start | Tools | Description | +|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:| +| [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer | +| [Get Test Tokens](/smart-contracts/faucets/){target=\_blank} | - | Request test funds to deploy and interact with contracts | +| [Explore Transactions](/smart-contracts/explorers/){target=\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state | +| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} | Remix | One‑click browser deployment to Polkadot Hub | +| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\_blank} | Foundry | Scripted deployments and testing from the CLI | +| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} | Hardhat | Project scaffolding, testing, and deployments | -Alternatively, you can set the provider in the network file: +## Build and Test Locally -```toml -[settings] -provider = "INSERT_PROVIDER" -... -``` +Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. -It's important to note that each provider has specific requirements and associated features. The following sections cover each provider's requirements and added features. +| Build and Test Locally | Tools | Description | +|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:| +| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\_blank} | Polkadot SDK node | Spin up a local node for iterative development | +| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts | +| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\_blank} | Remix | Publish verified source on explorers | +| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\_blank} | Foundry | Install toolchain and configure networks | +| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\_blank} | Foundry | Write and run Solidity tests locally | +| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\_blank} | Foundry | Verify deployed bytecode and metadata | +| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} | Hardhat | Initialize a project and configure networks | +| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} | Hardhat | Unit test contracts and run scripts | +| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\_blank} | Hardhat | Verify deployments on explorers | -### Kubernetes +## Ethereum Developer Resources -Kubernetes is a portable, extensible, open-source platform for managing containerized workloads and services. Zombienet is designed to be compatible with a variety of Kubernetes clusters, including: +Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. -- [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine){target=\_blank} -- [Docker Desktop](https://docs.docker.com/desktop/features/kubernetes/){target=\_blank} -- [kind](https://kind.sigs.k8s.io/){target=\_blank} +| Ethereum Developer Guides | Description | +|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:| +| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts | +| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\_blank} | Transaction types, fees, and multi‑dimensional metering | +| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} | Gas vs. weight, proof size, and storage deposits | +| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\_blank} | Deployment patterns and best practices on Polkadot Hub | +| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank} | Supported Ethereum JSON‑RPC methods and examples | +| [Migration](/smart-contracts/for-eth-devs/migration/){target=\_blank} | Port existing apps and tooling to Polkadot Hub | +| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} | Overview of EVM and native execution on the Hub | -#### Requirements - -To effectively interact with your cluster, you'll need to ensure that [`kubectl`](https://kubernetes.io/docs/reference/kubectl/){target=\_blank} is installed on your system. This Kubernetes command-line tool allows you to run commands against Kubernetes clusters. If you don't have `kubectl` installed, you can follow the instructions provided in the [Kubernetes documentation](https://kubernetes.io/docs/tasks/tools/#kubectl){target=\_blank}. +## Cookbook: Hands‑on Tutorials -To create resources such as namespaces, pods, and CronJobs within the target cluster, you must grant your user or service account the appropriate permissions. These permissions are essential for managing and deploying applications effectively within Kubernetes. +Follow step‑by‑step guides that walk through common tasks and complete dApp examples. -#### Features - -If available, Zombienet uses the Prometheus operator to oversee monitoring and visibility. This configuration ensures that only essential networking-related pods are deployed. Using the Prometheus operator, Zombienet improves its ability to monitor and manage network activities within the Kubernetes cluster efficiently. +| Tutorial | Tools | Description | +|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:| +| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} | Remix | Minimal deployment walkthrough | +| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token | +| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection | +| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\_blank} | Hardhat | Full dApp project: compile, test, deploy | +| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\_blank} | Multiple | End‑to‑end dApp patterns and practices | -### Podman +## Libraries -Podman is a daemonless container engine for developing, managing, and running Open Container Initiative (OCI) containers and container images on Linux-based systems. Zombienet supports Podman rootless as a provider on Linux machines. Although Podman has support for macOS through an internal virtual machine (VM), the Zombienet provider code requires Podman to run natively on Linux. +Choose the client libraries that fit your stack for connecting wallets and calling contracts. -#### Requirements - -To use Podman as a provider, you need to have Podman installed on your system. You can install Podman by following the instructions provided on the [Podman website](https://podman.io/getting-started/installation){target=\_blank}. +| Library | Description | +|:------------------------------------------------------------------:|:-------------------------------------------------------:| +| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank} | Connect, sign, and interact with contracts using Ethers | +| [viem](/smart-contracts/libraries/viem/){target=\_blank} | Type‑safe EVM interactions and utilities | +| [Wagmi](/smart-contracts/libraries/wagmi/){target=\_blank} | React hooks for wallet connections and contract calls | +| [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank} | Web3 provider and contract APIs | +| [Web3.py](/smart-contracts/libraries/web3-py/){target=\_blank} | Python toolkit for on‑chain interactions and scripts | -#### Features - -Using Podman, Zombienet deploys additional pods to enhance the monitoring and visibility of the active network. Specifically, pods for [Prometheus](https://prometheus.io/){target=\_blank}, [Tempo](https://grafana.com/docs/tempo/latest/operations/monitor/){target=\_blank}, and [Grafana](https://grafana.com/){target=\_blank} are included in the deployment. Grafana is configured with Prometheus and Tempo as data sources. +## Integrations -Upon launching Zombienet, access to these monitoring services is facilitated through specific URLs provided in the output: +Integrate essential services like wallets, indexers, and oracles to round out your dApp. -- **Prometheus**: `http://127.0.0.1:34123` -- **Tempo**: `http://127.0.0.1:34125` -- **Grafana**: `http://127.0.0.1:41461` +| Integration | Description | +|:-------------------------------------------------------------------:|:-----------------------------------------:| +| [Wallets](/smart-contracts/integrations/wallets/){target=\_blank} | Supported wallets and configuration notes | +| [Indexers](/smart-contracts/integrations/indexers/){target=\_blank} | Index and query blockchain data | +| [Oracles](/smart-contracts/integrations/oracles/){target=\_blank} | Bring external data on‑chain | -It's important to note that Grafana is deployed with default administrator access. - -When network operations cease, either from halting a running spawn with the `Ctrl+C` command or test completion, Zombienet automatically removes all associated pods. +## Precompiles -### Local Provider +Discover precompiled system contracts available on the Hub and how to use them. -The Zombienet local provider, also called native, enables you to run nodes as local processes in your environment. +| Topic | Description | +|:------------------------------------------------------------------------:|:---------------------------------------------------:| +| [Overview of Precompiles](/smart-contracts/precompiles/){target=\_blank} | What precompiles are available on the Hub | +| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\_blank} | EVM precompiles and interfaces | +| [Staking](/smart-contracts/precompiles/staking/){target=\_blank} | Interact with staking functionality via precompiles | +| [XCM](/smart-contracts/precompiles/xcm/){target=\_blank} | Cross‑chain messaging helpers for contracts | -#### Requirements - -You must have the necessary binaries for your network (such as `polkadot` and `polkadot-parachain`). These binaries should be available in your PATH, allowing Zombienet to spawn the nodes as local processes. +From here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\_blank} or reach out in the community channels. -To install the necessary binaries, you can use the Zombienet CLI command: -```bash -zombienet setup polkadot polkadot-parachain -``` +--- -This command will download and prepare the necessary binaries for Zombienet's use. +Page Title: Get Started with XCM -If you need to use a custom binary, ensure the binary is available in your PATH. You can also specify the binary path in the network configuration file. The following example uses the custom [OpenZeppelin template](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ +- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. -First, clone the OpenZeppelin template repository using the following command: +# Get Started with XCM -```bash -git clone https://github.com/OpenZeppelin/polkadot-runtime-templates \ -&& cd polkadot-runtime-templates/generic-template -``` +## Introduction -Next, run the command to build the custom binary: +Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. -```bash -cargo build --release -``` +With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. -Finally, add the custom binary to your PATH as follows: +## Messaging Format -```bash -export PATH=$PATH:INSERT_PATH_TO_RUNTIME_TEMPLATES/parachain-template-node/target/release -``` +XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. -Alternatively, you can specify the binary path in the network configuration file. The local provider exclusively utilizes the command configuration for nodes, which supports both relative and absolute paths. You can employ the `default_command` configuration to specify the binary for spawning all nodes in the relay chain. +XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. -```toml -[relaychain] -chain = "rococo-local" -default_command = "./bin-v1.6.0/polkadot" +## The Four Principles of XCM -[parachain] -id = 1000 +XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: - [parachain.collators] - name = "collator01" - command = "./target/release/parachain-template-node" -``` +- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. +- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. +- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. +- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. -#### Features +These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. -The local provider does not offer any additional features. +## The XCM Tech Stack -## Configure Zombienet +![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) -Effective network configuration is crucial for deploying and managing blockchain systems. Zombienet simplifies this process by offering versatile configuration options in both JSON and TOML formats. Whether setting up a simple test network or a complex multi-node system, Zombienet's tools provide the flexibility to customize every aspect of your network's setup. +The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. -The following sections will explore the structure and usage of Zombienet configuration files, explain key settings for network customization, and walk through CLI commands and flags to optimize your development workflow. +## Core Functionalities of XCM -### Configuration Files +XCM enhances cross-consensus communication by introducing several powerful features: -The network configuration file can be either JSON or TOML format. The Zombienet repository also provides a collection of [example configuration files](https://github.com/paritytech/zombienet/tree/main/examples){target=\_blank} that can be used as a reference. +- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. +- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. +- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. -Each section may include provider-specific keys that aren't recognized by other providers. For example, if you use the local provider, any references to images for nodes will be disregarded. +The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. -### CLI Usage +## XCM Example -Zombienet provides a CLI that allows interaction with the tool. The CLI can receive commands and flags to perform different kinds of operations. These operations use the following syntax: +The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). -```bash -zombienet +```rust +let message = Xcm(vec![ + WithdrawAsset((Here, amount).into()), + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } +]); ``` -The following sections will guide you through the primary usage of the Zombienet CLI and the available commands and flags. +The message consists of three instructions described as follows: -#### CLI Commands +- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. -- **`spawn `**: Spawn the network defined in the [configuration file](#configuration-files). -- **`test `**: Run tests on the spawned network using the assertions and tests defined in the [test file](/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/#the-test-file){target=\_blank}. -- **`setup `**: Set up the Zombienet development environment to download and use the `polkadot` or `polkadot-parachain` executable. -- **`convert `**: Transforms a [polkadot-launch](https://github.com/paritytech/polkadot-launch){target=\_blank} configuration file with a `.js` or `.json` extension into a Zombienet configuration file. -- **`version`**: Prints Zombienet version. -- **`help`**: Prints help information. + ```rust + WithdrawAsset((Here, amount).into()), + ``` -#### CLI Flags + - **`Here`**: The native parachain token. + - **`amount`**: The number of tokens that are transferred. -You can use the following flags to customize the behavior of the CLI: + The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. -- **`-p`, `--provider`**: Override the [provider](#providers) to use. -- **`-d`, `--dir`**: Specify a directory path for placing the network files instead of using the default temporary path. -- **`-f`, `--force`**: Force override all prompt commands. -- **`-l`, `--logType`**: Type of logging on the console. Defaults to `table`. -- **`-m`, `--monitor`**: Start as monitor and don't auto clean up network. -- **`-c`, `--spawn-concurrency`**: Number of concurrent spawning processes to launch. Defaults to `1`. -- **`-h`, `--help`**: Display help for command. +- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. -### Settings + ```rust + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + ``` -Through the keyword `settings`, it's possible to define the general settings for the network. The available keys are: + - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. + - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. -- **`global_volumes?`** ++"GlobalVolume[]"++: A list of global volumes to use. +- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. - ??? child "`GlobalVolume` interface definition" - ```js - export interface GlobalVolume { - name: string; - fs_type: string; - mount_path: string; + ```rust + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() } - ``` + ``` -- **`bootnode`** ++"boolean"++: Add bootnode to network. Defaults to `true`. -- **`bootnode_domain?`** ++"string"++: Domain to use for bootnode. -- **`timeout`** ++"number"++: Global timeout to use for spawning the whole network. -- **`node_spawn_timeout?`** ++"number"++: Timeout to spawn pod/process. -- **`grafana?`** ++"boolean"++: Deploy an instance of Grafana. -- **`prometheus?`** ++"boolean"++: Deploy an instance of Prometheus. -- **`telemetry?`** ++"boolean"++: Enable telemetry for the network. -- **`jaeger_agent?`** ++"string"++: The Jaeger agent endpoint passed to the nodes. Only available on Kubernetes. -- **`tracing_collator_url?`** ++"string"++: The URL of the tracing collator used to query by the tracing assertion. Should be tempo query compatible. -- **`tracing_collator_service_name?`** ++"string"++: Service name for tempo query frontend. Only available on Kubernetes. Defaults to `tempo-tempo-distributed-query-frontend`. -- **`tracing_collator_service_namespace?`** ++"string"++: Namespace where tempo is running. Only available on Kubernetes. Defaults to `tempo`. -- **`tracing_collator_service_port?`** ++"number"++: Port of the query instance of tempo. Only available on Kubernetes. Defaults to `3100`. -- **`enable_tracing?`** ++"boolean"++: Enable the tracing system. Only available on Kubernetes. Defaults to `true`. -- **`provider`** ++"string"++: Provider to use. Default is `kubernetes`". -- **`polkadot_introspector?`** ++"boolean"++: Deploy an instance of polkadot-introspector. Only available on Podman and Kubernetes. Defaults to `false`. -- **`backchannel?`** ++"boolean"++: Deploy an instance of backchannel server. Only available on Kubernetes. Defaults to `false`. -- **`image_pull_policy?`** ++"string"++: Image pull policy to use in the network. Possible values are `Always`, `IfNotPresent`, and `Never`. -- **`local_ip?`** ++"string"++: IP used for exposing local services (rpc/metrics/monitors). Defaults to `"127.0.0.1"`. -- **`global_delay_network_global_settings?`** ++"number"++: Delay in seconds to apply to the network. -- **`node_verifier?`** ++"string"++: Specify how to verify node readiness or deactivate by using `None`. Possible values are `None` and `Metric`. Defaults to `Metric`. + - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. + +This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. -For example, the following configuration file defines a minimal example for the settings: +## Overview -=== "TOML" +XCM revolutionizes cross-chain communication by enabling use cases such as: - ```toml title="base-example.toml" - [settings] - timeout = 1000 - bootnode = false - provider = "kubernetes" - backchannel = false - # ... +- Token transfers between blockchains. +- Asset locking for cross-chain smart contract interactions. +- Remote execution of functions on other blockchains. - ``` +These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. -=== "JSON" - ```json title="base-example.json" - { - "settings": { - "timeout": 1000, - "bootnode": false, - "provider": "kubernetes", - "backchannel": false, - "...": {} - }, - "...": {} - } +--- - ``` +Page Title: Install Polkadot SDK -### Relay Chain Configuration +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md +- Canonical (HTML): https://docs.polkadot.com/parachains/install-polkadot-sdk/ +- Summary: Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. -You can use the `relaychain` keyword to define further parameters for the relay chain at start-up. The available keys are: +# Install Polkadot SDK -- **`default_command?`** ++"string"++: The default command to run. Defaults to `polkadot`. -- **`default_image?`** ++"string"++: The default Docker image to use. -- **`default_resources?`** ++"Resources"++: Represents the resource limits/reservations the nodes need by default. Only available on Kubernetes. +This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts: - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } - ``` +- **Installing dependencies**: Setting up Rust, required system packages, and development tools. +- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. -- **`default_db_snapshot?`** ++"string"++: The default database snapshot to use. -- **`default_prometheus_prefix`** ++"string"++: A parameter for customizing the metric's prefix. Defaults to `substrate`. -- **`default_substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version. +Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } - ``` +## Install Dependencies: macOS -- **`default_keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. -- **`chain`** ++"string"++: The chain name. -- **`chain_spec_path?`** ++"string"++: Path to the chain spec file. Should be the plain version to allow customizations. -- **`chain_spec_command?`** ++"string"++: Command to generate the chain spec. It can't be used in combination with `chain_spec_path`. -- **`default_args?`** ++"string[]"++: An array of arguments to use as default to pass to the command. -- **`default_overrides?`** ++"Override[]"++: An array of overrides to upload to the node. +You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. - ??? child "`Override` interface definition" - ```js - export interface Override { - local_path: string; - remote_name: string; - } - ``` +### Before You Begin {: #before-you-begin-mac-os } -- **`random_nominators_count?`** ++"number"++: If set and the stacking pallet is enabled, Zombienet will generate the input quantity of nominators and inject them into the genesis. -- **`max_nominations`** ++"number"++: The max number of nominations allowed by a nominator. Should match the value set in the runtime. Defaults to `24`. -- **`nodes?`** ++"Node[]"++: An array of nodes to spawn. It is further defined in the [Node Configuration](#node-configuration) section. -- **`node_groups?`** ++"NodeGroup[]"++: An array of node groups to spawn. It is further defined in the [Node Group Configuration](#node-group-configuration) section. -- **`total_node_in_group?`** ++"number"++: The total number of nodes in the group. Defaults to `1`. -- **`genesis`** ++"JSON"++: The genesis configuration. -- **`default_delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. +Before you install Rust and set up your development environment on macOS, verify that your computer meets the following basic requirements: - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` +- Operating system version is 10.7 Lion or later. +- Processor speed of at least 2 GHz. Note that 3 GHz is recommended. +- Memory of at least 8 GB RAM. Note that 16 GB is recommended. +- Storage of at least 10 GB of available space. +- Broadband Internet connection. -#### Node Configuration +### Install Homebrew -One specific key capable of receiving more subkeys is the `nodes` key. This key is used to define further parameters for the nodes. The available keys: +In most cases, you should use Homebrew to install and manage packages on macOS computers. If you don't already have Homebrew installed on your local computer, you should download and install it before continuing. -- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). -- **`image?`** ++"string"++: Override default Docker image to use for this node. -- **`command?`** ++"string"++: Override default command to run. -- **`command_with_args?`** ++"string"++: Override default command and arguments. -- **`args?`** ++"string[]"++: Arguments to be passed to the command. -- **`env?`** ++"envVars[]"++: Environment variables to set in the container. +To install Homebrew: - ??? child "`envVars` interface definition" - ```js - export interface EnvVars { - name: string; - value: string; - } - ``` +1. Open the Terminal application. +2. Download and install Homebrew by running the following command: -- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. -- **`db_snapshot?`** ++"string"++: Database snapshot to use. -- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. + ```bash + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + ``` - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } - ``` +3. Verify Homebrew has been successfully installed by running the following command: -- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. + ```bash + brew --version + ``` - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } - ``` + The command displays output similar to the following: -- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. -- **`validator`** ++"boolean"++: Pass the `--validator` flag to the command. Defaults to `true`. -- **`invulnerable`** ++"boolean"++: If true, add the node to invulnerables in the chain spec. Defaults to `false`. -- **`balance`** ++"number"++: Balance to set in balances for node's account. Defaults to `2000000000000`. -- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. -- **`add_to_bootnodes?`** ++"boolean"++: Add this node to the bootnode list. Defaults to `false`. -- **`ws_port?`** ++"number"++: WS port to use. -- **`rpc_port?`** ++"number"++: RPC port to use. -- **`prometheus_port?`** ++"number"++: Prometheus port to use. -- **`p2p_cert_hash?`** ++"string"++: Libp2p certhash to use with webRTC transport. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. +
    + brew --version + Homebrew 4.3.15 +
    - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` +### Support for Apple Silicon -The following configuration file defines a minimal example for the relay chain, including the `nodes` key: +Protobuf must be installed before the build process can begin. To install it, run the following command: -=== "TOML" +```bash +brew install protobuf +``` - ```toml title="relaychain-example-nodes.toml" - [relaychain] - default_command = "polkadot" - default_image = "polkadot-debug:master" - chain = "rococo-local" - chain_spec_path = "INSERT_PATH_TO_CHAIN_SPEC" - default_args = ["--chain", "rococo-local"] +### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } - [[relaychain.nodes]] - name = "alice" - validator = true - balance = 1000000000000 +Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `openssl`. - [[relaychain.nodes]] - name = "bob" - validator = true - balance = 1000000000000 - # ... +To install `openssl` and the Rust toolchain on macOS: + +1. Open the Terminal application. +2. Ensure you have an updated version of Homebrew by running the following command: + ```bash + brew update ``` -=== "JSON" +3. Install the `openssl` package by running the following command: - ```json title="relaychain-example-nodes.json" - { - "relaychain": { - "default_command": "polkadot", - "default_image": "polkadot-debug:master", - "chain": "rococo-local", - "chain_spec_path": "INSERT_PATH_TO_CHAIN-SPEC.JSON", - "default_args": ["--chain", "rococo-local"], - "nodes": [ - { - "name": "alice", - "validator": true, - "balance": 1000000000000 - }, - { - "name": "bob", - "validator": true, - "balance": 1000000000000 - } - ] - } - } + ```bash + brew install openssl + ``` + +4. Download the `rustup` installation program and use it to install Rust by running the following command: + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -#### Node Group Configuration +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: -The `node_groups` key defines further parameters for the node groups. The available keys are: + ```bash + source ~/.cargo/env + ``` -- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). -- **`image?`** ++"string"++: Override default Docker image to use for this node. -- **`command?`** ++"string"++: Override default command to run. -- **`args?`** ++"string[]"++: Arguments to be passed to the command. -- **`env?`** ++"envVars[]"++: Environment variables to set in the container. - - ??? child "`envVars` interface definition" - ```js - export interface EnvVars { - name: string; - value: string; - } +7. Configure the Rust toolchain to default to the latest stable version by running the following commands: + + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` + +8. Install `cmake` using the following command: + + ```bash + brew install cmake + ``` + +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). + +## Install Dependencies: Linux + +Rust supports most Linux distributions. Depending on the specific distribution and version of the operating system you use, you might need to add some software dependencies to your environment. In general, your development environment should include a linker or a C-compatible compiler, such as `clang`, and an appropriate integrated development environment (IDE). + +### Before You Begin {: #before-you-begin-linux } + +Check the documentation for your operating system for information about the installed packages and how to download and install any additional packages you might need. For example, if you use Ubuntu, you can use the Ubuntu Advanced Packaging Tool (`apt`) to install the `build-essential` package: + +```bash +sudo apt install build-essential +``` + +At a minimum, you need the following packages before you install Rust: + +```text +clang curl git make +``` + +Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `libssl-dev` or `openssl-devel`. + +### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } + +To install the Rust toolchain on Linux: + +1. Open a terminal shell. +2. Check the packages installed on the local computer by running the appropriate package management command for your Linux distribution. +3. Add any package dependencies you are missing to your local development environment by running the appropriate package management command for your Linux distribution: + + === "Ubuntu" + + ```bash + sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler ``` -- **`overrides?`** ++"Override[]"++: Array of overrides definitions. + === "Debian" - ??? child "`Override` interface definition" - ```js - export interface Override { - local_path: string; - remote_name: string; - } + ```sh + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler ``` -- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. -- **`db_snapshot?`** ++"string"++: Database snapshot to use. -- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. + === "Arch" - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } + ```sh + pacman -Syu --needed --noconfirm curl git clang make protobuf ``` -- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. + === "Fedora" - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } + ```sh + sudo dnf update + sudo dnf install clang curl git openssl-devel make protobuf-compiler ``` -- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. -- **`count`** ++"number | string"++: Number of nodes to launch for this group. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. + === "OpenSUSE" - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } + ```sh + sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf ``` -The following configuration file defines a minimal example for the relay chain, including the `node_groups` key: + Remember that different distributions might use different package managers and bundle packages in different ways. For example, depending on your installation selections, Ubuntu Desktop and Ubuntu Server might have different packages and different requirements. However, the packages listed in the command-line examples are applicable to many common Linux distributions, including Debian, Linux Mint, MX Linux, and Elementary OS. -=== "TOML" +4. Download the `rustup` installation program and use it to install Rust by running the following command: - ```toml title="relaychain-example-node-groups.toml" - [relaychain] - default_command = "polkadot" - default_image = "polkadot-debug:master" - chain = "rococo-local" - chain_spec_path = "INSERT_PATH_TO_CHAIN_SPEC" - default_args = ["--chain", "rococo-local"] + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` - [[relaychain.node_groups]] - name = "group-1" - count = 2 - image = "polkadot-debug:master" - command = "polkadot" - args = ["--chain", "rococo-local"] - # ... +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: + ```bash + source $HOME/.cargo/env ``` -=== "JSON" +7. Verify your installation by running the following command: - ```json title="relaychain-example-node-groups.json" - { - "relaychain": { - "default_command": "polkadot", - "default_image": "polkadot-debug:master", - "chain": "rococo-local", - "chain_spec_path": "INSERT_PATH_TO_CHAIN-SPEC.JSON", - "default_args": ["--chain", "rococo-local"], - "node_groups": [ - { - "name": "group-1", - "count": 2, - "image": "polkadot-debug:master", - "command": "polkadot", - "args": ["--chain", "rococo-local"] - } - ], - "...": {} - }, - "...": {} - } + ```bash + rustc --version + ``` + +8. Configure the Rust toolchain to default to the latest stable version by running the following commands: + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src ``` -### Parachain Configuration +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -The `parachain` keyword defines further parameters for the parachain. The available keys are: +## Install Dependencies: Windows (WSL) -- **`id`** ++"number"++: The id to assign to this parachain. Must be unique. -- **`chain?`** ++"string"++: The chain name. -- **`force_decorator?`** ++"string"++: Force the use of a specific decorator. -- **`genesis?`** ++"JSON"++: The genesis configuration. -- **`balance?`** ++"number"++: Balance to set in balances for parachain's account. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. +In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` +However, suppose your local computer uses Microsoft Windows instead of a UNIX-based operating system. In that case, you can configure it with additional software to make it a suitable development environment for building Substrate-based blockchains. To prepare a development environment on a Microsoft Windows computer, you can use Windows Subsystem for Linux (WSL) to emulate a UNIX operating environment. -- **`add_to_genesis?`** ++"boolean"++: Flag to add parachain to genesis or register in runtime. Defaults to `true`. -- **`register_para?`** ++"boolean"++: Flag to specify whether the para should be registered. The `add_to_genesis` flag must be set to false for this flag to have any effect. Defaults to `true`. -- **`onboard_as_parachain?`** ++"boolean"++: Flag to specify whether the para should be onboarded as a parachain, rather than remaining a parathread. Defaults to `true`. -- **`genesis_wasm_path?`** ++"string"++: Path to the Wasm file to use. -- **`genesis_wasm_generator?`** ++"string"++: Command to generate the Wasm file. -- **`genesis_state_path?`** ++"string"++: Path to the state file to use. -- **`genesis_state_generator?`** ++"string"++: Command to generate the state file. -- **`chain_spec_path?`** ++"string"++: Path to the chain spec file. -- **`chain_spec_command?`** ++"string"++: Command to generate the chain spec. -- **`cumulus_based?`** ++"boolean"++: Flag to use cumulus command generation. Defaults to `true`. -- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. -- **`prometheus_prefix?`** ++"string"++: Parameter for customizing the metric's prefix for all parachain nodes/collators. Defaults to `substrate`. -- **`collator?`** ++"Collator"++: Further defined in the [Collator Configuration](#collator-configuration) section. -- **`collator_groups?`** ++"CollatorGroup[]"++: An array of collator groups to spawn. It is further defined in the [Collator Groups Configuration](#collator-groups-configuration) section. - -For example, the following configuration file defines a minimal example for the parachain: +### Before You Begin {: #before-you-begin-windows-wls } -=== "TOML" +Before installing on Microsoft Windows, verify the following basic requirements: - ```toml title="parachain-example.toml" - [parachain] - id = 100 - add_to_genesis = true - cumulus_based = true - genesis_wasm_path = "INSERT_PATH_TO_WASM" - genesis_state_path = "INSERT_PATH_TO_STATE" - # ... +- You have a computer running a supported Microsoft Windows operating system: + - **For Windows desktop**: You must be running Microsoft Windows 10, version 2004 or later, or Microsoft Windows 11 to install WSL. + - **For Windows server**: You must be running Microsoft Windows Server 2019, or later, to install WSL on a server operating system. +- You have a good internet connection and access to a shell terminal on your local computer. - ``` +### Set Up Windows Subsystem for Linux -=== "JSON" +WSL enables you to emulate a Linux environment on a computer that uses the Windows operating system. The primary advantage of this approach for Substrate development is that you can use all of the code and command-line examples as described in the Substrate documentation. For example, you can run common commands—such as `ls` and `ps`—unmodified. By using WSL, you can avoid configuring a virtual machine image or a dual-boot operating system. - ```json title="parachain-example.json" - { - "parachain": { - "id": 100, - "add_to_genesis": true, - "cumulus_based": true, - "genesis_wasm_path": "INSERT_PATH_TO_WASM", - "genesis_state_path": "INSERT_PATH_TO_STATE", - "...": {} - }, - "...": {} - } +To prepare a development environment using WSL: +1. Check your Windows version and build number to see if WSL is enabled by default. + + If you have Microsoft Windows 10, version 2004 (Build 19041 and higher), or Microsoft Windows 11, WSL is available by default and you can continue to the next step. + + If you have an older version of Microsoft Windows installed, see the [WSL manual installation steps for older versions](https://learn.microsoft.com/en-us/windows/wsl/install-manual){target=\_blank}. If you are installing on an older version of Microsoft Windows, you can download and install WLS 2 if your computer has Windows 10, version 1903 or higher. + +2. Select **Windows PowerShell** or **Command Prompt** from the **Start** menu, right-click, then **Run as administrator**. + +3. In the PowerShell or Command Prompt terminal, run the following command: + + ```bash + wsl --install ``` -#### Collator Configuration + This command enables the required WSL 2 components that are part of the Windows operating system, downloads the latest Linux kernel, and installs the Ubuntu Linux distribution by default. -One specific key capable of receiving more subkeys is the `collator` key. This key defines further parameters for the nodes. The available keys are: + If you want to review the other Linux distributions available, run the following command: -- **`name`** ++"string"++: Name of the collator. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). -- **`image?`** ++"string"++: Image to use for the collator. -- **`command_with_args?`** ++"string"++: Overrides both command and arguments for the collator. -- **`validator`** ++"boolean"++: Pass the `--validator` flag to the command. Defaults to `true`. -- **`invulnerable`** ++"boolean"++: If true, add the collator to invulnerables in the chain spec. Defaults to `false`. -- **`balance`** ++"number"++: Balance to set in balances for collator's account. Defaults to `2000000000000`. -- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. -- **`add_to_bootnodes?`** ++"boolean"++: Add this collator to the bootnode list. Defaults to `false`. -- **`ws_port?`** ++"number"++: WS port to use. -- **`rpc_port?`** ++"number"++: RPC port to use. -- **`prometheus_port?`** ++"number"++: Prometheus port to use. -- **`p2p_port?`** ++"number"++: P2P port to use. -- **`p2p_cert_hash?`** ++"string"++: Libp2p certhash to use with webRTC transport. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. + ```bash + wsl --list --online + ``` - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` +4. After the distribution is downloaded, close the terminal. -- **`command?`** ++"string"++: Override default command to run. -- **`args?`** ++"string[]"++: Arguments to be passed to the command. -- **`env?`** ++"envVars[]"++: Environment variables to set in the container. +5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. - ??? child "`envVars` interface definition" - ```js - export interface EnvVars { - name: string; - value: string; - } - ``` + Restarting the computer is required to start the installation of the Linux distribution. It can take a few minutes for the installation to complete after you restart. -- **`overrides?`** ++"Override[]"++: Array of overrides definitions. + For more information about setting up WSL as a development environment, see the [Set up a WSL development environment](https://learn.microsoft.com/en-us/windows/wsl/setup/environment){target=\_blank} docs. - ??? child "`Override` interface definition" - ```js - export interface Override { - local_path: string; - remote_name: string; - } - ``` +### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } -- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. -- **`db_snapshot?`** ++"string"++: Database snapshot to use. -- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. +To install the Rust toolchain on WSL: - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } - ``` +1. Click the **Start** menu, then select **Ubuntu**. +2. Type a UNIX user name to create a user account. +3. Type a password for your UNIX user, then retype the password to confirm it. +4. Download the latest updates for the Ubuntu distribution using the Ubuntu Advanced Packaging Tool (`apt`) by running the following command: -- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. + ```bash + sudo apt update + ``` - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } - ``` +5. Add the required packages for the Ubuntu distribution by running the following command: -- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. + ```bash + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler + ``` -The configuration file below defines a minimal example for the collator: +6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: -=== "TOML" + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` - ```toml title="collator-example.toml" - [parachain] - id = 100 - add_to_genesis = true - cumulus_based = true - genesis_wasm_path = "INSERT_PATH_TO_WASM" - genesis_state_path = "INSERT_PATH_TO_STATE" +7. Follow the prompts displayed to proceed with a default installation. - [[parachain.collators]] - name = "alice" - image = "polkadot-parachain" - command = "polkadot-parachain" - # ... +8. Update your current shell to include Cargo by running the following command: + ```bash + source ~/.cargo/env ``` -=== "JSON" +9. Verify your installation by running the following command: - ```json title="collator-example.json" - { - "parachain": { - "id": 100, - "add_to_genesis": true, - "cumulus_based": true, - "genesis_wasm_path": "INSERT_PATH_TO_WASM", - "genesis_state_path": "INSERT_PATH_TO_STATE", - "collators": [ - { - "name": "alice", - "image": "polkadot-parachain", - "command": "polkadot-parachain", - "...": {} - } - ] - }, - "...": {} - } + ```bash + rustc --version + ``` + +10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src ``` -#### Collator Groups Configuration +11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -The `collator_groups` key defines further parameters for the collator groups. The available keys are: +## Build the Polkadot SDK -- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). -- **`image?`** ++"string"++: Override default Docker image to use for this node. -- **`command?`** ++"string"++: Override default command to run. -- **`args?`** ++"string[]"++: Arguments to be passed to the command. -- **`env?`** ++"envVars[]"++: Environment variables to set in the container. +After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. - ??? child "`envVars` interface definition" - ```js - export interface EnvVars { - name: string; - value: string; - } - ``` +### Clone the Polkadot SDK -- **`overrides?`** ++"Override[]"++: Array of overrides definitions. +1. Clone the Polkadot SDK repository: - ??? child "`Override` interface definition" - ```js - export interface Override { - local_path: string; - remote_name: string; - } - ``` + ```bash + git clone https://github.com/paritytech/polkadot-sdk.git + ``` -- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. -- **`db_snapshot?`** ++"string"++: Database snapshot to use. -- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. +2. Navigate into the project directory: - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } - ``` + ```bash + cd polkadot-sdk + ``` -- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. +### Compile the Polkadot SDK - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } - ``` - -- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. -- **`count`** ++"number | string"++: Number of nodes to launch for this group. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. - - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` - -For instance, the configuration file below defines a minimal example for the collator groups: +Compile the entire Polkadot SDK repository to ensure your environment is properly configured: -=== "TOML" +```bash +cargo build --release --locked +``` - ```toml title="collator-groups-example.toml" - [parachain] - id = 100 - add_to_genesis = true - cumulus_based = true - genesis_wasm_path = "INSERT_PATH_TO_WASM" - genesis_state_path = "INSERT_PATH_TO_STATE" +!!!note + This initial compilation will take significant time, depending on your machine specifications. It compiles all components of the Polkadot SDK to verify your toolchain is correctly configured. - [[parachain.collator_groups]] - name = "group-1" - count = 2 - image = "polkadot-parachain" - command = "polkadot-parachain" - # ... +### Verify the Build - ``` +Once the build completes successfully, verify the installation by checking the compiled binaries: -=== "JSON" +```bash +ls target/release +``` - ```json title="collator-groups-example.json" - { - "parachain": { - "id": 100, - "add_to_genesis": true, - "cumulus_based": true, - "genesis_wasm_path": "INSERT_PATH_TO_WASM", - "genesis_state_path": "INSERT_PATH_TO_STATE", - "collator_groups": [ - { - "name": "group-1", - "count": 2, - "image": "polkadot-parachain", - "command": "polkadot-parachain", - "...": {} - } - ] - }, - "...": {} - } +You should see several binaries, including: - ``` +- `polkadot`: The Polkadot relay chain node. +- `polkadot-parachain`: The parachain collator node. +- `polkadot-omni-node`:The omni node for running parachains. +- `substrate-node`: The kitchensink node with many pre-configured pallets. -### XCM Configuration +Verify the Polkadot binary works by checking its version: -You can use the `hrmp_channels` keyword to define further parameters for the XCM channels at start-up. The available keys are: +```bash +./target/release/polkadot --version +``` -- **`hrmp_channels`** ++"HrmpChannelsConfig[]"++: Array of Horizontal Relay-routed Message Passing (HRMP) channel configurations. +This should display version information similar to: - ??? child "`HrmpChannelsConfig` interface definition" - ```js - export interface HrmpChannelsConfig { - sender: number; - recipient: number; - max_capacity: number; - max_message_size: number; - } - ``` - Each of the `HrmpChannelsConfig` keys are defined as follows: +```bash +polkadot 1.16.0-1234abcd567 +``` - - **`sender` ++"number"++**: Parachain ID of the sender. - - **`recipient` ++"number"++**: Parachain ID of the recipient. - - **`max_capacity` ++"number"++**: Maximum capacity of the HRMP channel. - - **`max_message_size` ++"number"++**: Maximum message size allowed in the HRMP channel. +If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! -## Where to Go Next +## Optional: Run the Kitchensink Node -
    +The Polkadot SDK includes a feature-rich node called "kitchensink" located at `substrate/bin/node`. This node comes pre-configured with many pallets and features from the Polkadot SDK, making it an excellent reference for exploring capabilities and understanding how different components work together. -- External __Zombienet Support__ +!!!note + If you've already compiled the Polkadot SDK in the previous step, the `substrate-node` binary is already built and ready to use. You can skip directly to running the node. - --- +### Run the Kitchensink Node in Development Mode - [Parity Technologies](https://www.parity.io/){target=\_blank} has designed and developed this framework, now maintained by the Zombienet team. +From the `polkadot-sdk` root directory, start the kitchensink node in development mode: - For further support and information, refer to the following contact points: +```bash +./target/release/substrate-node --dev +``` - [:octicons-arrow-right-24: Zombienet repository](https://github.com/paritytech/zombienet){target=\_blank} +The `--dev` flag enables development mode, which: - [:octicons-arrow-right-24: Element public channel](https://matrix.to/#/!FWyuEyNvIFygLnWNMh:parity.io?via=parity.io&via=matrix.org&via=web3.foundation){target=\_blank} +- Runs a single-node development chain. +- Produces and finalizes blocks automatically. +- Uses pre-configured development accounts (Alice, Bob, etc.). +- Deletes all data when stopped, ensuring a clean state on restart. -- Tutorial __Spawn a Basic Chain with Zombienet__ +You should see log output indicating the node is running and producing blocks, with increasing block numbers after `finalized`. - --- +### Interact with the Kitchensink Node - Learn to spawn, connect to and monitor a basic blockchain network with Zombienet, using customizable configurations for streamlined development and debugging. +The kitchensink node is accessible at `ws://localhost:9944`. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your browser to explore its features and connect to the local node. - [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/spawn-basic-chain/) +1. Click the network icon in the top left corner. +2. Scroll to **Development** and select **Local Node**. +3. Click **Switch** to connect to your local node. -
    +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) +Once connected, the interface updates its color scheme to indicate a successful connection to the local node. ---- +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) -Page Title: Get Started with Parachain Development +You can now explore the various pallets and features included in the kitchensink node, making it a valuable reference as you develop your own blockchain applications. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/get-started/ -- Summary: Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. +To stop the node, press `Control-C` in the terminal. -# Get Started +## Where to Go Next -The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. +
    -## Quick Start Guides +- __Get Started with Parachain Development__ -Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. + --- -| Tutorial | Tools | Description | -| :--------------------------------------------------------------------------------------------: | :----------------------------: | :---------------------------------------------------------------------: | -| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | Learn how to set up and run the Polkadot SDK Parachain Template locally | -| [Launch a Local Parachain](/parachains/testing/run-a-parachain-network/) | Zombienet, Chopsticks | Set up a local development environment for testing | -| [Connect to Polkadot](/chain-interactions/query-on-chain-data/query-sdks/) | Polkadot.js, Substrate Connect | Connect your application to Polkadot networks | -| [Fork an Existing Parachain](/parachains/testing/fork-a-parachain/) | Chopsticks | Create a local fork of a live parachain for testing | + Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. -## Launch a Simple Parachain + [:octicons-arrow-right-24: Get Started](/parachains/get-started/) + +
    -Learn the fundamentals of launching and deploying a parachain to the Polkadot network. -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------: | -| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | -| [Deploy to Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/) | Step-by-step tutorial to deploying your parachain to Polkadot | -| [Obtain Coretime](/parachains/launch-a-parachain/obtain-coretime/) | Learn how to acquire blockspace using Polkadot's coretime model (RegionX) | +--- -## Customize Your Runtime +Page Title: JSON-RPC APIs -Build custom functionality for your parachain by composing and creating pallets. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ +- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. -| Tutorial | Description | -| :-------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------: | -| [Add Existing Pallets to the Runtime](/parachains/customize-runtime/add-existing-pallets/) | Integrate pre-built pallets from the FRAME ecosystem | -| [Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/) | Configure and use multiple instances of the same pallet | -| [Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/) | Enable smart contract capabilities using Contracts or EVM pallets | +# JSON-RPC APIs -### Pallet Development +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -Deep dive into creating and managing custom pallets for your parachain. +Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------: | -| [Create a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/) | Build a pallet from scratch with custom logic | -| [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/) | Set up a mock runtime environment for testing | -| [Pallet Unit Testing](/parachains/customize-runtime/pallet-development/pallet-testing/) | Write comprehensive tests for your pallet logic | -| [Add Your Custom Pallet to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/) | Integrate your custom pallet into your parachain runtime | -| [Benchmark the Custom Pallet](/parachains/customize-runtime/pallet-development/benchmark-pallet/) | Measure and optimize pallet performance with benchmarking | +This guide uses the Polkadot Hub TestNet endpoint: -## Testing +```text +https://testnet-passet-hub-eth-rpc.polkadot.io +``` -Test your parachain in various environments before production deployment. +## Available Methods -| Tutorial | Description | -| :---------------------------------------------------------------------: | :-----------------------------------------------------: | -| [Fork a Parachain](/parachains/testing/fork-a-parachain/) | Use Chopsticks to create a local fork for testing | -| [Run a Parachain Network](/parachains/testing/run-a-parachain-network/) | Launch a complete parachain test network with Zombienet | +### eth_accounts -## Runtime Upgrades and Maintenance +Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. -Manage your parachain's lifecycle with forkless upgrades and maintenance operations. +**Parameters**: -| Tutorial | Description | -| :-----------------------------------------------------------------------: | :--------------------------------------------------: | -| [Runtime Upgrades](/parachains/runtime-maintenance/runtime-upgrades/) | Perform forkless runtime upgrades via governance | -| [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/) | Safely migrate storage when updating runtime logic | -| [Unlock Parachains](/parachains/runtime-maintenance/unlock-parachains/) | Understand parachain lifecycle and unlock mechanisms | +None. -## Interoperability +**Example**: -Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). +```bash title="eth_accounts" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_accounts", + "params":[], + "id":1 +}' +``` -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: | -| [Open HRMP Channels Between Parachains](/parachains/interoperability/channels-between-parachains/) | Establish communication channels with other parachains | -| [Open HRMP Channels with System Parachains](/parachains/interoperability/channels-with-system-parachains/) | Connect with Asset Hub and other system parachains | +--- -## Integrations +### eth_blockNumber -Integrate your parachain with essential ecosystem tools and services. +Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. -| Tutorial | Description | -| :--------------------------------------------: | :----------------------------------------------------: | -| [Wallets](/parachains/integrations/wallets/) | Integrate wallet support for user interactions | -| [Indexers](/parachains/integrations/indexers/) | Set up indexing solutions for querying blockchain data | -| [Oracles](/parachains/integrations/oracles/) | Connect your parachain to off-chain data sources | +**Parameters**: -## Additional Resources +None. -- [Polkadot SDK Documentation](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/index.html) -- [Polkadot Wiki - Parachains](https://wiki.polkadot.network/docs/learn-parachains/) +**Example**: +```bash title="eth_blockNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_blockNumber", + "params":[], + "id":1 +}' +``` --- -Page Title: Get Started with Smart Contracts - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/get-started/ -- Summary: Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. - -# Get Started - -This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need. - -## Quick Starts - -Kick off development fast with curated links for connecting, funding, exploring, and deploying your first contract. +### eth_call -| Quick Start | Tools | Description | -|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:| -| [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer | -| [Get Test Tokens](/smart-contracts/faucets/){target=\_blank} | - | Request test funds to deploy and interact with contracts | -| [Explore Transactions](/smart-contracts/explorers/){target=\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state | -| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} | Remix | One‑click browser deployment to Polkadot Hub | -| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\_blank} | Foundry | Scripted deployments and testing from the CLI | -| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} | Hardhat | Project scaffolding, testing, and deployments | +Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. -## Build and Test Locally +**Parameters**: -Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. +- **`transaction` ++"object"++**: The transaction call object. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -| Build and Test Locally | Tools | Description | -|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:| -| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\_blank} | Polkadot SDK node | Spin up a local node for iterative development | -| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts | -| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\_blank} | Remix | Publish verified source on explorers | -| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\_blank} | Foundry | Install toolchain and configure networks | -| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\_blank} | Foundry | Write and run Solidity tests locally | -| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\_blank} | Foundry | Verify deployed bytecode and metadata | -| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} | Hardhat | Initialize a project and configure networks | -| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} | Hardhat | Unit test contracts and run scripts | -| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\_blank} | Hardhat | Verify deployments on explorers | +**Example**: -## Ethereum Developer Resources +```bash title="eth_call" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_call", + "params":[{ + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_CALL" + }, "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. +Ensure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values. -| Ethereum Developer Guides | Description | -|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:| -| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts | -| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\_blank} | Transaction types, fees, and multi‑dimensional metering | -| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} | Gas vs. weight, proof size, and storage deposits | -| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\_blank} | Deployment patterns and best practices on Polkadot Hub | -| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank} | Supported Ethereum JSON‑RPC methods and examples | -| [Migration](/smart-contracts/for-eth-devs/migration/){target=\_blank} | Port existing apps and tooling to Polkadot Hub | -| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} | Overview of EVM and native execution on the Hub | +--- -## Cookbook: Hands‑on Tutorials +### eth_chainId -Follow step‑by‑step guides that walk through common tasks and complete dApp examples. +Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}. -| Tutorial | Tools | Description | -|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:| -| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} | Remix | Minimal deployment walkthrough | -| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token | -| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection | -| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\_blank} | Hardhat | Full dApp project: compile, test, deploy | -| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\_blank} | Multiple | End‑to‑end dApp patterns and practices | +**Parameters**: -## Libraries +None. -Choose the client libraries that fit your stack for connecting wallets and calling contracts. +**Example**: -| Library | Description | -|:------------------------------------------------------------------:|:-------------------------------------------------------:| -| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank} | Connect, sign, and interact with contracts using Ethers | -| [viem](/smart-contracts/libraries/viem/){target=\_blank} | Type‑safe EVM interactions and utilities | -| [Wagmi](/smart-contracts/libraries/wagmi/){target=\_blank} | React hooks for wallet connections and contract calls | -| [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank} | Web3 provider and contract APIs | -| [Web3.py](/smart-contracts/libraries/web3-py/){target=\_blank} | Python toolkit for on‑chain interactions and scripts | +```bash title="eth_chainId" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_chainId", + "params":[], + "id":1 +}' +``` -## Integrations +--- -Integrate essential services like wallets, indexers, and oracles to round out your dApp. +### eth_estimateGas -| Integration | Description | -|:-------------------------------------------------------------------:|:-----------------------------------------:| -| [Wallets](/smart-contracts/integrations/wallets/){target=\_blank} | Supported wallets and configuration notes | -| [Indexers](/smart-contracts/integrations/indexers/){target=\_blank} | Index and query blockchain data | -| [Oracles](/smart-contracts/integrations/oracles/){target=\_blank} | Bring external data on‑chain | +Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}. -## Precompiles +**Parameters**: -Discover precompiled system contracts available on the Hub and how to use them. +- **`transaction` ++"object"++**: The transaction call object. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -| Topic | Description | -|:------------------------------------------------------------------------:|:---------------------------------------------------:| -| [Overview of Precompiles](/smart-contracts/precompiles/){target=\_blank} | What precompiles are available on the Hub | -| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\_blank} | EVM precompiles and interfaces | -| [Staking](/smart-contracts/precompiles/staking/){target=\_blank} | Interact with staking functionality via precompiles | -| [XCM](/smart-contracts/precompiles/xcm/){target=\_blank} | Cross‑chain messaging helpers for contracts | +**Example**: -From here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\_blank} or reach out in the community channels. +```bash title="eth_estimateGas" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_estimateGas", + "params":[{ + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_FUNCTION_CALL" + }], + "id":1 +}' +``` +Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. --- -Page Title: Glossary - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md -- Canonical (HTML): https://docs.polkadot.com/reference/glossary/ -- Summary: Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. - -# Glossary - -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. - -Additional glossaries from around the ecosystem you might find helpful: - -- [Polkadot Wiki Glossary](https://wiki.polkadot.com/general/glossary){target=\_blank} -- [Polkadot SDK Glossary](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/glossary/index.html){target=\_blank} - -## Authority +### eth_gasPrice -The role in a blockchain that can participate in consensus mechanisms. +Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. -- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final. -- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author). +**Parameters**: -Authority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol. +None. -## Authority Round (Aura) +**Example**: -A deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol. +```bash title="eth_gasPrice" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_gasPrice", + "params":[], + "id":1 +}' +``` -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. +--- -## Blind Assignment of Blockchain Extension (BABE) +### eth_getBalance -A [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block. +Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. +**Parameters**: -## Block Author +- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -The node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_. +**Example**: -## Byzantine Fault Tolerance (BFT) +```bash title="eth_getBalance" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBalance", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -The ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack. +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -### Byzantine Failure +--- -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. +### eth_getBlockByHash -### Practical Byzantine Fault Tolerance (pBFT) +Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. +**Parameters**: -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. +- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. -### Preimage +**Example**: -A preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\_blank}, the output, the hash, cannot be used to reveal the input, the preimage. +```bash title="eth_getBlockByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockByHash", + "params":["INSERT_BLOCK_HASH", INSERT_BOOLEAN], + "id":1 +}' +``` -## Call +Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values. -In the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object. +--- -## Chain Specification +### eth_getBlockByNumber -A chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains. +Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. -## Collator +**Parameters**: -An [author](#block-author) of a [parachain](#parachain) network. -They aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus). +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. +**Example**: -## Collective +```bash title="eth_getBlockByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockByNumber", + "params":["INSERT_BLOCK_VALUE", INSERT_BOOLEAN], + "id":1 +}' +``` -Most often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network. +Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values. -## Consensus +--- -Consensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship. +### eth_getBlockTransactionCountByNumber -See also [hybrid consensus](#hybrid-consensus). +Returns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\_blank}. -## Consensus Algorithm +**Parameters**: -Ensures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft). +- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -Consensus algorithms are generally concerned with ensuring two properties: +**Example**: -- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. -- **Liveness**: Indicating the ability of the chain to keep progressing. +```bash title="eth_getBlockTransactionCountByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockTransactionCountByNumber", + "params":["INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -## Consensus Engine +Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. -The node subsystem responsible for consensus tasks. +--- -For detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} blog series. +### eth_getBlockTransactionCountByHash -See also [hybrid consensus](#hybrid-consensus). +Returns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}. -## Coretime +**Parameters**: -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. +- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -On-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety. +**Example**: -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank}. - -## Development Phrase - -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. - -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: - -``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk +```bash title="eth_getBlockTransactionCountByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockTransactionCountByHash", + "params":["INSERT_BLOCK_HASH"], + "id":1 +}' ``` -Many tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`. - -## Digest - -An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: - -- [Light clients](#light-client) for chain synchronization. -- Consensus engines for block verification. -- The runtime itself, in the case of pre-runtime digests. - -## Dispatchable - -Function objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations. +Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. -## Events +--- -A means of recording that some particular [state](#state) transition happened. +### eth_getCode -In the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization. +Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. -## Executor +**Parameters**: -A means of executing a function call in a given [runtime](#runtime) with a set of dependencies. -There are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_. +- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). -- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes. +**Example**: -- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain. +```bash title="eth_getCode" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getCode", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -## Existential Deposit +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -The minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. +--- -If an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\_blank} to drop its references to that account. +### eth_getLogs -If the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\_blank}. +Returns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}. -## Extrinsic +**Parameters**: -A general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder. +- **`filter` ++"object"++**: The filter object. + - **`fromBlock` ++"string"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + - **`toBlock` ++"string"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + - **`address` ++"string" or "array of strings"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`topics` ++"array of strings"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string or an array of such strings (meaning OR). + - **`blockhash` ++"string"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -It is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). +**Example**: -For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. +```bash title="eth_getLogs" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getLogs", + "params":[{ + "fromBlock": "latest", + "toBlock": "latest" + }], + "id":1 +}' +``` -## Fork Choice Rule/Strategy +--- -A fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\_blank}, in which the chain with the most blocks is selected. +### eth_getStorageAt -## FRAME (Framework for Runtime Aggregation of Modularized Entities) +Returns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}. -Enables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes. +**Parameters**: -[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank} +- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`storageKey` ++"string"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). -## Full Node +**Example**: -A node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization. +```bash title="eth_getStorageAt" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getStorageAt", + "params":["INSERT_ADDRESS", "INSERT_STORAGE_KEY", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -## Genesis Configuration +Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. -A mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file. +--- -## GRANDPA +### eth_getTransactionCount -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. +Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}. -The [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\_blank}. +**Parameters**: -## Header +- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). -A structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization. +**Example**: -## Hybrid Consensus +```bash title="eth_getTransactionCount" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionCount", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -Hybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa). +--- -## Inherent Transactions +### eth_getTransactionByHash -A special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block. +Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. -Only the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified. +**Parameters**: -## JSON-RPC +- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -A stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON. +**Example**: -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. +```bash title="eth_getTransactionByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByHash", + "params":["INSERT_TRANSACTION_HASH"], + "id":1 +}' +``` -## Keystore +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. -A subsystem for managing keys for the purpose of producing new blocks. +--- -## Kusama +### eth_getTransactionByBlockNumberAndIndex -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. +Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. -Kusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\_blank} network and is referred to as [Polkadot's "wild cousin."](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\_blank}. +**Parameters**: -As a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation. +- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -## libp2p +**Example**: -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). +```bash title="eth_getTransactionByBlockNumberAndIndex" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByBlockNumberAndIndex", + "params":["INSERT_BLOCK_VALUE", "INSERT_TRANSACTION_INDEX"], + "id":1 +}' +``` -Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. +Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. -## Light Client +--- -A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. +### eth_getTransactionByBlockHashAndIndex -A light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\_blank} server, enabling blockchain users to interact with the network. +Returns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}. -## Metadata +**Parameters**: -Data that provides information about one or more aspects of a system. -The metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system. +- **`blockHash` ++"string"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -## Nominated Proof of Stake (NPoS) +**Example**: -A method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes. +```bash title="eth_getTransactionByBlockHashAndIndex" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByBlockHashAndIndex", + "params":["INSERT_BLOCK_HASH", "INSERT_TRANSACTION_INDEX"], + "id":1 +}' +``` -## Oracle +Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. -An entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services. +--- -## Origin +### eth_getTransactionReceipt -A [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\_blank}. +Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. -## Pallet +**Parameters**: -A module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime). -Pallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item). +- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -## Parachain +**Example**: -A parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_. -You can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\_blank}. +```bash title="eth_getTransactionReceipt" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionReceipt", + "params":["INSERT_TRANSACTION_HASH"], + "id":1 +}' +``` -## Paseo +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. -Paseo TestNet provisions testing on Polkadot's "production" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing. +--- -## Polkadot +### eth_maxPriorityFeePerGas -The [Polkadot network](https://polkadot.com/){target=\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain). +Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. -## Polkadot Cloud +**Parameters**: -Polkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance. +None. -## Polkadot Hub +**Example**: -Polkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3. +```bash title="eth_maxPriorityFeePerGas" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_maxPriorityFeePerGas", + "params":[], + "id":1 +}' +``` -## PolkaVM +--- -PolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution. +### eth_sendRawTransaction -## Relay Chain +Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. -Relay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another. +**Parameters**: -## Rococo +- **`callData` ++"string"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -A [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead. +**Example**: -## Runtime +```bash title="eth_sendRawTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_sendRawTransaction", + "params":["INSERT_CALL_DATA"], + "id":1 +}' +``` -The runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function. +Ensure to replace the `INSERT_CALL_DATA` with the proper values. -## Slot +--- -A fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block. +### eth_sendTransaction -## Sovereign Account +Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. -The unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem. +**Parameters**: -The sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier. +- **`transaction` ++"object"++**: The transaction object. + - **`from` ++"string"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`to` ++"string"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`data` ++"string"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`nonce` ++"string"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -## SS58 Address Format +**Example**: -A public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain +```bash title="eth_sendTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_sendTransaction", + "params":[{ + "from": "INSERT_SENDER_ADDRESS", + "to": "INSERT_RECIPIENT_ADDRESS", + "gas": "INSERT_GAS_LIMIT", + "gasPrice": "INSERT_GAS_PRICE", + "value": "INSERT_VALUE", + "input": "INSERT_INPUT_DATA", + "nonce": "INSERT_NONCE" + }], + "id":1 +}' +``` -The [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks +Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values. -## State Transition Function (STF) +--- -The logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime). +### eth_syncing -## Storage Item +Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. -[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime). -Learn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\_blank} reference document in the Polkadot SDK. +**Parameters**: -## Substrate +None. -A flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\_blank}. +**Example**: -## Transaction +```bash title="eth_syncing" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_syncing", + "params":[], + "id":1 +}' +``` -An [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}. +--- -## Transaction Era +### net_listening -A definable period expressed as a range of block numbers during which a transaction can be included in a block. -Transaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero. +Returns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\_blank}. -## Trie (Patricia Merkle Tree) +**Parameters**: -A data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set. +None. -In Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays. +**Example**: -## Validator - -A validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance. +```bash title="net_listening" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_listening", + "params":[], + "id":1 +}' +``` -## WebAssembly (Wasm) +--- -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. +### net_peerCount -[Wasm](https://webassembly.org/){target=\_blank} can be compiled from many languages, including -the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state. +Returns the number of peers currently connected to the client. -## Weight +**Parameters**: -A convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block. -Polkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware. +None. -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: +**Example**: -- Block construction -- Network propagation -- Import and verification +```bash title="net_peerCount" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_peerCount", + "params":[], + "id":1 +}' +``` -By defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements. +--- -## Westend +### net_version -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. +Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. +**Parameters**: ---- +None. -Page Title: Install Polkadot SDK +**Example**: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md -- Canonical (HTML): https://docs.polkadot.com/parachains/install-polkadot-sdk/ -- Summary: Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. +```bash title="net_version" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_version", + "params":[], + "id":1 +}' +``` -# Install Polkadot SDK +--- -This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts: +### system_health -- **Installing dependencies**: Setting up Rust, required system packages, and development tools. -- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. +Returns information about the health of the system. -Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. +**Parameters**: -## Install Dependencies: macOS +None. -You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. +**Example**: -### Before You Begin {: #before-you-begin-mac-os } +```bash title="system_health" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"system_health", + "params":[], + "id":1 +}' +``` -Before you install Rust and set up your development environment on macOS, verify that your computer meets the following basic requirements: +--- -- Operating system version is 10.7 Lion or later. -- Processor speed of at least 2 GHz. Note that 3 GHz is recommended. -- Memory of at least 8 GB RAM. Note that 16 GB is recommended. -- Storage of at least 10 GB of available space. -- Broadband Internet connection. +### web3_clientVersion -### Install Homebrew +Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. -In most cases, you should use Homebrew to install and manage packages on macOS computers. If you don't already have Homebrew installed on your local computer, you should download and install it before continuing. +**Parameters**: -To install Homebrew: +None. -1. Open the Terminal application. -2. Download and install Homebrew by running the following command: +**Example**: - ```bash - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - ``` +```bash title="web3_clientVersion" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"web3_clientVersion", + "params":[], + "id":1 +}' +``` -3. Verify Homebrew has been successfully installed by running the following command: +--- - ```bash - brew --version - ``` +### debug_traceBlockByNumber - The command displays output similar to the following: +Traces a block's execution by its number and returns a detailed execution trace for each transaction. -
    - brew --version - Homebrew 4.3.15 -
    +**Parameters**: -### Support for Apple Silicon +- **`blockValue` ++"string"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`options` ++"object"++**: (Optional) An object containing tracer options. + - **`tracer` ++"string"++**: The name of the tracer to use (e.g., `"callTracer"`, `"opTracer"`). + - Other tracer-specific options may be supported. -Protobuf must be installed before the build process can begin. To install it, run the following command: +**Example**: -```bash -brew install protobuf +```bash title="debug_traceBlockByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceBlockByNumber", + "params":["INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "id":1 +}' ``` -### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } +Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. -Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `openssl`. +--- -To install `openssl` and the Rust toolchain on macOS: +### debug_traceTransaction -1. Open the Terminal application. -2. Ensure you have an updated version of Homebrew by running the following command: +Traces the execution of a single transaction by its hash and returns a detailed execution trace. - ```bash - brew update - ``` +**Parameters**: -3. Install the `openssl` package by running the following command: +- **`transactionHash` ++"string"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). - ```bash - brew install openssl - ``` +**Example**: -4. Download the `rustup` installation program and use it to install Rust by running the following command: +```bash title="debug_traceTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceTransaction", + "params":["INSERT_TRANSACTION_HASH", {"tracer": "callTracer"}], + "id":1 +}' +``` - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. -5. Follow the prompts displayed to proceed with a default installation. -6. Update your current shell to include Cargo by running the following command: +--- - ```bash - source ~/.cargo/env - ``` +### debug_traceCall -7. Configure the Rust toolchain to default to the latest stable version by running the following commands: +Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` +**Parameters**: -8. Install `cmake` using the following command: +- **`transaction` ++"object"++**: The transaction call object, similar to `eth_call` parameters. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). - ```bash - brew install cmake - ``` +**Example**: -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). +```bash title="debug_traceCall" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceCall", + "params":[{ + "from": "INSERT_SENDER_ADDRESS", + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_CALL" + }, "INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "id":1 +}' +``` -## Install Dependencies: Linux +Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value. -Rust supports most Linux distributions. Depending on the specific distribution and version of the operating system you use, you might need to add some software dependencies to your environment. In general, your development environment should include a linker or a C-compatible compiler, such as `clang`, and an appropriate integrated development environment (IDE). +--- -### Before You Begin {: #before-you-begin-linux } +## Response Format -Check the documentation for your operating system for information about the installed packages and how to download and install any additional packages you might need. For example, if you use Ubuntu, you can use the Ubuntu Advanced Packaging Tool (`apt`) to install the `build-essential` package: +All responses follow the standard JSON-RPC 2.0 format: -```bash -sudo apt install build-essential +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": ... // The return value varies by method +} ``` -At a minimum, you need the following packages before you install Rust: +## Error Handling -```text -clang curl git make +If an error occurs, the response will include an error object: + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32000, + "message": "Error message here" + } +} ``` -Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `libssl-dev` or `openssl-devel`. -### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } +--- -To install the Rust toolchain on Linux: +Page Title: Mock Your Runtime -1. Open a terminal shell. -2. Check the packages installed on the local computer by running the appropriate package management command for your Linux distribution. -3. Add any package dependencies you are missing to your local development environment by running the appropriate package management command for your Linux distribution: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md +- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/ +- Summary: Learn how to create a mock runtime environment for testing your custom pallets in isolation, enabling comprehensive unit testing before runtime integration. - === "Ubuntu" - - ```bash - sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler - ``` +# Mock Your Runtime - === "Debian" +## Introduction - ```sh - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` +Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node. - === "Arch" +In this guide, you'll learn how to create a mock runtime for the custom counter pallet built in the [Make a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\_blank} guide. This mock runtime will enable you to write comprehensive unit tests that verify: - ```sh - pacman -Syu --needed --noconfirm curl git clang make protobuf - ``` +- Dispatchable function behavior. +- Storage state changes. +- Event emission. +- Error handling. +- Access control and origin validation. +- Genesis configuration. - === "Fedora" +## Prerequisites - ```sh - sudo dnf update - sudo dnf install clang curl git openssl-devel make protobuf-compiler - ``` +Before you begin, ensure you have: - === "OpenSUSE" +- Completed the [Make a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\_blank} guide. +- The custom counter pallet from the Make a Custom Pallet guide. Available in `pallets/pallet-custom`. +- Basic understanding of [Rust testing](https://doc.rust-lang.org/book/ch11-00-testing.html){target=\_blank}. - ```sh - sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf - ``` +## Understand Mock Runtimes - Remember that different distributions might use different package managers and bundle packages in different ways. For example, depending on your installation selections, Ubuntu Desktop and Ubuntu Server might have different packages and different requirements. However, the packages listed in the command-line examples are applicable to many common Linux distributions, including Debian, Linux Mint, MX Linux, and Elementary OS. +A mock runtime is a minimal implementation of the runtime environment that: -4. Download the `rustup` installation program and use it to install Rust by running the following command: +- Simulates blockchain state to provide storage and state management. +- Satisfies your pallet's `Config` trait requirements. +- Allows isolated testing without external dependencies. +- Supports genesis configuration to set initial blockchain state for tests. +- Provides instant feedback on code changes for a faster development cycle. - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` +Mock runtimes are used exclusively for testing and are never deployed to a live blockchain. -5. Follow the prompts displayed to proceed with a default installation. -6. Update your current shell to include Cargo by running the following command: +## Create the Mock Runtime Module - ```bash - source $HOME/.cargo/env - ``` +Start by creating a new module file within your pallet to house the mock runtime code. -7. Verify your installation by running the following command: +1. Navigate to your pallet directory: ```bash - rustc --version + cd pallets/pallet-custom/src ``` -8. Configure the Rust toolchain to default to the latest stable version by running the following commands: +2. Create a new file named `mock.rs`: ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src + touch mock.rs ``` -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). +3. Next, open `src/lib.rs` and add the mock module declaration at the top of the file, right after the `pub use pallet::*;` line: -## Install Dependencies: Windows (WSL) + ```rust title="src/lib.rs" + #![cfg_attr(not(feature = "std"), no_std)] -In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. + pub use pallet::*; -However, suppose your local computer uses Microsoft Windows instead of a UNIX-based operating system. In that case, you can configure it with additional software to make it a suitable development environment for building Substrate-based blockchains. To prepare a development environment on a Microsoft Windows computer, you can use Windows Subsystem for Linux (WSL) to emulate a UNIX operating environment. + #[cfg(test)] + mod mock; -### Before You Begin {: #before-you-begin-windows-wls } + #[frame::pallet] + pub mod pallet { + // ... existing pallet code + } -Before installing on Microsoft Windows, verify the following basic requirements: + ``` -- You have a computer running a supported Microsoft Windows operating system: - - **For Windows desktop**: You must be running Microsoft Windows 10, version 2004 or later, or Microsoft Windows 11 to install WSL. - - **For Windows server**: You must be running Microsoft Windows Server 2019, or later, to install WSL on a server operating system. -- You have a good internet connection and access to a shell terminal on your local computer. + The `#[cfg(test)]` attribute ensures this module is only compiled during testing. -### Set Up Windows Subsystem for Linux +## Set Up Basic Mock -WSL enables you to emulate a Linux environment on a computer that uses the Windows operating system. The primary advantage of this approach for Substrate development is that you can use all of the code and command-line examples as described in the Substrate documentation. For example, you can run common commands—such as `ls` and `ps`—unmodified. By using WSL, you can avoid configuring a virtual machine image or a dual-boot operating system. +Open `src/mock.rs` and add the foundational imports and type definitions: -To prepare a development environment using WSL: +```rust title="src/mock.rs" +use crate as pallet_custom; +use frame::{ + deps::{ + frame_support::{ derive_impl, traits::ConstU32 }, + sp_io, + sp_runtime::{ traits::IdentityLookup, BuildStorage }, + }, + prelude::*, +}; -1. Check your Windows version and build number to see if WSL is enabled by default. +type Block = frame_system::mocking::MockBlock; - If you have Microsoft Windows 10, version 2004 (Build 19041 and higher), or Microsoft Windows 11, WSL is available by default and you can continue to the next step. +// Configure a mock runtime to test the pallet. +frame::deps::frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + CustomPallet: pallet_custom, + } + ); +``` - If you have an older version of Microsoft Windows installed, see the [WSL manual installation steps for older versions](https://learn.microsoft.com/en-us/windows/wsl/install-manual){target=\_blank}. If you are installing on an older version of Microsoft Windows, you can download and install WLS 2 if your computer has Windows 10, version 1903 or higher. +The preceding code includes the following key components: -2. Select **Windows PowerShell** or **Command Prompt** from the **Start** menu, right-click, then **Run as administrator**. +- **[`construct_runtime!`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/apis/trait.ConstructRuntimeApi.html#tymethod.construct_runtime_api){target=\_blank}**: Macro that builds a minimal runtime with only the pallets needed for testing. +- **`Test`**: The mock runtime type used in tests. +- **`Block`**: Type alias for the mock block type that the runtime will use. -3. In the PowerShell or Command Prompt terminal, run the following command: +## Implement Essential Configuration - ```bash - wsl --install - ``` +The [`frame_system`](https://paritytech.github.io/polkadot-sdk/master/frame_system/index.html){target=\_blank} pallet provides core blockchain functionality and is required by all other pallets. Configure it for the test environment as follows: - This command enables the required WSL 2 components that are part of the Windows operating system, downloads the latest Linux kernel, and installs the Ubuntu Linux distribution by default. +```rust title="src/mock.rs" +#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] +impl frame_system::Config for Test { + type Block = Block; + type AccountId = u64; + type Lookup = IdentityLookup; +} +``` - If you want to review the other Linux distributions available, run the following command: +This simplified configuration for testing includes the following: - ```bash - wsl --list --online - ``` +- **`#[derive_impl]`**: Automatically provides sensible test defaults for most `frame_system::Config` types. +- **`AccountId = u64`**: Uses simple integers instead of cryptographic account IDs. +- **`Lookup = IdentityLookup`**: Direct account ID mapping (no address conversion). +- **`Block = Block`**: Uses the mock block type we defined earlier. -4. After the distribution is downloaded, close the terminal. +This approach is much more concise than manually specifying every configuration type, as the `TestDefaultConfig` preset provides appropriate defaults for testing. -5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. +## Implement Your Pallet's Configuration - Restarting the computer is required to start the installation of the Linux distribution. It can take a few minutes for the installation to complete after you restart. +Now implement the `Config` trait for your custom pallet. This trait must match the one defined in your pallet's `src/lib.rs`: - For more information about setting up WSL as a development environment, see the [Set up a WSL development environment](https://learn.microsoft.com/en-us/windows/wsl/setup/environment){target=\_blank} docs. +```rust title="src/mock.rs" +impl pallet_custom::Config for Test { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; +} +``` -### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } +Configuration details include: -To install the Rust toolchain on WSL: +- **`RuntimeEvent`**: Connects your pallet's events to the mock runtime's event system. +- **`CounterMaxValue`**: Sets the maximum counter value to 1000, matching the production configuration. -1. Click the **Start** menu, then select **Ubuntu**. -2. Type a UNIX user name to create a user account. -3. Type a password for your UNIX user, then retype the password to confirm it. -4. Download the latest updates for the Ubuntu distribution using the Ubuntu Advanced Packaging Tool (`apt`) by running the following command: +The configuration here should mirror what you'll use in production unless you specifically need different values for testing. - ```bash - sudo apt update - ``` +## Configure Genesis Storage -5. Add the required packages for the Ubuntu distribution by running the following command: +Genesis storage defines the initial state of your blockchain before any blocks are produced. Since your counter pallet includes the genesis configuration (added in the previous guide), you can now set up test environments with different initial states. - ```bash - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` +### Basic Test Environment -6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: +Create a helper function for the default test environment: - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` +```rust title="src/mock.rs" +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); -7. Follow the prompts displayed to proceed with a default installation. + (pallet_custom::GenesisConfig:: { + initial_counter_value: 0, + initial_user_interactions: vec![], + }) + .assimilate_storage(&mut t) + .unwrap(); -8. Update your current shell to include Cargo by running the following command: + t.into() +} +``` - ```bash - source ~/.cargo/env - ``` +This function creates a clean blockchain state with an initial counter value of 0 and no user interactions. -9. Verify your installation by running the following command: +### Custom Genesis Configurations - ```bash - rustc --version - ``` +For testing specific scenarios, create additional helper functions with customized genesis states: -10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: +```rust title="src/mock.rs" +// Helper function to create a test externalities with a specific initial counter value +pub fn new_test_ext_with_counter(initial_value: u32) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` + (pallet_custom::GenesisConfig:: { + initial_counter_value: initial_value, + initial_user_interactions: vec![], + }) + .assimilate_storage(&mut t) + .unwrap(); -11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). + t.into() +} -## Build the Polkadot SDK +// Helper function to create a test externalities with initial user interactions +pub fn new_test_ext_with_interactions( + initial_value: u32, + interactions: Vec<(u64, u32)> +) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); -After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. + (pallet_custom::GenesisConfig:: { + initial_counter_value: initial_value, + initial_user_interactions: interactions, + }) + .assimilate_storage(&mut t) + .unwrap(); -### Clone the Polkadot SDK + t.into() +} +``` -1. Clone the Polkadot SDK repository: +Key methods used in this step include: - ```bash - git clone https://github.com/paritytech/polkadot-sdk.git - ``` +- **[`BuildStorage::build_storage()`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/trait.BuildStorage.html#method.build_storage){target=\_blank}**: Creates the initial storage state. +- **[`assimilate_storage`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/trait.BuildStorage.html#method.assimilate_storage){target=\_blank}**: Merges pallet genesis config into the existing storage. -2. Navigate into the project directory: +You can chain multiple `assimilate_storage` calls to configure multiple pallets. - ```bash - cd polkadot-sdk - ``` - -### Compile the Polkadot SDK - -Compile the entire Polkadot SDK repository to ensure your environment is properly configured: - -```bash -cargo build --release --locked -``` - -!!!note - This initial compilation will take significant time, depending on your machine specifications. It compiles all components of the Polkadot SDK to verify your toolchain is correctly configured. - -### Verify the Build - -Once the build completes successfully, verify the installation by checking the compiled binaries: - -```bash -ls target/release -``` - -You should see several binaries, including: - -- `polkadot`: The Polkadot relay chain node. -- `polkadot-parachain`: The parachain collator node. -- `polkadot-omni-node`:The omni node for running parachains. -- `substrate-node`: The kitchensink node with many pre-configured pallets. +## Verify Mock Compilation -Verify the Polkadot binary works by checking its version: +Before proceeding to write tests, ensure your mock runtime compiles correctly: ```bash -./target/release/polkadot --version +cargo test --package pallet-custom --lib ``` -This should display version information similar to: +This command compiles the test code (including the mock and genesis configuration) without running tests yet. Address any compilation errors before continuing. -```bash -polkadot 1.16.0-1234abcd567 -``` +??? code "Complete mock runtime script" -If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! + Here's the complete `mock.rs` file for reference: -## Optional: Run the Kitchensink Node + ```rust title="src/mock.rs" + use crate as pallet_custom; + use frame::{ + deps::{ + frame_support::{ derive_impl, traits::ConstU32 }, + sp_io, + sp_runtime::{ traits::IdentityLookup, BuildStorage }, + }, + prelude::*, + }; -The Polkadot SDK includes a feature-rich node called "kitchensink" located at `substrate/bin/node`. This node comes pre-configured with many pallets and features from the Polkadot SDK, making it an excellent reference for exploring capabilities and understanding how different components work together. + type Block = frame_system::mocking::MockBlock; -!!!note - If you've already compiled the Polkadot SDK in the previous step, the `substrate-node` binary is already built and ready to use. You can skip directly to running the node. + // Configure a mock runtime to test the pallet. + frame::deps::frame_support::construct_runtime!( + pub enum Test + { + System: frame_system, + CustomPallet: pallet_custom, + } + ); -### Run the Kitchensink Node in Development Mode + #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] + impl frame_system::Config for Test { + type Block = Block; + type AccountId = u64; + type Lookup = IdentityLookup; + } -From the `polkadot-sdk` root directory, start the kitchensink node in development mode: + impl pallet_custom::Config for Test { + type RuntimeEvent = RuntimeEvent; + type CounterMaxValue = ConstU32<1000>; + } -```bash -./target/release/substrate-node --dev -``` + // Build genesis storage according to the mock runtime. + pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); -The `--dev` flag enables development mode, which: + (pallet_custom::GenesisConfig:: { + initial_counter_value: 0, + initial_user_interactions: vec![], + }) + .assimilate_storage(&mut t) + .unwrap(); -- Runs a single-node development chain. -- Produces and finalizes blocks automatically. -- Uses pre-configured development accounts (Alice, Bob, etc.). -- Deletes all data when stopped, ensuring a clean state on restart. + t.into() + } + // Helper function to create a test externalities with a specific initial counter value + pub fn new_test_ext_with_counter(initial_value: u32) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); -You should see log output indicating the node is running and producing blocks, with increasing block numbers after `finalized`. + (pallet_custom::GenesisConfig:: { + initial_counter_value: initial_value, + initial_user_interactions: vec![], + }) + .assimilate_storage(&mut t) + .unwrap(); -### Interact with the Kitchensink Node + t.into() + } -The kitchensink node is accessible at `ws://localhost:9944`. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your browser to explore its features and connect to the local node. + // Helper function to create a test externalities with initial user interactions + pub fn new_test_ext_with_interactions( + initial_value: u32, + interactions: Vec<(u64, u32)> + ) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); -1. Click the network icon in the top left corner. -2. Scroll to **Development** and select **Local Node**. -3. Click **Switch** to connect to your local node. + (pallet_custom::GenesisConfig:: { + initial_counter_value: initial_value, + initial_user_interactions: interactions, + }) + .assimilate_storage(&mut t) + .unwrap(); -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) + t.into() + } + ``` -Once connected, the interface updates its color scheme to indicate a successful connection to the local node. +## Key Takeaways -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) +You've successfully created a mock runtime with a genesis configuration for your custom pallet. You can now: -You can now explore the various pallets and features included in the kitchensink node, making it a valuable reference as you develop your own blockchain applications. +- Test your pallet without a full runtime. +- Set initial blockchain state for different test scenarios. +- Create different genesis setups for various testing needs. +- Use this minimal setup to test all pallet functionality. -To stop the node, press `Control-C` in the terminal. +The mock runtime with a genesis configuration is essential for test-driven development, enabling you to verify logic under different initial conditions before integrating it into the actual parachain runtime. ## Where to Go Next
    -- __Get Started with Parachain Development__ +- Guide __Pallet Unit Testing__ --- - Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. + Learn to write comprehensive unit tests for your pallet using the mock runtime you just created. + + [:octicons-arrow-right-24: Continue](/parachains/customize-runtime/pallet-development/pallet-testing/) - [:octicons-arrow-right-24: Get Started](/parachains/get-started/) -
    --- -Page Title: Interoperability +Page Title: Obtain Coretime -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/interoperability/ -- Summary: Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md +- Canonical (HTML): https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/ +- Summary: Learn how to obtain coretime for block production with this guide, covering both on-demand and bulk options for smooth operations. -# Interoperability +# Obtain Coretime ## Introduction -Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions. +After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime. -Polkadot’s design ensures that blockchains can transcend their individual limitations by working together as part of a unified system. This cooperative architecture is what sets Polkadot apart in the blockchain landscape. +There are two primary ways to obtain coretime: -## Why Interoperability Matters +- **[On-demand coretime](#order-on-demand-coretime)**: Purchase coretime on a block-by-block basis, ideal for variable or unpredictable workloads. +- **[Bulk coretime](#purchase-bulk-coretime)**: Obtain a core or portion of a core for an extended period (up to 28 days), requiring renewal upon lease expiration. -The blockchain ecosystem is inherently fragmented. Different blockchains excel in specialized domains such as finance, gaming, or supply chain management, but these chains function in isolation without interoperability. This lack of connectivity stifles the broader utility of blockchain technology. +In this tutorial, you will: -Interoperability solves this problem by enabling blockchains to: +- Understand the different coretime options available. +- Learn how to purchase a core via bulk coretime. +- Assign your parachain to a core for block production. +- Explore on-demand coretime as an alternative approach. -- **Collaborate across networks**: Chains can interact to share assets, functionality, and data, creating synergies that amplify their individual strengths. -- **Achieve greater scalability**: Specialized chains can offload tasks to others, optimizing performance and resource utilization. -- **Expand use-case potential**: Cross-chain applications can leverage features from multiple blockchains, unlocking novel user experiences and solutions. +## Prerequisites -In the Polkadot ecosystem, interoperability transforms a collection of isolated chains into a cohesive, efficient network, pushing the boundaries of what blockchains can achieve together. +Before proceeding, ensure you have the following: -## Key Mechanisms for Interoperability +- A parachain ID reserved on Paseo. +- A properly configured chain specification file (both plain and raw versions). +- A registered parathread with the correct genesis state and runtime. +- A synced collator node running and connected to the Paseo relay chain. +- [PAS tokens](https://faucet.polkadot.io/?parachain=1005){target=\_blank} in your account on the Coretime Chain for transaction fees. -At the core of Polkadot's cross-chain collaboration are foundational technologies designed to break down barriers between networks. These mechanisms empower blockchains to communicate, share resources, and operate as a cohesive ecosystem. +If you haven't completed these prerequisites, start by referring to the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\_blank} tutorial. -### Cross-Consensus Messaging (XCM): The Backbone of Communication +## Order On-Demand Coretime -Polkadot's Cross-Consensus Messaging (XCM) is the standard framework for interaction between parachains, relay chains, and, eventually, external blockchains. XCM provides a trustless, secure messaging format for exchanging assets, sharing data, and executing cross-chain operations. +On-demand coretime allows you to purchase validation resources on a per-block basis. This approach is useful when you don't need continuous block production or want to test your parachain before committing to bulk coretime. -Through XCM, decentralized applications can: +### On-Demand Extrinsics -- Transfer tokens and other assets across chains. -- Coordinate complex workflows that span multiple blockchains. -- Enable seamless user experiences where underlying blockchain differences are invisible. -- XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem. +There are two extrinsics available for ordering on-demand coretime: -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. +- **[`onDemand.placeOrderAllowDeath`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/on_demand/pallet/struct.Pallet.html#method.place_order_allow_death){target=\_blank}**: Will [reap](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank} the account once the provided funds are depleted. +- **[`onDemand.placeOrderKeepAlive`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/on_demand/pallet/struct.Pallet.html#method.place_order_keep_alive){target=\_blank}**: Includes a check to prevent reaping the account, ensuring it remains alive even if funds run out. -### Bridges: Connecting External Networks +### Place an On-Demand Order -While XCM enables interoperability within the Polkadot ecosystem, bridges extend this functionality to external blockchains such as Ethereum and Bitcoin. By connecting these networks, bridges allow Polkadot-based chains to access external liquidity, additional functionalities, and broader user bases. +To place an on-demand coretime order, follow these steps: -With bridges, developers and users gain the ability to: +1. Open the [Polkadot.js Apps interface connected to the Polkadot TestNet (Paseo)](https://polkadot.js.org/apps/?rpc=wss://paseo.dotters.network){target=\_blank}. -- Integrate external assets into Polkadot-based applications. -- Combine the strengths of Polkadot’s scalability with the liquidity of other networks. -- Facilitate accurate multi-chain applications that transcend ecosystem boundaries. +2. Navigate to **Developer > Extrinsics** in the top menu. -For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. +3. Select the account that registered your parachain ID. -## The Polkadot Advantage +4. From the **submit the following extrinsic** dropdown, select **onDemand** and then choose **placeOrderAllowDeath** as the extrinsic. -Polkadot was purpose-built for interoperability. Unlike networks that add interoperability as an afterthought, Polkadot integrates it as a fundamental design principle. This approach offers several distinct advantages: +5. Configure the parameters: -- **Developer empowerment**: Polkadot’s interoperability tools allow developers to build applications that leverage multiple chains’ capabilities without added complexity. -- **Enhanced ecosystem collaboration**: Chains in Polkadot can focus on their unique strengths while contributing to the ecosystem’s overall growth. -- **Future-proofing blockchain**: By enabling seamless communication, Polkadot ensures its ecosystem can adapt to evolving demands and technologies. + - **maxAmount**: The maximum amount of tokens you're willing to spend (e.g., `1000000000000`). This value may vary depending on network conditions. + - **paraId**: Your reserved parachain ID (e.g., `4508`). -## Looking Ahead +6. Review the transaction details and click **Submit Transaction**. -Polkadot’s vision of interoperability extends beyond technical functionality, representing a shift towards a more collaborative blockchain landscape. By enabling chains to work together, Polkadot fosters innovation, efficiency, and accessibility, paving the way for a decentralized future where blockchains are not isolated competitors but interconnected collaborators. +![Placing an on-demand order for coretime](/images/parachains/launch-a-parachain/obtain-coretime/obtain-coretime-01.webp) +Upon successful submission, your parachain will produce a new block. You can verify this by checking your collator node logs, which should display output confirming block production. ---- +!!!note + Each successful on-demand extrinsic will trigger one block production cycle. For continuous block production, you'll need to place multiple orders or consider bulk coretime. -Page Title: Introduction to XCM +## Purchase Bulk Coretime -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ -- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. +Bulk coretime offers a cost-effective way to maintain continuous block production. It lets you reserve a core for up to 28 days and renew it as needed. -# Introduction to XCM +You can purchase and manage cores on the [Coretime Chain](https://wiki.polkadot.com/learn/learn-system-chains/#coretime-chain){target=\_blank}, a system parachain that runs the [`pallet_broker`](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank} to handle core sales, allocation, and renewal across the Polkadot ecosystem. -## Introduction +!!!tip + Paseo has a unique process for obtaining coretime cores. Refer to the [PAS-10 Onboard Paras Coretime](https://github.com/paseo-network/paseo-action-submission/blob/main/pas/PAS-10-Onboard-paras-coretime.md#summary){target=\_blank} guide for detailed instructions. -Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. +This tutorial shows you how to purchase bulk coretime using the [RegionX Coretime Marketplace](https://app.regionx.tech){target=\_blank}, a user-friendly interface for buying and managing cores on both the Polkadot TestNet and production networks. -With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. +![RegionX home page with Wallet connected](/images/parachains/launch-a-parachain/obtain-coretime/obtain-coretime-02.webp) -## Messaging Format +### Connect Your Wallet to RegionX -XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. +1. Visit the [RegionX App](https://app.regionx.tech){target=\_blank}. -XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. +2. Click the **Connect Wallet** button in the upper right corner. -## The Four Principles of XCM +3. Select your wallet provider and approve the connection. -XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: +### Obtain Coretime Chain Funds -- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. -- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. -- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. -- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. +To purchase a core, you need funds on the Coretime Chain. You can fund your account directly on the Coretime Chain using the Polkadot Faucet: -These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. +1. Visit the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=0){target=\_blank}. -## The XCM Tech Stack +2. Select the **Coretime (Paseo)** network from the dropdown menu. -![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) +3. Paste your wallet address in the input field. -The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. +4. Click **Get some PASs** to receive 5000 PAS tokens. -## Core Functionalities of XCM +!!!note + The Polkadot Faucet has a daily limit of 5,000 PAS tokens per account. If you need more tokens than this limit allows, you have two options: + + - Return to the faucet on consecutive days to accumulate additional tokens. + - Create additional accounts, fund each one separately, and then transfer the tokens to your primary account that will be making the bulk coretime purchase. -XCM enhances cross-consensus communication by introducing several powerful features: + Alternatively, to expedite the process, you can send a message to the [Paseo Support channel](https://matrix.to/#/#paseo-testnet-support:parity.io){target=\_blank} on Matrix, and the Paseo team will assist you in funding your account. -- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. -- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. -- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. +### Purchase a Core -The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. +1. From the RegionX home page, ensure the correct network is selected using the network switch in the top right corner (set to **Paseo**). -## XCM Example +2. Review the information displayed on the home page, including: + - **Cores Remaining**: Number of available cores + - **Cores Offered**: Total cores in the current sale + - **Current price**: The price per core in PAS tokens + - **Auction Phase Status**: Current phase and progress -The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). +3. Click the **Purchase New Core** button displayed on the page. -```rust -let message = Xcm(vec![ - WithdrawAsset((Here, amount).into()), - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } -]); -``` +4. A modal will appear detailing the transaction details and fees. Review the information carefully. -The message consists of three instructions described as follows: +5. Click **Ok** and sign the transaction using your connected wallet. -- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. +6. Wait for the transaction to be confirmed on-chain. - ```rust - WithdrawAsset((Here, amount).into()), - ``` +### Verify Your Purchase - - **`Here`**: The native parachain token. - - **`amount`**: The number of tokens that are transferred. +1. Once the transaction is confirmed, navigate to [**My Regions**](https://app.regionx.tech/regions){target=\_blank} from the left menu. - The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. +2. You should see your newly purchased core listed in your dashboard. -- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. +Congratulations! You've successfully purchased a core using RegionX. - ```rust - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - ``` +### Assign Your Parachain to the Core - - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. - - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. +With your core purchased, you now need to assign your parachain to it for block production: -- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. +1. From the **My Regions** page, click on your core to select it. - ```rust - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } - ``` +2. Click the **Assign** option from the left-hand menu. - - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. - -This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. +3. A modal will appear, allowing you to add a new task. -## Overview +4. Click **Add Task** and enter the following information: -XCM revolutionizes cross-chain communication by enabling use cases such as: + - **Parachain ID**: Your reserved parachain identifier + - **Project Name**: The name of your parachain project -- Token transfers between blockchains. -- Asset locking for cross-chain smart contract interactions. -- Remote execution of functions on other blockchains. +5. Click **Add Task** to proceed. -These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. +6. Select your parachain task from the list. +7. Set the core's **Finality** setting: ---- + - **Provisional**: Allows interlacing and partitioning of the core, but the region cannot be renewed as-is. + - **Final**: Prevents modification of the core but allows renewal. Choose this if you plan to renew the core. -Page Title: JSON-RPC APIs +8. Sign and submit the transaction. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ -- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. +Once confirmed, your parachain will be assigned to the core and should begin producing blocks (provided your collator is running and synced with the relay chain). -# JSON-RPC APIs +## Next Steps -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction +Your parachain is now set up for block production. Consider the following: -Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. +- **Monitor your collator**: Keep your collator node running and monitor its performance. +- **Plan coretime renewal**: If using bulk coretime, plan to renew your core before the current lease expires. +- **Explore runtime upgrades**: Once comfortable with your setup, explore how to upgrade your parachain's runtime without interrupting block production. -This guide uses the Polkadot Hub TestNet endpoint: -```text -https://testnet-passet-hub-eth-rpc.polkadot.io -``` +--- -## Available Methods +Page Title: Opening HRMP Channels Between Parachains -### eth_accounts +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md +- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/ +- Summary: Learn how to open HRMP channels between parachains on Polkadot. Discover the step-by-step process for establishing uni- and bidirectional communication. -Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. +# Opening HRMP Channels Between Parachains -**Parameters**: +## Introduction -None. +For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required: -**Example**: +1. **Channel request**: The parachain that wants to open an HRMP channel must make a request to the parachain it wishes to have an open channel with. +2. **Channel acceptance**: The other parachain must then accept this request to complete the channel establishment. -```bash title="eth_accounts" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_accounts", - "params":[], - "id":1 -}' -``` +This process results in a unidirectional HRMP channel, where messages can flow in only one direction between the two parachains. ---- +An additional HRMP channel must be established in the opposite direction to enable bidirectional communication. This requires repeating the request and acceptance process but with the parachains reversing their roles. -### eth_blockNumber +Once both unidirectional channels are established, the parachains can send messages back and forth freely through the bidirectional HRMP communication channel. -Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. +## Prerequisites -**Parameters**: +Before proceeding, ensure you meet the following requirements: -None. +- Blockchain network with a relay chain and at least two connected parachains. +- Wallet with sufficient funds to execute transactions on the participant chains. -**Example**: +## Procedure to Initiate an HRMP Channel -```bash title="eth_blockNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_blockNumber", - "params":[], - "id":1 -}' -``` +This example will demonstrate how to open a channel between parachain 2500 and parachain 2600, using Rococo Local as the relay chain. ---- +### Fund Sender Sovereign Account -### eth_call -Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. +The [sovereign account](https://github.com/polkadot-fellows/xcm-format/blob/10726875bd3016c5e528c85ed6e82415e4b847d7/README.md?plain=1#L50){target=_blank} for parachain 2500 on the relay chain must be funded so it can take care of any XCM transact fees. -**Parameters**: +Use [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} UI to connect to the relay chain and transfer funds from your account to the parachain 2500 sovereign account. -- **`transaction` ++"object"++**: The transaction call object. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +![](/images/parachains/interoperability/channels-common/channels-01.webp) -**Example**: +??? note "Calculating Parachain Sovereign Account" + To generate the sovereign account address for a parachain, you'll need to follow these steps: -```bash title="eth_call" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_call", - "params":[{ - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_CALL" - }, "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` + 1. Determine if the parachain is an "up/down" chain (parent or child) or a "sibling" chain: -Ensure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values. + - Up/down chains use the prefix `0x70617261` (which decodes to `b"para"`). + - Sibling chains use the prefix `0x7369626c` (which decodes to `b"sibl"`). ---- + 2. Calculate the u32 scale encoded value of the parachain ID: -### eth_chainId + - Parachain 2500 would be encoded as `c4090000`. -Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}. + 3. Combine the prefix and parachain ID encoding to form the full sovereign account address: -**Parameters**: + The sovereign account of parachain 2500 in relay chain will be `0x70617261c4090000000000000000000000000000000000000000000000000000` + and the SS58 format of this address is `5Ec4AhPSY2GEE4VoHUVheqv5wwq2C1HMKa7c9fVJ1WKivX1Y`. + + To perform this conversion, you can also use the **"Para ID" to Address** section in [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/){target=_blank}. -None. +### Create Channel Opening Extrinsic -**Example**: +1. In Polkadot.js Apps, connect to the relay chain, navigate to the **Developer** dropdown and select the **Extrinsics** option. -```bash title="eth_chainId" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_chainId", - "params":[], - "id":1 -}' -``` + ![](/images/parachains/interoperability/channels-common/channels-02.webp) ---- +2. Construct an `hrmpInitOpenChannel` extrinsic call: -### eth_estimateGas + 1. Select the **`hrmp`** pallet. + 2. Choose the **`hrmpInitOpenChannel`** extrinsic. + 3. Fill in the parameters: + - **`recipient`**: Parachain ID of the target chain (in this case, 2600). + - **`proposedMaxCapacity`**: Max number of messages that can be pending in the channel at once. + - **`proposedMaxMessageSize`**: Max message size that could be put into the channel. + 4. Copy the encoded call data. -Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}. + ![](/images/parachains/interoperability/channels-between-parachains/parachains-01.webp) -**Parameters**: + The encoded call data for opening a channel with parachain 2600 is `0x3c00280a00000800000000001000`. -- **`transaction` ++"object"++**: The transaction call object. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +### Craft and Submit the XCM Message from the Sender -**Example**: +To initiate the HRMP channel opening process, you need to create an XCM message that includes the encoded `hrmpInitOpenChannel` call data from the previous step. This message will be sent from your parachain to the relay chain. -```bash title="eth_estimateGas" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_estimateGas", - "params":[{ - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_FUNCTION_CALL" - }], - "id":1 -}' -``` +This example uses the `sudo` pallet to dispatch the extrinsic. Verify the XCM configuration of the parachain you're working with and ensure you're using an origin with the necessary privileges to execute the `polkadotXcm.send` extrinsic. -Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. +The XCM message should contain the following instructions: ---- +- **`WithdrawAsset`**: Withdraws assets from the origin's ownership and places them in the Holding Register. +- **`BuyExecution`**: Pays for the execution of the current message using the assets in the Holding Register. +- **`Transact`**: Execute the encoded transaction call. +- **`RefundSurplus`**: Increases the Refunded Weight Register to the value of the Surplus Weight Register, attempting to reclaim any excess fees paid via BuyExecution. +- **`DepositAsset`**: Subtracts assets from the Holding Register and deposits equivalent on-chain assets under the specified beneficiary's ownership. -### eth_gasPrice +!!!note + For more detailed information about XCM's functionality, complexities, and instruction set, refer to the [xcm-format](https://github.com/polkadot-fellows/xcm-format){target=_blank} documentation. -Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. +In essence, this process withdraws funds from the parachain's sovereign account to the XCVM Holding Register, then uses these funds to purchase execution time for the XCM `Transact` instruction, executes `Transact`, refunds any unused execution time and deposits any remaining funds into a specified account. -**Parameters**: +To send the XCM message to the relay chain, connect to parachain 2500 in Polkadot.js Apps. Fill in the required parameters as shown in the image below, ensuring that you: -None. +1. Replace the **`call`** field with your encoded `hrmpInitOpenChannel` call data from the previous step. +2. Use the correct beneficiary information. +3. Click the **Submit Transaction** button to dispatch the XCM message to the relay chain. -**Example**: +![](/images/parachains/interoperability/channels-between-parachains/parachains-02.webp) -```bash title="eth_gasPrice" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_gasPrice", - "params":[], - "id":1 -}' -``` +!!! note + The exact process and parameters for submitting this XCM message may vary depending on your specific parachain and relay chain configurations. Always refer to the most current documentation for your particular network setup. ---- +After submitting the XCM message to initiate the HRMP channel opening, you should verify that the request was successful. Follow these steps to check the status of your channel request: -### eth_getBalance +1. Using Polkadot.js Apps, connect to the relay chain and navigate to the **Developer** dropdown, then select the **Chain state** option. -Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. + ![](/images/parachains/interoperability/channels-common/channels-03.webp) -**Parameters**: +2. Query the HRMP open channel requests: -- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + 1. Select **`hrmp`**. + 2. Choose the **`hrmpOpenChannelRequests`** call. + 3. Click the **+** button to execute the query. + 4. Check the status of all pending channel requests. -**Example**: + ![](/images/parachains/interoperability/channels-between-parachains/parachains-03.webp) -```bash title="eth_getBalance" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBalance", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` +If your channel request was successful, you should see an entry for your parachain ID in the list of open channel requests. This confirms that your request has been properly registered on the relay chain and is awaiting acceptance by the target parachain. -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. +## Procedure to Accept an HRMP Channel ---- +For the channel to be fully established, the target parachain must accept the channel request by submitting an XCM message to the relay chain. -### eth_getBlockByHash +### Fund Receiver Sovereign Account -Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. +Before proceeding, ensure that the sovereign account of parachain 2600 on the relay chain is funded. This account will be responsible for covering any XCM transact fees. +To fund the account, follow the same process described in the previous section, [Fund Sovereign Account](#fund-sender-sovereign-account). -**Parameters**: +### Create Channel Accepting Extrinsic -- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. +1. In Polkadot.js Apps, connect to the relay chain, navigate to the **Developer** dropdown and select the **Extrinsics** option. -**Example**: + ![](/images/parachains/interoperability/channels-common/channels-02.webp) -```bash title="eth_getBlockByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockByHash", - "params":["INSERT_BLOCK_HASH", INSERT_BOOLEAN], - "id":1 -}' -``` +2. Construct an `hrmpAcceptOpenChannel` extrinsic call: -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values. + 1. Select the **`hrmp`** pallet. + 2. Choose the **`hrmpAcceptOpenChannel`** extrinsic. + 3. Fill in the parameters: + - **`sender`**: Parachain ID of the requesting chain (in this case, 2500). + 4. Copy the encoded call data. ---- + ![](/images/parachains/interoperability/channels-between-parachains/parachains-04.webp) + + The encoded call data for accepting a channel with parachain 2500 should be `0x3c01c4090000`. -### eth_getBlockByNumber +### Craft and Submit the XCM Message from the Receiver -Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. +To accept the HRMP channel opening, you need to create and submit an XCM message that includes the encoded `hrmpAcceptOpenChannel` call data from the previous step. This process is similar to the one described in the previous section, [Craft and Submit the XCM Message](#craft-and-submit-the-xcm-message-from-the-sender), with a few key differences: -**Parameters**: +- Use the encoded call data for `hrmpAcceptOpenChannel` obtained in step 2 of this section. +- In the last XCM instruction (DepositAsset), set the beneficiary to parachain 2600's sovereign account to receive any surplus funds. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. +To send the XCM message to the relay chain, connect to parachain 2600 in Polkadot.js Apps. Fill in the required parameters as shown in the image below, ensuring that you: -**Example**: +1. Replace the **`call`** field with your encoded `hrmpAcceptOpenChannel` call data from the previous step. +2. Use the correct beneficiary information. +3. Click the **Submit Transaction** button to dispatch the XCM message to the relay chain. -```bash title="eth_getBlockByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockByNumber", - "params":["INSERT_BLOCK_VALUE", INSERT_BOOLEAN], - "id":1 -}' -``` +![](/images/parachains/interoperability/channels-between-parachains/parachains-05.webp) -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values. +After submitting the XCM message to accept the HRMP channel opening, verify that the channel has been set up correctly. ---- +1. Using Polkadot.js Apps, connect to the relay chain and navigate to the **Developer** dropdown, then select the **Chain state** option. -### eth_getBlockTransactionCountByNumber + ![](/images/parachains/interoperability/channels-common/channels-01.webp) -Returns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\_blank}. +2. Query the HRMP channels: -**Parameters**: + 1. Select **`hrmp`**. + 2. Choose the **`hrmpChannels`** call. + 3. Click the **+** button to execute the query. + 4. Check the status of the opened channel. -- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + ![](/images/parachains/interoperability/channels-between-parachains/parachains-06.webp) -**Example**: +If the channel has been successfully established, you should see the channel details in the query results. -```bash title="eth_getBlockTransactionCountByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockTransactionCountByNumber", - "params":["INSERT_BLOCK_VALUE"], - "id":1 -}' -``` +By following these steps, you will have successfully accepted the HRMP channel request and established a unidirectional channel between the two parachains. + +!!! note + Remember that for full bidirectional communication, you'll need to repeat this process in the opposite direction, with parachain 2600 initiating a channel request to parachain 2500. -Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. --- -### eth_getBlockTransactionCountByHash +Page Title: Opening HRMP Channels with System Parachains -Returns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md +- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/ +- Summary: Learn how to open HRMP channels with Polkadot system parachains. Discover the process for establishing bi-directional communication using a single XCM message. -**Parameters**: +# Opening HRMP Channels with System Parachains -- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +## Introduction -**Example**: +While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach. -```bash title="eth_getBlockTransactionCountByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockTransactionCountByHash", - "params":["INSERT_BLOCK_HASH"], - "id":1 -}' -``` +System parachains are specialized chains that provide core functionality to the Polkadot network. Examples include Asset Hub for cross-chain asset transfers and Bridge Hub for connecting to external networks. Given their critical role, establishing communication channels with these system parachains has been optimized for efficiency and ease of use. -Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. +Any parachain can establish a bidirectional channel with a system chain through a single operation, requiring just one XCM message from the parachain to the relay chain. ---- +## Prerequisites -### eth_getCode +To successfully complete this process, you'll need to have the following in place: -Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. +- Access to a blockchain network consisting of: + - A relay chain + - A parachain + - An Asset Hub system chain +- A wallet containing enough funds to cover transaction fees on each of the participating chains. -**Parameters**: +## Procedure to Establish an HRMP Channel -- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). +This guide demonstrates opening an HRMP channel between parachain 2500 and system chain Asset Hub (parachain 1000) on the Rococo Local relay chain. -**Example**: +### Fund Parachain Sovereign Account -```bash title="eth_getCode" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getCode", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` +The [sovereign account](https://github.com/polkadot-fellows/xcm-format/blob/10726875bd3016c5e528c85ed6e82415e4b847d7/README.md?plain=1#L50){target=_blank} for parachain 2500 on the relay chain must be funded so it can take care of any XCM transact fees. -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. +Use [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} UI to connect to the relay chain and transfer funds from your account to the parachain 2500 sovereign account. ---- +![](/images/parachains/interoperability/channels-common/channels-01.webp) -### eth_getLogs +??? note "Calculating Parachain Sovereign Account" + To generate the sovereign account address for a parachain, you'll need to follow these steps: -Returns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}. + 1. Determine if the parachain is an "up/down" chain (parent or child) or a "sibling" chain: -**Parameters**: + - Up/down chains use the prefix `0x70617261` (which decodes to `b"para"`). + - Sibling chains use the prefix `0x7369626c` (which decodes to `b"sibl"`). -- **`filter` ++"object"++**: The filter object. - - **`fromBlock` ++"string"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - - **`toBlock` ++"string"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - - **`address` ++"string" or "array of strings"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`topics` ++"array of strings"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string or an array of such strings (meaning OR). - - **`blockhash` ++"string"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + 2. Calculate the u32 scale encoded value of the parachain ID: -**Example**: + - Parachain 2500 would be encoded as `c4090000`. -```bash title="eth_getLogs" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getLogs", - "params":[{ - "fromBlock": "latest", - "toBlock": "latest" - }], - "id":1 -}' -``` + 3. Combine the prefix and parachain ID encoding to form the full sovereign account address: ---- + The sovereign account of parachain 2500 in relay chain will be `0x70617261c4090000000000000000000000000000000000000000000000000000` + and the SS58 format of this address is `5Ec4AhPSY2GEE4VoHUVheqv5wwq2C1HMKa7c9fVJ1WKivX1Y`. + + To perform this conversion, you can also use the **"Para ID" to Address** section in [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/){target=\_blank}. -### eth_getStorageAt +### Create Establish Channel with System Extrinsic -Returns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}. +1. In Polkadot.js Apps, connect to the relay chain, navigate to the **Developer** dropdown and select the **Extrinsics** option. -**Parameters**: + ![](/images/parachains/interoperability/channels-common/channels-02.webp) -- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`storageKey` ++"string"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). +2. Construct an `establish_channel_with_system` extrinsic call: -**Example**: + 1. Select the **`hrmp`** pallet. + 2. Choose the **`establish_channel_with_system`** extrinsic. + 3. Fill in the parameters: + - **`target_system_chain`**: Parachain ID of the target system chain (in this case, 1000). + 4. Copy the encoded call data. + ![](/images/parachains/interoperability/channels-with-system-parachains/system-parachains-01.webp) -```bash title="eth_getStorageAt" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getStorageAt", - "params":["INSERT_ADDRESS", "INSERT_STORAGE_KEY", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. + The encoded call data for establishing a channel with system parachain 1000 should be `0x3c0ae8030000`. ---- +### Craft and Submit the XCM Message -### eth_getTransactionCount +Connect to parachain 2500 using Polkadot.js Apps to send the XCM message to the relay chain. Input the necessary parameters as illustrated in the image below. Make sure to: -Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}. +1. Insert your previously encoded `establish_channel_with_system` call data into the **`call`** field. +2. Provide beneficiary details. +3. Dispatch the XCM message to the relay chain by clicking the **Submit Transaction** button. -**Parameters**: +![](/images/parachains/interoperability/channels-with-system-parachains/system-parachains-02.webp) -- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). +!!! note + The exact process and parameters for submitting this XCM message may vary depending on your specific parachain and relay chain configurations. Always refer to the most current documentation for your particular network setup. -**Example**: +After successfully submitting the XCM message to the relay chain, two [`HrmpSystemChannelOpened`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/hrmp/pallet/enum.Event.html#variant.HrmpSystemChannelOpened){target=\_blank} events are emitted, indicating that the channels are now present in storage under [`HrmpOpenChannelRequests`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/hrmp/pallet/storage_types/struct.HrmpOpenChannelRequests.html){target=\_blank}. However, the channels are not actually set up until the start of the next session, at which point bidirectional communication between parachain 2500 and system chain 1000 is established. -```bash title="eth_getTransactionCount" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionCount", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` +To verify this, wait for the next session and then follow these steps: -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. +1. Using Polkadot.js Apps, connect to the relay chain and navigate to the **Developer** dropdown, then select **Chain state**. ---- + ![](/images/parachains/interoperability/channels-common/channels-03.webp) -### eth_getTransactionByHash +2. Query the HRMP channels: -Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. + 1. Select **`hrmp`** from the options. + 2. Choose the **`hrmpChannels`** call. + 3. Click the **+** button to execute the query. -**Parameters**: + ![](/images/parachains/interoperability/channels-with-system-parachains/system-parachains-03.webp) + +3. Examine the query results. You should see output similar to the following: -- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + ```json + [ + [ + [ + { + "sender": 1000, + "recipient": 2500 + } + ], + { + "maxCapacity": 8, + "maxTotalSize": 8192, + "maxMessageSize": 1048576, + "msgCount": 0, + "totalSize": 0, + "mqcHead": null, + "senderDeposit": 0, + "recipientDeposit": 0 + } + ], + [ + [ + { + "sender": 2500, + "recipient": 1000 + } + ], + { + "maxCapacity": 8, + "maxTotalSize": 8192, + "maxMessageSize": 1048576, + "msgCount": 0, + "totalSize": 0, + "mqcHead": null, + "senderDeposit": 0, + "recipientDeposit": 0 + } + ] + ] -**Example**: + ``` -```bash title="eth_getTransactionByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByHash", - "params":["INSERT_TRANSACTION_HASH"], - "id":1 -}' -``` +The output confirms the successful establishment of two HRMP channels: -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. +- From chain 1000 (system chain) to chain 2500 (parachain). +- From chain 2500 (parachain) to chain 1000 (system chain). ---- +This bidirectional channel enables direct communication between the system chain and the parachain, allowing for cross-chain message passing. -### eth_getTransactionByBlockNumberAndIndex -Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. +--- -**Parameters**: +Page Title: Overview of FRAME -- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md +- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ +- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. -**Example**: +# Customize Your Runtime -```bash title="eth_getTransactionByBlockNumberAndIndex" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByBlockNumberAndIndex", - "params":["INSERT_BLOCK_VALUE", "INSERT_TRANSACTION_INDEX"], - "id":1 -}' -``` +## Introduction -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. +A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. ---- +This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. -### eth_getTransactionByBlockHashAndIndex +## Understanding Your Runtime -Returns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}. +The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. -**Parameters**: +Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. -- **`blockHash` ++"string"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +## Runtime Architecture -**Example**: +The following diagram shows how FRAME components work together to form your runtime: -```bash title="eth_getTransactionByBlockHashAndIndex" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByBlockHashAndIndex", - "params":["INSERT_BLOCK_HASH", "INSERT_TRANSACTION_INDEX"], - "id":1 -}' -``` +![](/images/parachains/customize-runtime/index/frame-overview-01.webp) -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. +The main components are: ---- +- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. +- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. +- **`frame_system`**: Provides core runtime primitives and storage. +- **`frame_support`**: Utilities and macros that simplify pallet development. -### eth_getTransactionReceipt +## Building Blocks: Pallets -Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. +[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. -**Parameters**: +A pallet can implement virtually any blockchain feature you need: -- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- Expose new transactions that users can submit. +- Store data on-chain. +- Enforce business rules and validation logic. +- Emit events to notify users of state changes. +- Handle errors gracefully. -**Example**: +### Pre-Built Pallets vs. Custom Pallets -```bash title="eth_getTransactionReceipt" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionReceipt", - "params":["INSERT_TRANSACTION_HASH"], - "id":1 -}' -``` +FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. +However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. ---- +### Pallet Structure -### eth_maxPriorityFeePerGas +FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. -Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. +A typical pallet looks like this: -**Parameters**: +```rust +pub use pallet::*; -None. +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; -**Example**: + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); -```bash title="eth_maxPriorityFeePerGas" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_maxPriorityFeePerGas", - "params":[], - "id":1 -}' + #[pallet::config] // snip + #[pallet::event] // snip + #[pallet::error] // snip + #[pallet::storage] // snip + #[pallet::call] // snip +} ``` ---- +Every pallet can implement these core macros: -### eth_sendRawTransaction +- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. +- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. +- **`#[pallet::config]`**: Defines configuration and associated types. +- **`#[pallet::event]`**: Defines events emitted by your pallet. +- **`#[pallet::error]`**: Defines error types your pallet can return. +- **`#[pallet::storage]`**: Defines on-chain storage items. +- **`#[pallet::call]`**: Defines dispatchable functions (transactions). -Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. +For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. -**Parameters**: +## How Runtime Customization Works -- **`callData` ++"string"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +Customizing your runtime typically follows these patterns: -**Example**: +**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. -```bash title="eth_sendRawTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_sendRawTransaction", - "params":["INSERT_CALL_DATA"], - "id":1 -}' -``` +**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. -Ensure to replace the `INSERT_CALL_DATA` with the proper values. +**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. ---- +**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. -### eth_sendTransaction +The following diagram illustrates how pallets combine to form a complete runtime: -Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. +![](/images/parachains/customize-runtime/index/frame-overview-02.webp) -**Parameters**: +## Starting Templates -- **`transaction` ++"object"++**: The transaction object. - - **`from` ++"string"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`to` ++"string"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`data` ++"string"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`nonce` ++"string"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. -**Example**: +- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. -```bash title="eth_sendTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_sendTransaction", - "params":[{ - "from": "INSERT_SENDER_ADDRESS", - "to": "INSERT_RECIPIENT_ADDRESS", - "gas": "INSERT_GAS_LIMIT", - "gasPrice": "INSERT_GAS_PRICE", - "value": "INSERT_VALUE", - "input": "INSERT_INPUT_DATA", - "nonce": "INSERT_NONCE" - }], - "id":1 -}' -``` +- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. -Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values. +- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. ---- +- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. -### eth_syncing +## Key Customization Scenarios -Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. +This section covers the most common customization patterns you'll encounter: -**Parameters**: +- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. -None. +- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. -**Example**: +- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. + +- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. + +- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. -```bash title="eth_syncing" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_syncing", - "params":[], - "id":1 -}' -``` --- -### net_listening +Page Title: Pallet Testing -Returns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\_blank}. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md +- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/ +- Summary: Learn how to efficiently test pallets in the Polkadot SDK, ensuring the reliability and security of your pallets operations. -**Parameters**: +# Pallet Testing -None. +## Introduction -**Example**: +Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries. -```bash title="net_listening" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_listening", - "params":[], - "id":1 -}' -``` +To begin unit testing, you must first set up a mock runtime that simulates blockchain behavior, incorporating the necessary pallets. For a deeper understanding, consult the [Mock Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\_blank} guide. ---- +## Writing Unit Tests -### net_peerCount +Once the mock runtime is in place, the next step is to write unit tests that evaluate the functionality of your pallet. Unit tests allow you to test specific pallet features in isolation, ensuring that each function behaves correctly under various conditions. These tests typically reside in your pallet module's `test.rs` file. -Returns the number of peers currently connected to the client. +Unit tests in the Polkadot SDK use the Rust testing framework, and the mock runtime you've defined earlier will serve as the test environment. Below are the typical steps involved in writing unit tests for a pallet. -**Parameters**: +The tests confirm that: -None. +- **Pallets initialize correctly**: At the start of each test, the system should initialize with block number 0, and the pallets should be in their default states. +- **Pallets modify each other's state**: The second test shows how one pallet can trigger changes in another pallet's internal state, confirming proper cross-pallet interactions. +- **State transitions between blocks are seamless**: By simulating block transitions, the tests validate that the runtime responds correctly to changes in the block number. -**Example**: +Testing pallet interactions within the runtime is critical for ensuring the blockchain behaves as expected under real-world conditions. Writing integration tests allows validation of how pallets function together, preventing issues that might arise when the system is fully assembled. -```bash title="net_peerCount" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_peerCount", - "params":[], - "id":1 -}' -``` +This approach provides a comprehensive view of the runtime's functionality, ensuring the blockchain is stable and reliable. ---- +### Test Initialization -### net_version +Each test starts by initializing the runtime environment, typically using the `new_test_ext()` function, which sets up the mock storage and environment. -Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. +```rust +#[test] +fn test_pallet_functionality() { + new_test_ext().execute_with(|| { + // Test logic goes here + }); +} +``` -**Parameters**: +### Function Call Testing -None. +Call the pallet's extrinsics or functions to simulate user interaction or internal logic. Use the `assert_ok!` macro to check for successful execution and `assert_err!` to verify that errors are correctly handled. -**Example**: +```rust +#[test] +fn it_works_for_valid_input() { + new_test_ext().execute_with(|| { + // Call an extrinsic or function + assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param)); + }); +} -```bash title="net_version" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_version", - "params":[], - "id":1 -}' +#[test] +fn it_fails_for_invalid_input() { + new_test_ext().execute_with(|| { + // Call an extrinsic with invalid input and expect an error + assert_err!( + TemplateModule::some_function(Origin::signed(1), invalid_param), + Error::::InvalidInput + ); + }); +} ``` ---- +### Storage Testing -### system_health +After calling a function or extrinsic in your pallet, it's essential to verify that the state changes in the pallet's storage match the expected behavior to ensure data is updated correctly based on the actions taken. -Returns information about the health of the system. +The following example shows how to test the storage behavior before and after the function call: -**Parameters**: +```rust +#[test] +fn test_storage_update_on_extrinsic_call() { + new_test_ext().execute_with(|| { + // Check the initial storage state (before the call) + assert_eq!(Something::::get(), None); -None. + // Dispatch a signed extrinsic, which modifies storage + assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42)); -**Example**: + // Validate that the storage has been updated as expected (after the call) + assert_eq!(Something::::get(), Some(42)); + }); +} -```bash title="system_health" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"system_health", - "params":[], - "id":1 -}' ``` ---- +### Event Testing -### web3_clientVersion +It's also crucial to test the events that your pallet emits during execution. By default, events generated in a pallet using the [`#generate_deposit`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.generate_deposit.html){target=\_blank} macro are stored under the system's event storage key (system/events) as [`EventRecord`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.EventRecord.html){target=\_blank} entries. These can be accessed using [`System::events()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.events){target=\_blank} or verified with specific helper methods provided by the system pallet, such as [`assert_has_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_has_event){target=\_blank} and [`assert_last_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_last_event){target=\_blank}. -Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. +Here's an example of testing events in a mock runtime: -**Parameters**: +```rust +#[test] +fn it_emits_events_on_success() { + new_test_ext().execute_with(|| { + // Call an extrinsic or function + assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param)); -None. + // Verify that the expected event was emitted + assert!(System::events().iter().any(|record| { + record.event == Event::TemplateModule(TemplateEvent::SomeEvent) + })); + }); +} +``` -**Example**: +Some key considerations are: -```bash title="web3_clientVersion" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"web3_clientVersion", - "params":[], - "id":1 -}' -``` +- **Block number**: Events are not emitted on the genesis block, so you need to set the block number using [`System::set_block_number()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.set_block_number){target=\_blank} to ensure events are triggered. +- **Converting events**: Use `.into()` when instantiating your pallet's event to convert it into a generic event type, as required by the system's event storage. ---- +## Where to Go Next -### debug_traceBlockByNumber +- Dive into the full implementation of the [`mock.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/mock.rs){target=\_blank} and [`test.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/tests.rs){target=\_blank} files in the [Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=_blank}. -Traces a block's execution by its number and returns a detailed execution trace for each transaction. +
    -**Parameters**: +- Guide __Benchmarking__ -- **`blockValue` ++"string"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`options` ++"object"++**: (Optional) An object containing tracer options. - - **`tracer` ++"string"++**: The name of the tracer to use (e.g., `"callTracer"`, `"opTracer"`). - - Other tracer-specific options may be supported. + --- -**Example**: + Explore methods to measure the performance and execution cost of your pallet. -```bash title="debug_traceBlockByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceBlockByNumber", - "params":["INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], - "id":1 -}' -``` + [:octicons-arrow-right-24: Reference](/develop/parachains/testing/benchmarking) + +
    -Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. --- -### debug_traceTransaction +Page Title: Run a Parachain Network -Traces the execution of a single transaction by its hash and returns a detailed execution trace. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md +- Canonical (HTML): https://docs.polkadot.com/parachains/testing/run-a-parachain-network/ +- Summary: Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. -**Parameters**: +# Run a Parachain Network Using Zombienet -- **`transactionHash` ++"string"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). +## Introduction -**Example**: +Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance. -```bash title="debug_traceTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceTransaction", - "params":["INSERT_TRANSACTION_HASH", {"tracer": "callTracer"}], - "id":1 -}' -``` +This guide will outline the different installation methods for Zombienet, provide step-by-step instructions for setting up on various platforms, and highlight essential provider-specific features and requirements. -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. +By following this guide, Zombienet will be up and running quickly, ready to streamline your blockchain testing and development workflows. ---- +## Install Zombienet -### debug_traceCall +Zombienet releases are available on the [Zombienet repository](https://github.com/paritytech/zombienet){target=\_blank}. -Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. +Multiple options are available for installing Zombienet, depending on the user's preferences and the environment where it will be used. The following section will guide you through the installation process for each option. -**Parameters**: +=== "Use the executable" -- **`transaction` ++"object"++**: The transaction call object, similar to `eth_call` parameters. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). + Install Zombienet using executables by visiting the [latest release](https://github.com/paritytech/zombienet/releases){target=\_blank} page and selecting the appropriate asset for your operating system. You can download the executable and move it to a directory in your PATH. -**Example**: + Each release includes executables for Linux and macOS. Executables are generated using [pkg](https://github.com/vercel/pkg){target=\_blank}, which allows the Zombienet CLI to operate without requiring Node.js to be installed. -```bash title="debug_traceCall" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceCall", - "params":[{ - "from": "INSERT_SENDER_ADDRESS", - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_CALL" - }, "INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], - "id":1 -}' -``` + Then, ensure the downloaded file is executable: -Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value. + ```bash + chmod +x zombienet-macos-arm64 + ``` ---- + Finally, you can run the following command to check if the installation was successful. If so, it will display the version of the installed Zombienet: -## Response Format + ```bash + ./zombienet-macos-arm64 version + ``` -All responses follow the standard JSON-RPC 2.0 format: + If you want to add the `zombienet` executable to your PATH, you can move it to a directory in your PATH, such as `/usr/local/bin`: -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": ... // The return value varies by method -} -``` + ```bash + mv zombienet-macos-arm64 /usr/local/bin/zombienet + ``` -## Error Handling + Now you can refer to the `zombienet` executable directly. -If an error occurs, the response will include an error object: + ```bash + zombienet version + ``` -```json -{ - "jsonrpc": "2.0", - "id": 1, - "error": { - "code": -32000, - "message": "Error message here" - } -} -``` +=== "Use Nix" + For Nix users, the Zombienet repository provides a [`flake.nix`](https://github.com/paritytech/zombienet/blob/main/flake.nix){target=\_blank} file to install Zombienet making it easy to incorporate Zombienet into Nix-based projects. + + To install Zombienet utilizing Nix, users can run the following command, triggering the fetching of the flake and subsequently installing the Zombienet package: ---- + ```bash + nix run github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION -- \ + spawn INSERT_ZOMBIENET_CONFIG_FILE_NAME.toml + ``` -Page Title: Light Clients + Replace the `INSERT_ZOMBIENET_VERSION` with the desired version of Zombienet and the `INSERT_ZOMBIENET_CONFIG_FILE_NAME` with the name of the configuration file you want to use. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/light-clients/ -- Summary: Light clients enable secure and efficient blockchain interaction without running a full node. Learn everything you need to know about light clients on Polkadot. + To run the command above, you need to have [Flakes](https://nixos.wiki/wiki/Flakes#Enable_flakes){target=\_blank} enabled. -# Light Clients + Alternatively, you can also include the Zombienet binary in the PATH for the current shell using the following command: + + ```bash + nix shell github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION + ``` -## Introduction +=== "Use Docker" -Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes. + Zombienet can also be run using Docker. The Zombienet repository provides a Docker image that can be used to run the Zombienet CLI. To run Zombienet using Docker, you can use the following command: -This guide covers: + ```bash + docker run -it --rm \ + -v $(pwd):/home/nonroot/zombie-net/host-current-files \ + paritytech/zombienet + ``` -- What light clients are and how they work. -- Their advantages compared to full nodes and JSON-RPC. -- Available implementations in the Polkadot ecosystem. -- How to use light clients in your applications. + The command above will run the Zombienet CLI inside a Docker container and mount the current directory to the `/home/nonroot/zombie-net/host-current-files` directory. This allows Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path. -Light clients are particularly valuable for resource-constrained environments and applications requiring secure, decentralized blockchain access without the overhead of maintaining full nodes. + Inside the Docker container, you can run the Zombienet CLI commands. First, you need to set up Zombienet to download the necessary binaries: -!!!note "Light node or light client?" - The terms _light node_ and _light client_ are interchangeable. Both refer to a blockchain client that syncs without downloading the entire blockchain state. All nodes in a blockchain network are fundamentally clients, engaging in peer-to-peer communication. + ```bash + npm run zombie -- setup polkadot polkadot-parachain + ``` -## Light Clients Workflow + After that, you need to add those binaries to the PATH: -Unlike JSON-RPC interfaces, where an application must maintain a list of providers or rely on a single node, light clients are not limited to or dependent on a single node. They use cryptographic proofs to verify the blockchain's state, ensuring it is up-to-date and accurate. By verifying only block headers, light clients avoid syncing the entire state, making them ideal for resource-constrained environments. + ```bash + export PATH=/home/nonroot/zombie-net:$PATH + ``` -```mermaid -flowchart LR -DAPP([dApp])-- Query Account Info -->LC([Light Client]) -LC -- Request --> FN(((Full Node))) -LC -- Response --> DAPP -FN -- Response (validated via Merkle proof) --> LC -``` + Finally, you can run the Zombienet CLI commands. For example, to spawn a network using a specific configuration file, you can run the following command: -In the diagram above, the decentralized application queries on-chain account information through the light client. The light client runs as part of the application and requires minimal memory and computational resources. It uses Merkle proofs to verify the state retrieved from a full node in a trust-minimized manner. Polkadot-compatible light clients utilize [warp syncing](https://spec.polkadot.network/sect-lightclient#sect-sync-warp-lightclient){target=\_blank}, which downloads only block headers. + ```bash + npm run zombie -- -p native spawn host-current-files/minimal.toml + ``` -Light clients can quickly verify the blockchain's state, including [GRANDPA finality](/polkadot-protocol/glossary#grandpa){target=\_blank} justifications. + The command above mounts the current directory to the `/workspace` directory inside the Docker container, allowing Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path. -!!!note "What does it mean to be trust-minimized?" - _Trust-minimized_ means that the light client does not need to fully trust the full node from which it retrieves the state. This is achieved through the use of Merkle proofs, which allow the light client to verify the correctness of the state by checking the Merkle tree root. +## Providers -## JSON-RPC and Light Client Comparison +Zombienet supports different backend providers for running the nodes. At this moment, [Kubernetes](https://kubernetes.io/){target=\_blank}, [Podman](https://podman.io/){target=\_blank}, and local providers are supported, which can be declared as `kubernetes`, `podman`, or `native`, respectively. -Another common method of communication between a user interface (UI) and a node is through the JSON-RPC protocol. Generally, the UI retrieves information from the node, fetches network or [pallet](/polkadot-protocol/glossary#pallet){target=\_blank} data, and interacts with the blockchain. This is typically done in one of two ways: +To use a particular provider, you can specify it in the network file or use the `--provider` flag in the CLI: -- **User-controlled nodes**: The UI connects to a node client installed on the user's machine. - - These nodes are secure, but installation and maintenance can be inconvenient. -- **Publicly accessible nodes**: The UI connects to a third-party-owned publicly accessible node client. - - These nodes are convenient but centralized and less secure. Applications must maintain a list of backup nodes in case the primary node becomes unavailable. +```bash +zombienet spawn network.toml --provider INSERT_PROVIDER +``` -While light clients still communicate with [full nodes](/polkadot-protocol/glossary#full-node), they offer significant advantages for applications requiring a secure alternative to running a full node: +Alternatively, you can set the provider in the network file: -| Full Node | Light Client | -| :---------------------------------------------------------------------------------------------: | :------------------------------------------------------------: | -| Fully verifies all blocks of the chain | Verifies only the authenticity of blocks | -| Stores previous block data and the chain's storage in a database | Does not require a database | -| Installation, maintenance, and execution are resource-intensive and require technical expertise | No installation is typically included as part of the application | +```toml +[settings] +provider = "INSERT_PROVIDER" +... +``` -## Using Light Clients +It's important to note that each provider has specific requirements and associated features. The following sections cover each provider's requirements and added features. -The [`smoldot`](https://github.com/smol-dot/smoldot){target=\_blank} client is the cornerstone of light client implementation for Polkadot SDK-based chains. It provides the primitives needed to build light clients and is also integrated into libraries such as [PAPI](#papi-light-client-support). +### Kubernetes -### PAPI Light Client Support +Kubernetes is a portable, extensible, open-source platform for managing containerized workloads and services. Zombienet is designed to be compatible with a variety of Kubernetes clusters, including: -The [Polkadot API (PAPI)](/develop/toolkit/api-libraries/papi){target=\_blank} library natively supports light client configurations powered by [`smoldot`](https://github.com/smol-dot/smoldot){target=\_blank}. This allows developers to connect to multiple chains simultaneously using a light client. +- [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine){target=\_blank} +- [Docker Desktop](https://docs.docker.com/desktop/features/kubernetes/){target=\_blank} +- [kind](https://kind.sigs.k8s.io/){target=\_blank} -### Substrate Connect - Browser Extension +#### Requirements + +To effectively interact with your cluster, you'll need to ensure that [`kubectl`](https://kubernetes.io/docs/reference/kubectl/){target=\_blank} is installed on your system. This Kubernetes command-line tool allows you to run commands against Kubernetes clusters. If you don't have `kubectl` installed, you can follow the instructions provided in the [Kubernetes documentation](https://kubernetes.io/docs/tasks/tools/#kubectl){target=\_blank}. -The [Substrate Connect browser extension](https://www.npmjs.com/package/@substrate/connect-extension-protocol){target=\_blank} enables end-users to interact with applications connected to multiple blockchains or to connect their own blockchains to supported applications. +To create resources such as namespaces, pods, and CronJobs within the target cluster, you must grant your user or service account the appropriate permissions. These permissions are essential for managing and deploying applications effectively within Kubernetes. -Establishing a sufficient number of peers can be challenging due to browser limitations on WebSocket connections from HTTPS pages, as many nodes require TLS. The Substrate Connect browser extension addresses this limitation by keeping chains synced in the background, enabling faster application performance. +#### Features + +If available, Zombienet uses the Prometheus operator to oversee monitoring and visibility. This configuration ensures that only essential networking-related pods are deployed. Using the Prometheus operator, Zombienet improves its ability to monitor and manage network activities within the Kubernetes cluster efficiently. -Substrate Connect automatically detects whether the user has the extension installed. If not, an in-page Wasm light client is created for them. +### Podman -## Resources +Podman is a daemonless container engine for developing, managing, and running Open Container Initiative (OCI) containers and container images on Linux-based systems. Zombienet supports Podman rootless as a provider on Linux machines. Although Podman has support for macOS through an internal virtual machine (VM), the Zombienet provider code requires Podman to run natively on Linux. -- [What is a light client and why you should care?](https://medium.com/paritytech/what-is-a-light-client-and-why-you-should-care-75f813ae2670){target=\_blank} -- [Introducing Substrate Connect: Browser-Based Light Clients for Connecting to Substrate Chains](https://www.parity.io/blog/introducing-substrate-connect){target=\_blank} -- [Substrate Connect GitHub Repository](https://github.com/paritytech/substrate-connect/tree/master/projects/extension){target=\_blank} -- [Light Clients - Polkadot Specification](https://spec.polkadot.network/sect-lightclient){target=\_blank} +#### Requirements + +To use Podman as a provider, you need to have Podman installed on your system. You can install Podman by following the instructions provided on the [Podman website](https://podman.io/getting-started/installation){target=\_blank}. +#### Features + +Using Podman, Zombienet deploys additional pods to enhance the monitoring and visibility of the active network. Specifically, pods for [Prometheus](https://prometheus.io/){target=\_blank}, [Tempo](https://grafana.com/docs/tempo/latest/operations/monitor/){target=\_blank}, and [Grafana](https://grafana.com/){target=\_blank} are included in the deployment. Grafana is configured with Prometheus and Tempo as data sources. ---- +Upon launching Zombienet, access to these monitoring services is facilitated through specific URLs provided in the output: -Page Title: Mock Your Runtime +- **Prometheus**: `http://127.0.0.1:34123` +- **Tempo**: `http://127.0.0.1:34125` +- **Grafana**: `http://127.0.0.1:41461` -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md -- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/ -- Summary: Learn how to create a mock runtime environment for testing your custom pallets in isolation, enabling comprehensive unit testing before runtime integration. +It's important to note that Grafana is deployed with default administrator access. + +When network operations cease, either from halting a running spawn with the `Ctrl+C` command or test completion, Zombienet automatically removes all associated pods. -# Mock Your Runtime +### Local Provider -## Introduction +The Zombienet local provider, also called native, enables you to run nodes as local processes in your environment. -Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node. +#### Requirements + +You must have the necessary binaries for your network (such as `polkadot` and `polkadot-parachain`). These binaries should be available in your PATH, allowing Zombienet to spawn the nodes as local processes. -In this guide, you'll learn how to create a mock runtime for the custom counter pallet built in the [Make a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\_blank} guide. This mock runtime will enable you to write comprehensive unit tests that verify: +To install the necessary binaries, you can use the Zombienet CLI command: -- Dispatchable function behavior. -- Storage state changes. -- Event emission. -- Error handling. -- Access control and origin validation. -- Genesis configuration. +```bash +zombienet setup polkadot polkadot-parachain +``` -## Prerequisites +This command will download and prepare the necessary binaries for Zombienet's use. -Before you begin, ensure you have: +If you need to use a custom binary, ensure the binary is available in your PATH. You can also specify the binary path in the network configuration file. The following example uses the custom [OpenZeppelin template](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}: -- Completed the [Make a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/){target=\_blank} guide. -- The custom counter pallet from the Make a Custom Pallet guide. Available in `pallets/pallet-custom`. -- Basic understanding of [Rust testing](https://doc.rust-lang.org/book/ch11-00-testing.html){target=\_blank}. +First, clone the OpenZeppelin template repository using the following command: -## Understand Mock Runtimes +```bash +git clone https://github.com/OpenZeppelin/polkadot-runtime-templates \ +&& cd polkadot-runtime-templates/generic-template +``` -A mock runtime is a minimal implementation of the runtime environment that: +Next, run the command to build the custom binary: -- Simulates blockchain state to provide storage and state management. -- Satisfies your pallet's `Config` trait requirements. -- Allows isolated testing without external dependencies. -- Supports genesis configuration to set initial blockchain state for tests. -- Provides instant feedback on code changes for a faster development cycle. +```bash +cargo build --release +``` -Mock runtimes are used exclusively for testing and are never deployed to a live blockchain. +Finally, add the custom binary to your PATH as follows: -## Create the Mock Runtime Module +```bash +export PATH=$PATH:INSERT_PATH_TO_RUNTIME_TEMPLATES/parachain-template-node/target/release +``` -Start by creating a new module file within your pallet to house the mock runtime code. +Alternatively, you can specify the binary path in the network configuration file. The local provider exclusively utilizes the command configuration for nodes, which supports both relative and absolute paths. You can employ the `default_command` configuration to specify the binary for spawning all nodes in the relay chain. -1. Navigate to your pallet directory: +```toml +[relaychain] +chain = "rococo-local" +default_command = "./bin-v1.6.0/polkadot" - ```bash - cd pallets/pallet-custom/src - ``` +[parachain] +id = 1000 -2. Create a new file named `mock.rs`: + [parachain.collators] + name = "collator01" + command = "./target/release/parachain-template-node" +``` - ```bash - touch mock.rs - ``` +#### Features -3. Next, open `src/lib.rs` and add the mock module declaration at the top of the file, right after the `pub use pallet::*;` line: +The local provider does not offer any additional features. - ```rust title="src/lib.rs" - #![cfg_attr(not(feature = "std"), no_std)] +## Configure Zombienet - pub use pallet::*; +Effective network configuration is crucial for deploying and managing blockchain systems. Zombienet simplifies this process by offering versatile configuration options in both JSON and TOML formats. Whether setting up a simple test network or a complex multi-node system, Zombienet's tools provide the flexibility to customize every aspect of your network's setup. - #[cfg(test)] - mod mock; +The following sections will explore the structure and usage of Zombienet configuration files, explain key settings for network customization, and walk through CLI commands and flags to optimize your development workflow. - #[frame::pallet] - pub mod pallet { - // ... existing pallet code - } - - ``` - - The `#[cfg(test)]` attribute ensures this module is only compiled during testing. +### Configuration Files -## Set Up Basic Mock +The network configuration file can be either JSON or TOML format. The Zombienet repository also provides a collection of [example configuration files](https://github.com/paritytech/zombienet/tree/main/examples){target=\_blank} that can be used as a reference. -Open `src/mock.rs` and add the foundational imports and type definitions: +Each section may include provider-specific keys that aren't recognized by other providers. For example, if you use the local provider, any references to images for nodes will be disregarded. -```rust title="src/mock.rs" -use crate as pallet_custom; -use frame::{ - deps::{ - frame_support::{ derive_impl, traits::ConstU32 }, - sp_io, - sp_runtime::{ traits::IdentityLookup, BuildStorage }, - }, - prelude::*, -}; +### CLI Usage -type Block = frame_system::mocking::MockBlock; +Zombienet provides a CLI that allows interaction with the tool. The CLI can receive commands and flags to perform different kinds of operations. These operations use the following syntax: -// Configure a mock runtime to test the pallet. -frame::deps::frame_support::construct_runtime!( - pub enum Test - { - System: frame_system, - CustomPallet: pallet_custom, - } - ); +```bash +zombienet ``` -The preceding code includes the following key components: +The following sections will guide you through the primary usage of the Zombienet CLI and the available commands and flags. -- **[`construct_runtime!`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/apis/trait.ConstructRuntimeApi.html#tymethod.construct_runtime_api){target=\_blank}**: Macro that builds a minimal runtime with only the pallets needed for testing. -- **`Test`**: The mock runtime type used in tests. -- **`Block`**: Type alias for the mock block type that the runtime will use. +#### CLI Commands -## Implement Essential Configuration +- **`spawn `**: Spawn the network defined in the [configuration file](#configuration-files). +- **`test `**: Run tests on the spawned network using the assertions and tests defined in the [test file](/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/#the-test-file){target=\_blank}. +- **`setup `**: Set up the Zombienet development environment to download and use the `polkadot` or `polkadot-parachain` executable. +- **`convert `**: Transforms a [polkadot-launch](https://github.com/paritytech/polkadot-launch){target=\_blank} configuration file with a `.js` or `.json` extension into a Zombienet configuration file. +- **`version`**: Prints Zombienet version. +- **`help`**: Prints help information. -The [`frame_system`](https://paritytech.github.io/polkadot-sdk/master/frame_system/index.html){target=\_blank} pallet provides core blockchain functionality and is required by all other pallets. Configure it for the test environment as follows: +#### CLI Flags -```rust title="src/mock.rs" -#[derive_impl(frame_system::config_preludes::TestDefaultConfig)] -impl frame_system::Config for Test { - type Block = Block; - type AccountId = u64; - type Lookup = IdentityLookup; -} -``` +You can use the following flags to customize the behavior of the CLI: -This simplified configuration for testing includes the following: +- **`-p`, `--provider`**: Override the [provider](#providers) to use. +- **`-d`, `--dir`**: Specify a directory path for placing the network files instead of using the default temporary path. +- **`-f`, `--force`**: Force override all prompt commands. +- **`-l`, `--logType`**: Type of logging on the console. Defaults to `table`. +- **`-m`, `--monitor`**: Start as monitor and don't auto clean up network. +- **`-c`, `--spawn-concurrency`**: Number of concurrent spawning processes to launch. Defaults to `1`. +- **`-h`, `--help`**: Display help for command. -- **`#[derive_impl]`**: Automatically provides sensible test defaults for most `frame_system::Config` types. -- **`AccountId = u64`**: Uses simple integers instead of cryptographic account IDs. -- **`Lookup = IdentityLookup`**: Direct account ID mapping (no address conversion). -- **`Block = Block`**: Uses the mock block type we defined earlier. +### Settings -This approach is much more concise than manually specifying every configuration type, as the `TestDefaultConfig` preset provides appropriate defaults for testing. +Through the keyword `settings`, it's possible to define the general settings for the network. The available keys are: -## Implement Your Pallet's Configuration +- **`global_volumes?`** ++"GlobalVolume[]"++: A list of global volumes to use. -Now implement the `Config` trait for your custom pallet. This trait must match the one defined in your pallet's `src/lib.rs`: + ??? child "`GlobalVolume` interface definition" + ```js + export interface GlobalVolume { + name: string; + fs_type: string; + mount_path: string; + } + ``` -```rust title="src/mock.rs" -impl pallet_custom::Config for Test { - type RuntimeEvent = RuntimeEvent; - type CounterMaxValue = ConstU32<1000>; -} -``` +- **`bootnode`** ++"boolean"++: Add bootnode to network. Defaults to `true`. +- **`bootnode_domain?`** ++"string"++: Domain to use for bootnode. +- **`timeout`** ++"number"++: Global timeout to use for spawning the whole network. +- **`node_spawn_timeout?`** ++"number"++: Timeout to spawn pod/process. +- **`grafana?`** ++"boolean"++: Deploy an instance of Grafana. +- **`prometheus?`** ++"boolean"++: Deploy an instance of Prometheus. +- **`telemetry?`** ++"boolean"++: Enable telemetry for the network. +- **`jaeger_agent?`** ++"string"++: The Jaeger agent endpoint passed to the nodes. Only available on Kubernetes. +- **`tracing_collator_url?`** ++"string"++: The URL of the tracing collator used to query by the tracing assertion. Should be tempo query compatible. +- **`tracing_collator_service_name?`** ++"string"++: Service name for tempo query frontend. Only available on Kubernetes. Defaults to `tempo-tempo-distributed-query-frontend`. +- **`tracing_collator_service_namespace?`** ++"string"++: Namespace where tempo is running. Only available on Kubernetes. Defaults to `tempo`. +- **`tracing_collator_service_port?`** ++"number"++: Port of the query instance of tempo. Only available on Kubernetes. Defaults to `3100`. +- **`enable_tracing?`** ++"boolean"++: Enable the tracing system. Only available on Kubernetes. Defaults to `true`. +- **`provider`** ++"string"++: Provider to use. Default is `kubernetes`". +- **`polkadot_introspector?`** ++"boolean"++: Deploy an instance of polkadot-introspector. Only available on Podman and Kubernetes. Defaults to `false`. +- **`backchannel?`** ++"boolean"++: Deploy an instance of backchannel server. Only available on Kubernetes. Defaults to `false`. +- **`image_pull_policy?`** ++"string"++: Image pull policy to use in the network. Possible values are `Always`, `IfNotPresent`, and `Never`. +- **`local_ip?`** ++"string"++: IP used for exposing local services (rpc/metrics/monitors). Defaults to `"127.0.0.1"`. +- **`global_delay_network_global_settings?`** ++"number"++: Delay in seconds to apply to the network. +- **`node_verifier?`** ++"string"++: Specify how to verify node readiness or deactivate by using `None`. Possible values are `None` and `Metric`. Defaults to `Metric`. -Configuration details include: +For example, the following configuration file defines a minimal example for the settings: -- **`RuntimeEvent`**: Connects your pallet's events to the mock runtime's event system. -- **`CounterMaxValue`**: Sets the maximum counter value to 1000, matching the production configuration. +=== "TOML" -The configuration here should mirror what you'll use in production unless you specifically need different values for testing. + ```toml title="base-example.toml" + [settings] + timeout = 1000 + bootnode = false + provider = "kubernetes" + backchannel = false + # ... -## Configure Genesis Storage + ``` -Genesis storage defines the initial state of your blockchain before any blocks are produced. Since your counter pallet includes the genesis configuration (added in the previous guide), you can now set up test environments with different initial states. +=== "JSON" -### Basic Test Environment + ```json title="base-example.json" + { + "settings": { + "timeout": 1000, + "bootnode": false, + "provider": "kubernetes", + "backchannel": false, + "...": {} + }, + "...": {} + } -Create a helper function for the default test environment: + ``` -```rust title="src/mock.rs" -// Build genesis storage according to the mock runtime. -pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); +### Relay Chain Configuration - (pallet_custom::GenesisConfig:: { - initial_counter_value: 0, - initial_user_interactions: vec![], - }) - .assimilate_storage(&mut t) - .unwrap(); +You can use the `relaychain` keyword to define further parameters for the relay chain at start-up. The available keys are: - t.into() -} -``` +- **`default_command?`** ++"string"++: The default command to run. Defaults to `polkadot`. +- **`default_image?`** ++"string"++: The default Docker image to use. +- **`default_resources?`** ++"Resources"++: Represents the resource limits/reservations the nodes need by default. Only available on Kubernetes. -This function creates a clean blockchain state with an initial counter value of 0 and no user interactions. + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` -### Custom Genesis Configurations +- **`default_db_snapshot?`** ++"string"++: The default database snapshot to use. +- **`default_prometheus_prefix`** ++"string"++: A parameter for customizing the metric's prefix. Defaults to `substrate`. +- **`default_substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version. -For testing specific scenarios, create additional helper functions with customized genesis states: + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } + ``` -```rust title="src/mock.rs" -// Helper function to create a test externalities with a specific initial counter value -pub fn new_test_ext_with_counter(initial_value: u32) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); +- **`default_keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. +- **`chain`** ++"string"++: The chain name. +- **`chain_spec_path?`** ++"string"++: Path to the chain spec file. Should be the plain version to allow customizations. +- **`chain_spec_command?`** ++"string"++: Command to generate the chain spec. It can't be used in combination with `chain_spec_path`. +- **`default_args?`** ++"string[]"++: An array of arguments to use as default to pass to the command. +- **`default_overrides?`** ++"Override[]"++: An array of overrides to upload to the node. - (pallet_custom::GenesisConfig:: { - initial_counter_value: initial_value, - initial_user_interactions: vec![], - }) - .assimilate_storage(&mut t) - .unwrap(); + ??? child "`Override` interface definition" + ```js + export interface Override { + local_path: string; + remote_name: string; + } + ``` - t.into() -} +- **`random_nominators_count?`** ++"number"++: If set and the stacking pallet is enabled, Zombienet will generate the input quantity of nominators and inject them into the genesis. +- **`max_nominations`** ++"number"++: The max number of nominations allowed by a nominator. Should match the value set in the runtime. Defaults to `24`. +- **`nodes?`** ++"Node[]"++: An array of nodes to spawn. It is further defined in the [Node Configuration](#node-configuration) section. +- **`node_groups?`** ++"NodeGroup[]"++: An array of node groups to spawn. It is further defined in the [Node Group Configuration](#node-group-configuration) section. +- **`total_node_in_group?`** ++"number"++: The total number of nodes in the group. Defaults to `1`. +- **`genesis`** ++"JSON"++: The genesis configuration. +- **`default_delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -// Helper function to create a test externalities with initial user interactions -pub fn new_test_ext_with_interactions( - initial_value: u32, - interactions: Vec<(u64, u32)> -) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` - (pallet_custom::GenesisConfig:: { - initial_counter_value: initial_value, - initial_user_interactions: interactions, - }) - .assimilate_storage(&mut t) - .unwrap(); +#### Node Configuration - t.into() -} -``` +One specific key capable of receiving more subkeys is the `nodes` key. This key is used to define further parameters for the nodes. The available keys: -Key methods used in this step include: +- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). +- **`image?`** ++"string"++: Override default Docker image to use for this node. +- **`command?`** ++"string"++: Override default command to run. +- **`command_with_args?`** ++"string"++: Override default command and arguments. +- **`args?`** ++"string[]"++: Arguments to be passed to the command. +- **`env?`** ++"envVars[]"++: Environment variables to set in the container. -- **[`BuildStorage::build_storage()`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/trait.BuildStorage.html#method.build_storage){target=\_blank}**: Creates the initial storage state. -- **[`assimilate_storage`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/trait.BuildStorage.html#method.assimilate_storage){target=\_blank}**: Merges pallet genesis config into the existing storage. - -You can chain multiple `assimilate_storage` calls to configure multiple pallets. - -## Verify Mock Compilation - -Before proceeding to write tests, ensure your mock runtime compiles correctly: - -```bash -cargo test --package pallet-custom --lib -``` + ??? child "`envVars` interface definition" + ```js + export interface EnvVars { + name: string; + value: string; + } + ``` -This command compiles the test code (including the mock and genesis configuration) without running tests yet. Address any compilation errors before continuing. +- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. +- **`db_snapshot?`** ++"string"++: Database snapshot to use. +- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. -??? code "Complete mock runtime script" + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } + ``` - Here's the complete `mock.rs` file for reference: +- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. - ```rust title="src/mock.rs" - use crate as pallet_custom; - use frame::{ - deps::{ - frame_support::{ derive_impl, traits::ConstU32 }, - sp_io, - sp_runtime::{ traits::IdentityLookup, BuildStorage }, - }, - prelude::*, - }; + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` - type Block = frame_system::mocking::MockBlock; +- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. +- **`validator`** ++"boolean"++: Pass the `--validator` flag to the command. Defaults to `true`. +- **`invulnerable`** ++"boolean"++: If true, add the node to invulnerables in the chain spec. Defaults to `false`. +- **`balance`** ++"number"++: Balance to set in balances for node's account. Defaults to `2000000000000`. +- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. +- **`add_to_bootnodes?`** ++"boolean"++: Add this node to the bootnode list. Defaults to `false`. +- **`ws_port?`** ++"number"++: WS port to use. +- **`rpc_port?`** ++"number"++: RPC port to use. +- **`prometheus_port?`** ++"number"++: Prometheus port to use. +- **`p2p_cert_hash?`** ++"string"++: Libp2p certhash to use with webRTC transport. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. - // Configure a mock runtime to test the pallet. - frame::deps::frame_support::construct_runtime!( - pub enum Test - { - System: frame_system, - CustomPallet: pallet_custom, - } - ); + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` - #[derive_impl(frame_system::config_preludes::TestDefaultConfig)] - impl frame_system::Config for Test { - type Block = Block; - type AccountId = u64; - type Lookup = IdentityLookup; - } +The following configuration file defines a minimal example for the relay chain, including the `nodes` key: - impl pallet_custom::Config for Test { - type RuntimeEvent = RuntimeEvent; - type CounterMaxValue = ConstU32<1000>; - } +=== "TOML" - // Build genesis storage according to the mock runtime. - pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + ```toml title="relaychain-example-nodes.toml" + [relaychain] + default_command = "polkadot" + default_image = "polkadot-debug:master" + chain = "rococo-local" + chain_spec_path = "INSERT_PATH_TO_CHAIN_SPEC" + default_args = ["--chain", "rococo-local"] - (pallet_custom::GenesisConfig:: { - initial_counter_value: 0, - initial_user_interactions: vec![], - }) - .assimilate_storage(&mut t) - .unwrap(); + [[relaychain.nodes]] + name = "alice" + validator = true + balance = 1000000000000 - t.into() - } + [[relaychain.nodes]] + name = "bob" + validator = true + balance = 1000000000000 + # ... - // Helper function to create a test externalities with a specific initial counter value - pub fn new_test_ext_with_counter(initial_value: u32) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); + ``` - (pallet_custom::GenesisConfig:: { - initial_counter_value: initial_value, - initial_user_interactions: vec![], - }) - .assimilate_storage(&mut t) - .unwrap(); +=== "JSON" - t.into() + ```json title="relaychain-example-nodes.json" + { + "relaychain": { + "default_command": "polkadot", + "default_image": "polkadot-debug:master", + "chain": "rococo-local", + "chain_spec_path": "INSERT_PATH_TO_CHAIN-SPEC.JSON", + "default_args": ["--chain", "rococo-local"], + "nodes": [ + { + "name": "alice", + "validator": true, + "balance": 1000000000000 + }, + { + "name": "bob", + "validator": true, + "balance": 1000000000000 + } + ] + } } - // Helper function to create a test externalities with initial user interactions - pub fn new_test_ext_with_interactions( - initial_value: u32, - interactions: Vec<(u64, u32)> - ) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::::default().build_storage().unwrap(); - - (pallet_custom::GenesisConfig:: { - initial_counter_value: initial_value, - initial_user_interactions: interactions, - }) - .assimilate_storage(&mut t) - .unwrap(); - - t.into() - } ``` -## Key Takeaways - -You've successfully created a mock runtime with a genesis configuration for your custom pallet. You can now: - -- Test your pallet without a full runtime. -- Set initial blockchain state for different test scenarios. -- Create different genesis setups for various testing needs. -- Use this minimal setup to test all pallet functionality. - -The mock runtime with a genesis configuration is essential for test-driven development, enabling you to verify logic under different initial conditions before integrating it into the actual parachain runtime. +#### Node Group Configuration -## Where to Go Next +The `node_groups` key defines further parameters for the node groups. The available keys are: -
    +- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). +- **`image?`** ++"string"++: Override default Docker image to use for this node. +- **`command?`** ++"string"++: Override default command to run. +- **`args?`** ++"string[]"++: Arguments to be passed to the command. +- **`env?`** ++"envVars[]"++: Environment variables to set in the container. + + ??? child "`envVars` interface definition" + ```js + export interface EnvVars { + name: string; + value: string; + } + ``` -- Guide __Pallet Unit Testing__ +- **`overrides?`** ++"Override[]"++: Array of overrides definitions. - --- + ??? child "`Override` interface definition" + ```js + export interface Override { + local_path: string; + remote_name: string; + } + ``` - Learn to write comprehensive unit tests for your pallet using the mock runtime you just created. +- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. +- **`db_snapshot?`** ++"string"++: Database snapshot to use. +- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. - [:octicons-arrow-right-24: Continue](/parachains/customize-runtime/pallet-development/pallet-testing/) + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } + ``` -
    +- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` ---- +- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. +- **`count`** ++"number | string"++: Number of nodes to launch for this group. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -Page Title: Networks + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/networks/ -- Summary: Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. +The following configuration file defines a minimal example for the relay chain, including the `node_groups` key: -# Networks +=== "TOML" -## Introduction - -The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's various networks and explain how they fit into the development workflow. - -## Network Overview - -Polkadot's development process is structured to ensure new features and upgrades are rigorously tested before being deployed on live production networks. The progression follows a well-defined path, starting from local environments and advancing through TestNets, ultimately reaching the Polkadot MainNet. The diagram below outlines the typical progression of the Polkadot development cycle: - -``` mermaid -flowchart LR - id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] - id1[Local] --> id3[Paseo] --> id5[Polkadot] -``` - -This flow ensures developers can thoroughly test and iterate without risking real tokens or affecting production networks. Testing tools like [Chopsticks](#chopsticks) and various TestNets make it easier to experiment safely before releasing to production. - -A typical journey through the Polkadot core protocol development process might look like this: - -1. **Local development node**: Development starts in a local environment, where developers can create, test, and iterate on upgrades or new features using a local development node. This stage allows rapid experimentation in an isolated setup without any external dependencies. - -2. **Westend**: After testing locally, upgrades are deployed to [Westend](#westend), Polkadot's primary TestNet. Westend simulates real-world conditions without using real tokens, making it the ideal place for rigorous feature testing before moving on to production networks. - -3. **Kusama**: Once features have passed extensive testing on Westend, they move to Kusama, Polkadot's experimental and fast-moving "canary" network. Kusama operates as a high-fidelity testing ground with actual economic incentives, giving developers insights into how their features will perform in a real-world environment. - -4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network. - - In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. - -5. **Paseo**: For parachain and dApp developers, Paseo serves as a community-run TestNet that mirrors Polkadot's runtime. Like Westend for core protocol development, Paseo provides a testing ground for parachain development without affecting live networks. - -!!!note - The Rococo TestNet deprecation date was October 14, 2024. Teams should use Westend for Polkadot protocol and feature testing and Paseo for chain development-related testing. - -## Polkadot Development Networks - -Development and testing are crucial to building robust dApps and parachains and performing network upgrades within the Polkadot ecosystem. To achieve this, developers can leverage various networks and tools that provide a risk-free environment for experimentation and validation before deploying features to live networks. These networks help avoid the costs and risks associated with real tokens, enabling testing for functionalities like governance, cross-chain messaging, and runtime upgrades. - -## Kusama Network - -Kusama is the experimental version of Polkadot, designed for developers who want to move quickly and test their applications in a real-world environment with economic incentives. Kusama serves as a production-grade testing ground where developers can deploy features and upgrades with the pressure of game theory and economics in mind. It mirrors Polkadot but operates as a more flexible space for innovation. - -The native token for Kusama is KSM. For more information about KSM, visit the [Native Assets](https://wiki.polkadot.com/kusama/kusama-getting-started/){target=\_blank} page. - -## Test Networks - -The following test networks provide controlled environments for testing upgrades and new features. TestNet tokens are available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}. - -### Westend - -Westend is Polkadot's primary permanent TestNet. Unlike temporary test networks, Westend is not reset to the genesis block, making it an ongoing environment for testing Polkadot core features. Managed by Parity Technologies, Westend ensures that developers can test features in a real-world simulation without using actual tokens. - -The native token for Westend is WND. More details about WND can be found on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_2){target=\_blank} page. - -### Paseo - -[Paseo](https://github.com/paseo-network){target=\_blank} is a community-managed TestNet designed for parachain and dApp developers. It mirrors Polkadot's runtime and is maintained by Polkadot community members. Paseo provides a dedicated space for parachain developers to test their applications in a Polkadot-like environment without the risks associated with live networks. - -The native token for Paseo is PAS. Additional information on PAS is available on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_1){target=\_blank} page. - -## Local Test Networks - -Local test networks are an essential part of the development cycle for blockchain developers using the Polkadot SDK. They allow for fast, iterative testing in controlled, private environments without connecting to public TestNets. Developers can quickly spin up local instances to experiment, debug, and validate their code before deploying to larger TestNets like Westend or Paseo. Two key tools for local network testing are Zombienet and Chopsticks. - -### Zombienet - -[Zombienet](https://github.com/paritytech/zombienet){target=\_blank} is a flexible testing framework for Polkadot SDK-based blockchains. It enables developers to create and manage ephemeral, short-lived networks. This feature makes Zombienet particularly useful for quick iterations, as it allows you to run multiple local networks concurrently, mimicking different runtime conditions. Whether you're developing a parachain or testing your custom blockchain logic, Zombienet gives you the tools to automate local testing. - -Key features of Zombienet include: - -- Creating dynamic, local networks with different configurations. -- Running parachains and relay chains in a simulated environment. -- Efficient testing of network components like cross-chain messaging and governance. - -Zombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets. - -### Chopsticks - -[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\_blank} is a tool designed to create forks of Polkadot SDK-based blockchains, allowing developers to interact with network forks as part of their testing process. This capability makes Chopsticks a powerful option for testing upgrades, runtime changes, or cross-chain applications in a forked network environment. - -Key features of Chopsticks include: - -- Forking live Polkadot SDK-based blockchains for isolated testing. -- Simulating cross-chain messages in a private, controlled setup. -- Debugging network behavior by interacting with the fork in real-time. - -Chopsticks provides a controlled environment for developers to safely explore the effects of runtime changes. It ensures that network behavior is tested and verified before upgrades are deployed to live networks. - - ---- - -Page Title: Node and Runtime - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/node-and-runtime/ -- Summary: Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. - -# Node and Runtime - -## Introduction - -Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network. - -Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. - -If the system were a monolithic protocol, any modification would require updating the entire system. Instead, Polkadot achieves true upgradeability by defining an immutable meta-protocol (the client) and a protocol (the runtime) that can be upgraded independently. - -This separation gives the [Polkadot Relay Chain](/polkadot-protocol/architecture/polkadot-chain){target=\_blank} and all connected [parachains](/polkadot-protocol/architecture/parachains){target=\_blank} an evolutionary advantage over other blockchain platforms. - -## Architectural Principles - -The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: - -- Client (Meta-protocol): - - Handles the foundational infrastructure of the blockchain. - - Manages runtime execution, networking, consensus, and other off-chain components. - - Provides an immutable base layer that ensures network stability. - - Upgradable only through hard forks. - -- Runtime (Protocol): - - Defines the blockchain's state transition logic. - - Determines the specific rules and behaviors of the blockchain. - - Compiled to WebAssembly (Wasm) for platform-independent execution. - - Capable of being upgraded without network-wide forking. - -### Advantages of this Architecture - -- **Forkless upgrades**: Runtime can be updated without disrupting the entire network. -- **Modularity**: Clear separation allows independent development of client and runtime. -- **Flexibility**: Enables rapid iteration and evolution of blockchain logic. -- **Performance**: WebAssembly compilation provides efficient, cross-platform execution. - -## Node (Client) - -The node, also known as the client, is the core component responsible for executing the Wasm runtime and orchestrating various essential blockchain components. It ensures the correct execution of the state transition function and manages multiple critical subsystems, including: - -- **Wasm execution**: Runs the blockchain runtime, which defines the state transition rules. -- **Database management**: Stores blockchain data. -- **Networking**: Facilitates peer-to-peer communication, block propagation, and transaction gossiping. -- **Transaction pool (Mempool)**: Manages pending transactions before they are included in a block. -- **Consensus mechanism**: Ensures agreement on the blockchain state across nodes. -- **RPC services**: Provides external interfaces for applications and users to interact with the node. - -## Runtime - -The runtime is more than just a set of rules. It's the fundamental logic engine that defines a blockchain's entire behavior. In Polkadot SDK-based blockchains, the runtime represents a complete, self-contained description of the blockchain's state transition function. - -### Characteristics - -The runtime is distinguished by three key characteristics: - -- **Business logic**: Defines the complete application-specific blockchain behavior. -- **WebAssembly compilation**: Ensures platform-independent, secure execution. -- **On-chain storage**: Stored within the blockchain's state, allowing dynamic updates. - -### Key Functions - -The runtime performs several critical functions, such as: - -- Define state transition rules. -- Implement blockchain-specific logic. -- Manage account interactions. -- Control transaction processing. -- Define governance mechanisms. -- Handle custom pallets and modules. - -## Communication Between Node and Runtime - -The client and runtime communicate exclusively using [SCALE-encoded](/polkadot-protocol/parachain-basics/data-encoding){target=\_blank} communication. This ensures efficient and compact data exchange between the two components. - -### Runtime APIs - -The Runtime API consists of well-defined functions and constants a client assumes are implemented in the Runtime Wasm blob. These APIs enable the client to interact with the runtime to execute blockchain operations and retrieve information. The client invokes these APIs to: - -- Build, execute, and finalize blocks. -- Access metadata. -- Access consensus related information. -- Handle transaction execution. - -### Host Functions - -During execution, the runtime can access certain external client functionalities via host functions. The specific functions the client exposes allow the runtime to perform operations outside the WebAssembly domain. Host functions enable the runtime to: - -- Perform cryptographic operations. -- Access the current blockchain state. -- Handle storage modifications. -- Allocate memory. - - ---- - -Page Title: Obtain Coretime - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md -- Canonical (HTML): https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/ -- Summary: Learn how to obtain coretime for block production with this guide, covering both on-demand and bulk options for smooth operations. - -# Obtain Coretime - -## Introduction - -After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime. - -There are two primary ways to obtain coretime: - -- **[On-demand coretime](#order-on-demand-coretime)**: Purchase coretime on a block-by-block basis, ideal for variable or unpredictable workloads. -- **[Bulk coretime](#purchase-bulk-coretime)**: Obtain a core or portion of a core for an extended period (up to 28 days), requiring renewal upon lease expiration. - -In this tutorial, you will: - -- Understand the different coretime options available. -- Learn how to purchase a core via bulk coretime. -- Assign your parachain to a core for block production. -- Explore on-demand coretime as an alternative approach. - -## Prerequisites - -Before proceeding, ensure you have the following: - -- A parachain ID reserved on Paseo. -- A properly configured chain specification file (both plain and raw versions). -- A registered parathread with the correct genesis state and runtime. -- A synced collator node running and connected to the Paseo relay chain. -- [PAS tokens](https://faucet.polkadot.io/?parachain=1005){target=\_blank} in your account on the Coretime Chain for transaction fees. - -If you haven't completed these prerequisites, start by referring to the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\_blank} tutorial. - -## Order On-Demand Coretime - -On-demand coretime allows you to purchase validation resources on a per-block basis. This approach is useful when you don't need continuous block production or want to test your parachain before committing to bulk coretime. - -### On-Demand Extrinsics - -There are two extrinsics available for ordering on-demand coretime: - -- **[`onDemand.placeOrderAllowDeath`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/on_demand/pallet/struct.Pallet.html#method.place_order_allow_death){target=\_blank}**: Will [reap](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank} the account once the provided funds are depleted. -- **[`onDemand.placeOrderKeepAlive`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/on_demand/pallet/struct.Pallet.html#method.place_order_keep_alive){target=\_blank}**: Includes a check to prevent reaping the account, ensuring it remains alive even if funds run out. - -### Place an On-Demand Order - -To place an on-demand coretime order, follow these steps: - -1. Open the [Polkadot.js Apps interface connected to the Polkadot TestNet (Paseo)](https://polkadot.js.org/apps/?rpc=wss://paseo.dotters.network){target=\_blank}. - -2. Navigate to **Developer > Extrinsics** in the top menu. - -3. Select the account that registered your parachain ID. - -4. From the **submit the following extrinsic** dropdown, select **onDemand** and then choose **placeOrderAllowDeath** as the extrinsic. - -5. Configure the parameters: - - - **maxAmount**: The maximum amount of tokens you're willing to spend (e.g., `1000000000000`). This value may vary depending on network conditions. - - **paraId**: Your reserved parachain ID (e.g., `4508`). - -6. Review the transaction details and click **Submit Transaction**. - -![Placing an on-demand order for coretime](/images/parachains/launch-a-parachain/obtain-coretime/obtain-coretime-01.webp) - -Upon successful submission, your parachain will produce a new block. You can verify this by checking your collator node logs, which should display output confirming block production. - -!!!note - Each successful on-demand extrinsic will trigger one block production cycle. For continuous block production, you'll need to place multiple orders or consider bulk coretime. - -## Purchase Bulk Coretime - -Bulk coretime offers a cost-effective way to maintain continuous block production. It lets you reserve a core for up to 28 days and renew it as needed. - -You can purchase and manage cores on the [Coretime Chain](https://wiki.polkadot.com/learn/learn-system-chains/#coretime-chain){target=\_blank}, a system parachain that runs the [`pallet_broker`](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank} to handle core sales, allocation, and renewal across the Polkadot ecosystem. - -!!!tip - Paseo has a unique process for obtaining coretime cores. Refer to the [PAS-10 Onboard Paras Coretime](https://github.com/paseo-network/paseo-action-submission/blob/main/pas/PAS-10-Onboard-paras-coretime.md#summary){target=\_blank} guide for detailed instructions. - -This tutorial shows you how to purchase bulk coretime using the [RegionX Coretime Marketplace](https://app.regionx.tech){target=\_blank}, a user-friendly interface for buying and managing cores on both the Polkadot TestNet and production networks. - -![RegionX home page with Wallet connected](/images/parachains/launch-a-parachain/obtain-coretime/obtain-coretime-02.webp) - -### Connect Your Wallet to RegionX - -1. Visit the [RegionX App](https://app.regionx.tech){target=\_blank}. - -2. Click the **Connect Wallet** button in the upper right corner. - -3. Select your wallet provider and approve the connection. - -### Obtain Coretime Chain Funds - -To purchase a core, you need funds on the Coretime Chain. You can fund your account directly on the Coretime Chain using the Polkadot Faucet: - -1. Visit the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=0){target=\_blank}. - -2. Select the **Coretime (Paseo)** network from the dropdown menu. - -3. Paste your wallet address in the input field. - -4. Click **Get some PASs** to receive 5000 PAS tokens. - -!!!note - The Polkadot Faucet has a daily limit of 5,000 PAS tokens per account. If you need more tokens than this limit allows, you have two options: - - - Return to the faucet on consecutive days to accumulate additional tokens. - - Create additional accounts, fund each one separately, and then transfer the tokens to your primary account that will be making the bulk coretime purchase. - - Alternatively, to expedite the process, you can send a message to the [Paseo Support channel](https://matrix.to/#/#paseo-testnet-support:parity.io){target=\_blank} on Matrix, and the Paseo team will assist you in funding your account. - -### Purchase a Core - -1. From the RegionX home page, ensure the correct network is selected using the network switch in the top right corner (set to **Paseo**). - -2. Review the information displayed on the home page, including: - - **Cores Remaining**: Number of available cores - - **Cores Offered**: Total cores in the current sale - - **Current price**: The price per core in PAS tokens - - **Auction Phase Status**: Current phase and progress - -3. Click the **Purchase New Core** button displayed on the page. - -4. A modal will appear detailing the transaction details and fees. Review the information carefully. - -5. Click **Ok** and sign the transaction using your connected wallet. - -6. Wait for the transaction to be confirmed on-chain. - -### Verify Your Purchase - -1. Once the transaction is confirmed, navigate to [**My Regions**](https://app.regionx.tech/regions){target=\_blank} from the left menu. - -2. You should see your newly purchased core listed in your dashboard. - -Congratulations! You've successfully purchased a core using RegionX. - -### Assign Your Parachain to the Core - -With your core purchased, you now need to assign your parachain to it for block production: - -1. From the **My Regions** page, click on your core to select it. - -2. Click the **Assign** option from the left-hand menu. - -3. A modal will appear, allowing you to add a new task. - -4. Click **Add Task** and enter the following information: - - - **Parachain ID**: Your reserved parachain identifier - - **Project Name**: The name of your parachain project - -5. Click **Add Task** to proceed. - -6. Select your parachain task from the list. - -7. Set the core's **Finality** setting: - - - **Provisional**: Allows interlacing and partitioning of the core, but the region cannot be renewed as-is. - - **Final**: Prevents modification of the core but allows renewal. Choose this if you plan to renew the core. - -8. Sign and submit the transaction. - -Once confirmed, your parachain will be assigned to the core and should begin producing blocks (provided your collator is running and synced with the relay chain). - -## Next Steps - -Your parachain is now set up for block production. Consider the following: - -- **Monitor your collator**: Keep your collator node running and monitor its performance. -- **Plan coretime renewal**: If using bulk coretime, plan to renew your core before the current lease expires. -- **Explore runtime upgrades**: Once comfortable with your setup, explore how to upgrade your parachain's runtime without interrupting block production. - - ---- - -Page Title: On-Chain Governance Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md -- Canonical (HTML): https://docs.polkadot.com/reference/governance/ -- Summary: Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. - -# On-Chain Governance - -## Introduction - -Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model. - -This guide will explain the principles and structure of OpenGov and walk you through its key components, such as Origins, Tracks, and Delegation. You will learn about improvements over earlier governance systems, including streamlined voting processes and enhanced stakeholder participation. - -With OpenGov, Polkadot achieves a flexible, scalable, and democratic governance framework that allows multiple proposals to proceed simultaneously, ensuring the network evolves in alignment with its community's needs. - -## Governance Evolution - -Polkadot’s governance journey began with [Governance V1](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#governance-summary){target=\_blank}, a system that proved effective in managing treasury funds and protocol upgrades. However, it faced limitations, such as: - -- Slow voting cycles, causing delays in decision-making. -- Inflexibility in handling multiple referendums, restricting scalability. - -To address these challenges, Polkadot introduced OpenGov, a governance model designed for greater inclusivity, efficiency, and scalability. OpenGov replaces the centralized structures of Governance V1, such as the Council and Technical Committee, with a fully decentralized and dynamic framework. - -For a full comparison of the historic and current governance models, visit the [Gov1 vs. Polkadot OpenGov](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#gov1-vs-polkadot-opengov){target=\_blank} section of the Polkadot Wiki. - -## OpenGov Key Features - -OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: - -- **Decentralization**: Shifts all decision-making power to the public, ensuring a more democratic process. -- **Enhanced delegation**: Allows users to delegate their votes to trusted experts across specific governance tracks. -- **Simultaneous referendums**: Multiple proposals can progress at once, enabling faster decision-making. -- **Polkadot Technical Fellowship**: A broad, community-driven group replacing the centralized Technical Committee. - -This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. - -## Origins and Tracks - -In OpenGov, origins and tracks are central to managing proposals and votes. - -- **Origin**: Determines the authority level of a proposal (e.g., Treasury, Root) which decides the track of all referendums from that origin. -- **Track**: Define the procedural flow of a proposal, such as voting duration, approval thresholds, and enactment timelines. - -Developers must be aware that referendums from different origins and tracks will take varying amounts of time to reach approval and enactment. The [Polkadot Technical Fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} has the option to shorten this timeline by whitelisting a proposal and allowing it to be enacted through the [Whitelist Caller](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#whitelisted-caller){target=\_blank} origin. - -Visit [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#origins-and-tracks){target=\_blank} for details on current origins and tracks, associated terminology, and parameters. - -## Referendums - -In OpenGov, anyone can submit a referendum, fostering an open and participatory system. The timeline for a referendum depends on the privilege level of the origin with more significant changes offering more time for community voting and participation before enactment. - -The timeline for an individual referendum includes four distinct periods: - -- **Lead-in**: A minimum amount of time to allow for community participation, available room in the origin, and payment of the decision deposit. Voting is open during this period. -- **Decision**: Voting continues. -- **Confirmation**: Referendum must meet [approval and support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} criteria during entire period to avoid rejection. -- **Enactment**: Changes approved by the referendum are executed. - -### Vote on Referendums - -Voters can vote with their tokens on each referendum. Polkadot uses a voluntary token locking mechanism, called conviction voting, as a way for voters to increase their voting power. A token holder signals they have a stronger preference for approving a proposal based upon their willingness to lock up tokens. Longer voluntary token locks are seen as a signal of continual approval and translate to increased voting weight. - -See [Voting on a Referendum](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank} for a deeper look at conviction voting and related token locks. - -### Delegate Voting Power - -The OpenGov system also supports multi-role delegations, allowing token holders to assign their voting power on different tracks to entities with expertise in those areas. - -For example, if a token holder lacks the technical knowledge to evaluate proposals on the [Root track](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#root){target=\_blank}, they can delegate their voting power for that track to an expert they trust to vote in the best interest of the network. This ensures informed decision-making across tracks while maintaining flexibility for token holders. - -Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. - -### Cancel a Referendum - -Polkadot OpenGov has two origins for rejecting ongoing referendums: - -- [**Referendum Canceller**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-canceller){target=\_blank}: Cancels an active referendum when non-malicious errors occur and refunds the deposits to the originators. -- [**Referendum Killer**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-killer){target=\_blank}: Used for urgent, malicious cases this origin instantly terminates an active referendum and slashes deposits. - -See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. - -## Additional Resources - -- **[Democracy pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/democracy/src){target=\_blank}**: Handles administration of general stakeholder voting. -- **[Gov2: Polkadot’s Next Generation of Decentralised Governance](https://medium.com/polkadot-network/gov2-polkadots-next-generation-of-decentralised-governance-4d9ef657d11b){target=\_blank}**: Medium article by Gavin Wood. -- **[Polkadot Direction](https://matrix.to/#/#Polkadot-Direction:parity.io){target=\_blank}**: Matrix Element client. -- **[Polkassembly](https://polkadot.polkassembly.io/){target=\_blank}**: OpenGov dashboard and UI. -- **[Polkadot.js Apps Governance](https://polkadot.js.org/apps/#/referenda){target=\_blank}**: Overview of active referendums. - - ---- - -Page Title: Opening HRMP Channels Between Parachains - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md -- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/ -- Summary: Learn how to open HRMP channels between parachains on Polkadot. Discover the step-by-step process for establishing uni- and bidirectional communication. - -# Opening HRMP Channels Between Parachains - -## Introduction - -For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required: - -1. **Channel request**: The parachain that wants to open an HRMP channel must make a request to the parachain it wishes to have an open channel with. -2. **Channel acceptance**: The other parachain must then accept this request to complete the channel establishment. - -This process results in a unidirectional HRMP channel, where messages can flow in only one direction between the two parachains. - -An additional HRMP channel must be established in the opposite direction to enable bidirectional communication. This requires repeating the request and acceptance process but with the parachains reversing their roles. - -Once both unidirectional channels are established, the parachains can send messages back and forth freely through the bidirectional HRMP communication channel. - -## Prerequisites - -Before proceeding, ensure you meet the following requirements: - -- Blockchain network with a relay chain and at least two connected parachains. -- Wallet with sufficient funds to execute transactions on the participant chains. - -## Procedure to Initiate an HRMP Channel - -This example will demonstrate how to open a channel between parachain 2500 and parachain 2600, using Rococo Local as the relay chain. - -### Fund Sender Sovereign Account - - -The [sovereign account](https://github.com/polkadot-fellows/xcm-format/blob/10726875bd3016c5e528c85ed6e82415e4b847d7/README.md?plain=1#L50){target=_blank} for parachain 2500 on the relay chain must be funded so it can take care of any XCM transact fees. - -Use [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} UI to connect to the relay chain and transfer funds from your account to the parachain 2500 sovereign account. - -![](/images/parachains/interoperability/channels-common/channels-01.webp) - -??? note "Calculating Parachain Sovereign Account" - To generate the sovereign account address for a parachain, you'll need to follow these steps: - - 1. Determine if the parachain is an "up/down" chain (parent or child) or a "sibling" chain: - - - Up/down chains use the prefix `0x70617261` (which decodes to `b"para"`). - - Sibling chains use the prefix `0x7369626c` (which decodes to `b"sibl"`). - - 2. Calculate the u32 scale encoded value of the parachain ID: - - - Parachain 2500 would be encoded as `c4090000`. - - 3. Combine the prefix and parachain ID encoding to form the full sovereign account address: - - The sovereign account of parachain 2500 in relay chain will be `0x70617261c4090000000000000000000000000000000000000000000000000000` - and the SS58 format of this address is `5Ec4AhPSY2GEE4VoHUVheqv5wwq2C1HMKa7c9fVJ1WKivX1Y`. - - To perform this conversion, you can also use the **"Para ID" to Address** section in [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/){target=_blank}. - -### Create Channel Opening Extrinsic - -1. In Polkadot.js Apps, connect to the relay chain, navigate to the **Developer** dropdown and select the **Extrinsics** option. - - ![](/images/parachains/interoperability/channels-common/channels-02.webp) - -2. Construct an `hrmpInitOpenChannel` extrinsic call: - - 1. Select the **`hrmp`** pallet. - 2. Choose the **`hrmpInitOpenChannel`** extrinsic. - 3. Fill in the parameters: - - **`recipient`**: Parachain ID of the target chain (in this case, 2600). - - **`proposedMaxCapacity`**: Max number of messages that can be pending in the channel at once. - - **`proposedMaxMessageSize`**: Max message size that could be put into the channel. - 4. Copy the encoded call data. - - ![](/images/parachains/interoperability/channels-between-parachains/parachains-01.webp) - - The encoded call data for opening a channel with parachain 2600 is `0x3c00280a00000800000000001000`. - -### Craft and Submit the XCM Message from the Sender - -To initiate the HRMP channel opening process, you need to create an XCM message that includes the encoded `hrmpInitOpenChannel` call data from the previous step. This message will be sent from your parachain to the relay chain. - -This example uses the `sudo` pallet to dispatch the extrinsic. Verify the XCM configuration of the parachain you're working with and ensure you're using an origin with the necessary privileges to execute the `polkadotXcm.send` extrinsic. - -The XCM message should contain the following instructions: - -- **`WithdrawAsset`**: Withdraws assets from the origin's ownership and places them in the Holding Register. -- **`BuyExecution`**: Pays for the execution of the current message using the assets in the Holding Register. -- **`Transact`**: Execute the encoded transaction call. -- **`RefundSurplus`**: Increases the Refunded Weight Register to the value of the Surplus Weight Register, attempting to reclaim any excess fees paid via BuyExecution. -- **`DepositAsset`**: Subtracts assets from the Holding Register and deposits equivalent on-chain assets under the specified beneficiary's ownership. - -!!!note - For more detailed information about XCM's functionality, complexities, and instruction set, refer to the [xcm-format](https://github.com/polkadot-fellows/xcm-format){target=_blank} documentation. - -In essence, this process withdraws funds from the parachain's sovereign account to the XCVM Holding Register, then uses these funds to purchase execution time for the XCM `Transact` instruction, executes `Transact`, refunds any unused execution time and deposits any remaining funds into a specified account. - -To send the XCM message to the relay chain, connect to parachain 2500 in Polkadot.js Apps. Fill in the required parameters as shown in the image below, ensuring that you: - -1. Replace the **`call`** field with your encoded `hrmpInitOpenChannel` call data from the previous step. -2. Use the correct beneficiary information. -3. Click the **Submit Transaction** button to dispatch the XCM message to the relay chain. - -![](/images/parachains/interoperability/channels-between-parachains/parachains-02.webp) - -!!! note - The exact process and parameters for submitting this XCM message may vary depending on your specific parachain and relay chain configurations. Always refer to the most current documentation for your particular network setup. - -After submitting the XCM message to initiate the HRMP channel opening, you should verify that the request was successful. Follow these steps to check the status of your channel request: - -1. Using Polkadot.js Apps, connect to the relay chain and navigate to the **Developer** dropdown, then select the **Chain state** option. - - ![](/images/parachains/interoperability/channels-common/channels-03.webp) - -2. Query the HRMP open channel requests: - - 1. Select **`hrmp`**. - 2. Choose the **`hrmpOpenChannelRequests`** call. - 3. Click the **+** button to execute the query. - 4. Check the status of all pending channel requests. - - ![](/images/parachains/interoperability/channels-between-parachains/parachains-03.webp) - -If your channel request was successful, you should see an entry for your parachain ID in the list of open channel requests. This confirms that your request has been properly registered on the relay chain and is awaiting acceptance by the target parachain. - -## Procedure to Accept an HRMP Channel - -For the channel to be fully established, the target parachain must accept the channel request by submitting an XCM message to the relay chain. - -### Fund Receiver Sovereign Account - -Before proceeding, ensure that the sovereign account of parachain 2600 on the relay chain is funded. This account will be responsible for covering any XCM transact fees. -To fund the account, follow the same process described in the previous section, [Fund Sovereign Account](#fund-sender-sovereign-account). - -### Create Channel Accepting Extrinsic - -1. In Polkadot.js Apps, connect to the relay chain, navigate to the **Developer** dropdown and select the **Extrinsics** option. - - ![](/images/parachains/interoperability/channels-common/channels-02.webp) - -2. Construct an `hrmpAcceptOpenChannel` extrinsic call: - - 1. Select the **`hrmp`** pallet. - 2. Choose the **`hrmpAcceptOpenChannel`** extrinsic. - 3. Fill in the parameters: - - **`sender`**: Parachain ID of the requesting chain (in this case, 2500). - 4. Copy the encoded call data. - - ![](/images/parachains/interoperability/channels-between-parachains/parachains-04.webp) - - The encoded call data for accepting a channel with parachain 2500 should be `0x3c01c4090000`. - -### Craft and Submit the XCM Message from the Receiver - -To accept the HRMP channel opening, you need to create and submit an XCM message that includes the encoded `hrmpAcceptOpenChannel` call data from the previous step. This process is similar to the one described in the previous section, [Craft and Submit the XCM Message](#craft-and-submit-the-xcm-message-from-the-sender), with a few key differences: - -- Use the encoded call data for `hrmpAcceptOpenChannel` obtained in step 2 of this section. -- In the last XCM instruction (DepositAsset), set the beneficiary to parachain 2600's sovereign account to receive any surplus funds. - -To send the XCM message to the relay chain, connect to parachain 2600 in Polkadot.js Apps. Fill in the required parameters as shown in the image below, ensuring that you: - -1. Replace the **`call`** field with your encoded `hrmpAcceptOpenChannel` call data from the previous step. -2. Use the correct beneficiary information. -3. Click the **Submit Transaction** button to dispatch the XCM message to the relay chain. - -![](/images/parachains/interoperability/channels-between-parachains/parachains-05.webp) - -After submitting the XCM message to accept the HRMP channel opening, verify that the channel has been set up correctly. - -1. Using Polkadot.js Apps, connect to the relay chain and navigate to the **Developer** dropdown, then select the **Chain state** option. - - ![](/images/parachains/interoperability/channels-common/channels-01.webp) - -2. Query the HRMP channels: - - 1. Select **`hrmp`**. - 2. Choose the **`hrmpChannels`** call. - 3. Click the **+** button to execute the query. - 4. Check the status of the opened channel. - - ![](/images/parachains/interoperability/channels-between-parachains/parachains-06.webp) - -If the channel has been successfully established, you should see the channel details in the query results. - -By following these steps, you will have successfully accepted the HRMP channel request and established a unidirectional channel between the two parachains. - -!!! note - Remember that for full bidirectional communication, you'll need to repeat this process in the opposite direction, with parachain 2600 initiating a channel request to parachain 2500. - - ---- - -Page Title: Opening HRMP Channels with System Parachains - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md -- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/ -- Summary: Learn how to open HRMP channels with Polkadot system parachains. Discover the process for establishing bi-directional communication using a single XCM message. - -# Opening HRMP Channels with System Parachains - -## Introduction - -While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach. - -System parachains are specialized chains that provide core functionality to the Polkadot network. Examples include Asset Hub for cross-chain asset transfers and Bridge Hub for connecting to external networks. Given their critical role, establishing communication channels with these system parachains has been optimized for efficiency and ease of use. - -Any parachain can establish a bidirectional channel with a system chain through a single operation, requiring just one XCM message from the parachain to the relay chain. - -## Prerequisites - -To successfully complete this process, you'll need to have the following in place: - -- Access to a blockchain network consisting of: - - A relay chain - - A parachain - - An Asset Hub system chain -- A wallet containing enough funds to cover transaction fees on each of the participating chains. - -## Procedure to Establish an HRMP Channel - -This guide demonstrates opening an HRMP channel between parachain 2500 and system chain Asset Hub (parachain 1000) on the Rococo Local relay chain. - -### Fund Parachain Sovereign Account - -The [sovereign account](https://github.com/polkadot-fellows/xcm-format/blob/10726875bd3016c5e528c85ed6e82415e4b847d7/README.md?plain=1#L50){target=_blank} for parachain 2500 on the relay chain must be funded so it can take care of any XCM transact fees. - -Use [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} UI to connect to the relay chain and transfer funds from your account to the parachain 2500 sovereign account. - -![](/images/parachains/interoperability/channels-common/channels-01.webp) - -??? note "Calculating Parachain Sovereign Account" - To generate the sovereign account address for a parachain, you'll need to follow these steps: - - 1. Determine if the parachain is an "up/down" chain (parent or child) or a "sibling" chain: - - - Up/down chains use the prefix `0x70617261` (which decodes to `b"para"`). - - Sibling chains use the prefix `0x7369626c` (which decodes to `b"sibl"`). - - 2. Calculate the u32 scale encoded value of the parachain ID: - - - Parachain 2500 would be encoded as `c4090000`. - - 3. Combine the prefix and parachain ID encoding to form the full sovereign account address: - - The sovereign account of parachain 2500 in relay chain will be `0x70617261c4090000000000000000000000000000000000000000000000000000` - and the SS58 format of this address is `5Ec4AhPSY2GEE4VoHUVheqv5wwq2C1HMKa7c9fVJ1WKivX1Y`. - - To perform this conversion, you can also use the **"Para ID" to Address** section in [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/){target=\_blank}. - -### Create Establish Channel with System Extrinsic - -1. In Polkadot.js Apps, connect to the relay chain, navigate to the **Developer** dropdown and select the **Extrinsics** option. - - ![](/images/parachains/interoperability/channels-common/channels-02.webp) - -2. Construct an `establish_channel_with_system` extrinsic call: - - 1. Select the **`hrmp`** pallet. - 2. Choose the **`establish_channel_with_system`** extrinsic. - 3. Fill in the parameters: - - **`target_system_chain`**: Parachain ID of the target system chain (in this case, 1000). - 4. Copy the encoded call data. - ![](/images/parachains/interoperability/channels-with-system-parachains/system-parachains-01.webp) - - The encoded call data for establishing a channel with system parachain 1000 should be `0x3c0ae8030000`. - -### Craft and Submit the XCM Message - -Connect to parachain 2500 using Polkadot.js Apps to send the XCM message to the relay chain. Input the necessary parameters as illustrated in the image below. Make sure to: - -1. Insert your previously encoded `establish_channel_with_system` call data into the **`call`** field. -2. Provide beneficiary details. -3. Dispatch the XCM message to the relay chain by clicking the **Submit Transaction** button. - -![](/images/parachains/interoperability/channels-with-system-parachains/system-parachains-02.webp) - -!!! note - The exact process and parameters for submitting this XCM message may vary depending on your specific parachain and relay chain configurations. Always refer to the most current documentation for your particular network setup. - -After successfully submitting the XCM message to the relay chain, two [`HrmpSystemChannelOpened`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/hrmp/pallet/enum.Event.html#variant.HrmpSystemChannelOpened){target=\_blank} events are emitted, indicating that the channels are now present in storage under [`HrmpOpenChannelRequests`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/hrmp/pallet/storage_types/struct.HrmpOpenChannelRequests.html){target=\_blank}. However, the channels are not actually set up until the start of the next session, at which point bidirectional communication between parachain 2500 and system chain 1000 is established. - -To verify this, wait for the next session and then follow these steps: - -1. Using Polkadot.js Apps, connect to the relay chain and navigate to the **Developer** dropdown, then select **Chain state**. - - ![](/images/parachains/interoperability/channels-common/channels-03.webp) - -2. Query the HRMP channels: - - 1. Select **`hrmp`** from the options. - 2. Choose the **`hrmpChannels`** call. - 3. Click the **+** button to execute the query. - - ![](/images/parachains/interoperability/channels-with-system-parachains/system-parachains-03.webp) - -3. Examine the query results. You should see output similar to the following: - - ```json - [ - [ - [ - { - "sender": 1000, - "recipient": 2500 - } - ], - { - "maxCapacity": 8, - "maxTotalSize": 8192, - "maxMessageSize": 1048576, - "msgCount": 0, - "totalSize": 0, - "mqcHead": null, - "senderDeposit": 0, - "recipientDeposit": 0 - } - ], - [ - [ - { - "sender": 2500, - "recipient": 1000 - } - ], - { - "maxCapacity": 8, - "maxTotalSize": 8192, - "maxMessageSize": 1048576, - "msgCount": 0, - "totalSize": 0, - "mqcHead": null, - "senderDeposit": 0, - "recipientDeposit": 0 - } - ] - ] - - ``` - -The output confirms the successful establishment of two HRMP channels: - -- From chain 1000 (system chain) to chain 2500 (parachain). -- From chain 2500 (parachain) to chain 1000 (system chain). - -This bidirectional channel enables direct communication between the system chain and the parachain, allowing for cross-chain message passing. - - ---- - -Page Title: Overview of FRAME - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md -- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ -- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. - -# Customize Your Runtime - -## Introduction - -A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. - -This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. - -## Understanding Your Runtime - -The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. - -Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. - -## Runtime Architecture - -The following diagram shows how FRAME components work together to form your runtime: - -![](/images/parachains/customize-runtime/index/frame-overview-01.webp) - -The main components are: - -- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. -- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. -- **`frame_system`**: Provides core runtime primitives and storage. -- **`frame_support`**: Utilities and macros that simplify pallet development. - -## Building Blocks: Pallets - -[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. - -A pallet can implement virtually any blockchain feature you need: - -- Expose new transactions that users can submit. -- Store data on-chain. -- Enforce business rules and validation logic. -- Emit events to notify users of state changes. -- Handle errors gracefully. - -### Pre-Built Pallets vs. Custom Pallets - -FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. - -However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. - -### Pallet Structure - -FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. - -A typical pallet looks like this: - -```rust -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - #[pallet::config] // snip - #[pallet::event] // snip - #[pallet::error] // snip - #[pallet::storage] // snip - #[pallet::call] // snip -} -``` - -Every pallet can implement these core macros: - -- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. -- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. -- **`#[pallet::config]`**: Defines configuration and associated types. -- **`#[pallet::event]`**: Defines events emitted by your pallet. -- **`#[pallet::error]`**: Defines error types your pallet can return. -- **`#[pallet::storage]`**: Defines on-chain storage items. -- **`#[pallet::call]`**: Defines dispatchable functions (transactions). - -For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. - -## How Runtime Customization Works - -Customizing your runtime typically follows these patterns: - -**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. - -**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. - -**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. - -**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. - -The following diagram illustrates how pallets combine to form a complete runtime: - -![](/images/parachains/customize-runtime/index/frame-overview-02.webp) - -## Starting Templates - -The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. - -- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. - -- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. - -- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. - -- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. - -## Key Customization Scenarios - -This section covers the most common customization patterns you'll encounter: - -- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. - -- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. - -- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. - -- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. - -- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. - - ---- - -Page Title: Overview of the Polkadot Relay Chain - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/ -- Summary: Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. - -# Overview - -## Introduction - -Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank}, and cross-chain interactions via its native [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank}. - -This guide covers key aspects of Polkadot’s architecture, including its high-level protocol structure, blockspace commoditization, and the role of its native token, DOT, in governance, staking, and resource allocation. - -## Polkadot 1.0 - -Polkadot 1.0 represents the state of Polkadot as of 2023, coinciding with the release of [Polkadot runtime v1.0.0](https://github.com/paritytech/polkadot/releases/tag/v1.0.0){target=\_blank}. This section will focus on Polkadot 1.0, along with philosophical insights into network resilience and blockspace. - -As a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including: - -- **Application-specific Layer-1 blockchains (parachains)**: Polkadot's sharded network allows for parallel transaction processing, with shards that can have unique state transition functions, enabling custom-built L1 chains optimized for specific applications. - -- **Shared security and scalability**: L1 chains connected to Polkadot benefit from its [Nominated Proof of Stake (NPoS)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#nominated-proof-of-stake){target=\_blank} system, providing security out-of-the-box without the need to bootstrap their own. - -- **Secure interoperability**: Polkadot's native interoperability enables seamless data and value exchange between parachains. This interoperability can also be used outside of the ecosystem for bridging with external networks. - -- **Resilient infrastructure**: Decentralized and scalable, Polkadot ensures ongoing support for development and community initiatives via its on-chain [treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} and governance. - -- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. - -- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. - - - [Polkadot Blockchain Academy](https://polkadot.com/blockchain-academy){target=\_blank} - - [EdX courses](https://www.edx.org/school/web3x){target=\_blank} - - Rust and Substrate courses (coming soon) - -### High-Level Architecture - -Polkadot features a chain that serves as the central component of the system. This chain is depicted as a ring encircled by several parachains that are connected to it. - -According to Polkadot's design, any blockchain that can compile to WebAssembly (Wasm) and adheres to the Parachains Protocol becomes a parachain on the Polkadot network. - -Here’s a high-level overview of the Polkadot protocol architecture: - -![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } - -Parachains propose blocks to Polkadot validators, who check for availability and validity before finalizing them. With the relay chain providing security, collators—full nodes of parachains—can focus on their tasks without needing strong incentives. - -The [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank} allows parachains to exchange messages freely, leveraging the chain's security for trust-free communication. - -In order to interact with chains that want to use their own finalization process (e.g., Bitcoin), Polkadot has [bridges](/reference/parachains/interoperability/#bridges-connecting-external-networks){target=\_blank} that offer two-way compatibility, meaning that transactions can be made between different parachains. - -### Polkadot's Additional Functionalities - -Historically, obtaining core slots on Polkadot chain relied upon crowdloans and auctions. Chain cores were leased through auctions for three-month periods, up to a maximum of two years. Crowdloans enabled users to securely lend funds to teams for lease deposits in exchange for pre-sale tokens, which is the only way to access slots on Polkadot 1.0. Auctions are now deprecated in favor of [coretime](/polkadot-protocol/architecture/system-chains/coretime/){target=\_blank}. - -Additionally, the chain handles [staking](https://wiki.polkadot.com/learn/learn-staking/){target=\_blank}, [accounts](/reference/parachains/accounts/){target=\_blank}, balances, and [governance](/reference/governance/){target=\_blank}. - -#### Agile Coretime - -The new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. - -[Agile coretime](/reference/polkadot-hub/consensus-and-security/agile-coretime/){target=\_blank} improves the efficient use of Polkadot's network resources and offers economic flexibility for developers, extending Polkadot's capabilities far beyond the original vision outlined in the [whitepaper](https://polkadot.com/papers/Polkadot-whitepaper.pdf){target=\_blank}. - -It enables parachains to purchase monthly "bulk" allocations of coretime (the time allocated for utilizing a core, measured in Polkadot relay chain blocks), ensuring heavy-duty parachains that can author a block every six seconds with [Asynchronous Backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} can reliably renew their coretime each month. Although six-second block times are now the default, parachains have the option of producing blocks less frequently. - -Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. - -### Polkadot's Resilience - -Decentralization is a vital component of blockchain networks, but it comes with trade-offs: - -- An overly decentralized network may face challenges in reaching consensus and require significant energy to operate. -- Also, a network that achieves consensus quickly risks centralization, making it easier to manipulate or attack. - -A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. - -Polkadot 1.0 currently achieves resilience through several strategies: - -- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. - -- **Decentralized nodes**: Designed to encourage operators to join the network. This program aims to expand and diversify the validators in the ecosystem who aim to become independent of the program during their term. Feel free to explore more about the program on the official [Decentralized Nodes](https://nodes.web3.foundation/){target=\_blank} page. - -- **On-chain treasury and governance**: Known as [OpenGov](/reference/governance/){target=\_blank}, this system allows every decision to be made through public referenda, enabling any token holder to cast a vote. - -### Polkadot's Blockspace - -Polkadot 1.0’s design allows for the commoditization of blockspace. - -Blockspace is a blockchain's capacity to finalize and commit operations, encompassing its security, computing, and storage capabilities. Its characteristics can vary across different blockchains, affecting security, flexibility, and availability. - -- **Security**: Measures the robustness of blockspace in Proof of Stake (PoS) networks linked to the stake locked on validator nodes, the variance in stake among validators, and the total number of validators. It also considers social centralization (how many validators are owned by single operators) and physical centralization (how many validators run on the same service provider). - -- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes. - -- **Availability**: Indicates how easily users can access blockspace. It should be easily accessible, allowing diverse business models to thrive, ideally regulated by a marketplace based on demand and supplemented by options for "second-hand" blockspace. - -Polkadot is built on core blockspace principles, but there's room for improvement. Tasks like balance transfers, staking, and governance are managed on the relay chain. - -Delegating these responsibilities to [system chains](/polkadot-protocol/architecture/system-chains/){target=\_blank} could enhance flexibility and allow the relay chain to concentrate on providing shared security and interoperability. - -For more information about blockspace, watch [Robert Habermeier’s interview](https://www.youtube.com/watch?v=e1vISppPwe4){target=\_blank} or read his [technical blog post](https://www.rob.tech/blog/polkadot-blockspace-over-blockchains/){target=\_blank}. - -## DOT Token - -DOT is the native token of the Polkadot network, much like BTC for Bitcoin and Ether for the Ethereum blockchain. DOT has 10 decimals, uses the Planck base unit, and has a balance type of `u128`. The same is true for Kusama's KSM token with the exception of having 12 decimals. - -### Redenomination of DOT - -Polkadot conducted a community poll, which ended on 27 July 2020 at block 888,888, to decide whether to redenominate the DOT token. The stakeholders chose to redenominate the token, changing the value of 1 DOT from 1e12 plancks to 1e10 plancks. - -Importantly, this did not affect the network's total number of base units (plancks); it only affects how a single DOT is represented. The redenomination became effective 72 hours after transfers were enabled, occurring at block 1,248,328 on 21 August 2020 around 16:50 UTC. - -### The Planck Unit - -The smallest unit of account balance on Polkadot SDK-based blockchains (such as Polkadot and Kusama) is called _Planck_, named after the Planck length, the smallest measurable distance in the physical universe. - -Similar to how BTC's smallest unit is the Satoshi and ETH's is the Wei, Polkadot's native token DOT equals 1e10 Planck, while Kusama's native token KSM equals 1e12 Planck. - -### Uses for DOT - -DOT serves three primary functions within the Polkadot network: - -- **Governance**: It is used to participate in the governance of the network. -- **Staking**: DOT is staked to support the network's operation and security. -- **Buying coretime**: Used to purchase coretime in-bulk or on-demand and access the chain to benefit from Polkadot's security and interoperability. - -Additionally, DOT can serve as a transferable token. For example, DOT, held in the treasury, can be allocated to teams developing projects that benefit the Polkadot ecosystem. - -## JAM and the Road Ahead - -The Join-Accumulate Machine (JAM) represents a transformative redesign of Polkadot's core architecture, envisioned as the successor to the current relay chain. Unlike traditional blockchain architectures, JAM introduces a unique computational model that processes work through two primary functions: - -- **Join**: Handles data integration. -- **Accumulate**: Folds computations into the chain's state. - -JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: - -- **Permissionless code execution**: JAM is designed to be more generic and flexible, allowing for permissionless code execution through services that can be deployed without governance approval. -- **More effective block time utilization**: JAM's efficient pipeline processing model places the prior state root in block headers instead of the posterior state root, enabling more effective utilization of block time for computations. - -This architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes. - - ---- - -Page Title: Parachains Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/ -- Summary: Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. - -# Parachains Overview - -## Introduction - -A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network. - -Unlike standalone blockchains that must bootstrap their own validator sets and security, parachains leverage Polkadot's pooled security model. This allows parachain developers to focus on their application-specific functionality rather than consensus and security infrastructure. Parachains can communicate with each other through Cross-Consensus Messaging (XCM), enabling seamless interoperability across the Polkadot ecosystem. - -Key capabilities that parachains provide include: - -- **Shared security**: Inherit security from Polkadot's validator set without maintaining your own. -- **Interoperability**: Communicate trustlessly with other parachains via XCM. -- **Scalability**: Process transactions in parallel with other parachains. -- **Customization**: Build application-specific logic tailored to your use case. -- **Upgradeability**: Upgrade runtime logic without hard forks. - -## Polkadot SDK: Parachain Architecture - -Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: - -![](/images/reference/parachains/index/overview-01.webp) - -- **[Substrate](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html){target=\_blank}**: The foundation providing core blockchain primitives and libraries. -- **[FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank}**: A modular framework for building your parachain's runtime logic. -- **[Cumulus](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html){target=\_blank}**: Essential libraries and pallets that enable parachain functionality. -- **[XCM (Cross Consensus Messaging)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/xcm/index.html){target=\_blank}**: The messaging format for communicating with other parachains and the relay chain. -- **[Polkadot](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/polkadot/index.html){target=\_blank}**: The relay chain that provides security and coordination. - -### Substrate: The Foundation - -Substrate provides the core infrastructure that every parachain is built upon. It handles the low-level blockchain functionality, allowing you to focus on your application's unique features. Substrate includes implementations for networking, database management, consensus participation, and the execution environment for your runtime. - -Every Polkadot SDK node consists of two main components: - -- **Client (Host)**: Handles infrastructure services. - - - Native binary that runs on validator and collator nodes. - - Executes the Wasm-compiled runtime. - - Manages networking, database, mempool, and block production. - - Interfaces with the relay chain for validation. - -- **Runtime (State Transition Function)**: Contains your business logic. - - - Defines how your Polkadot SDK node processes transactions. - - Compiled to [Wasm](https://webassembly.org/){target=\_blank} for deterministic execution. - - Stored on-chain and upgradeable via governance. - -```mermaid -%%{init: {'flowchart': {'padding': 5, 'nodeSpacing': 50, 'rankSpacing': 10}}}%% -graph TB - classDef title font-size:20px,font-weight:bold,stroke-width:0px - classDef clientStyle font-size:16px,font-weight:bold - classDef clientSubNodeStyle margin-top:10px - classDef runtimeCallExecutorStyle padding-top:10px - - subgraph sg1[Parachain
    Node] - direction TB - - I[RuntimeCall Executor] - B[Wasm Runtime - STF] - - subgraph sg2[Client] - direction TB - C[Network and Blockchain
    Infrastructure Services
    + Relay Chain Interface] - end - - I --> B - end - - class sg1 title - class sg2 clientStyle - class C clientSubNodeStyle - class I runtimeCallExecutorStyle - -``` - -### FRAME: Building Blocks for Your Runtime - -FRAME provides modular components called [pallets](/reference/glossary#pallet){target=\_blank} that you can compose to build your parachain's runtime. Each pallet provides specific functionality that you can customize and configure for your needs. This modular approach allows you to quickly assemble complex functionality without writing everything from scratch. - -```mermaid -graph LR - subgraph SP["Parachain Runtime"] - direction LR - Timestamp ~~~ Aura ~~~ ParachainSystem - Balances ~~~ TransactionPayment ~~~ Sudo - subgraph Timestamp["Timestamp"] - SS1[Custom Config] - end - subgraph Aura["Aura"] - SS2[Custom Config] - end - subgraph ParachainSystem["Parachain System"] - SS3[Custom Config] - end - subgraph Balances["Balances"] - SS4[Custom Config] - end - subgraph TransactionPayment["Transaction Payment"] - SS5[Custom Config] - end - subgraph Sudo["Sudo"] - SS6[Custom Config] - end - style Timestamp stroke:#FF69B4 - style Aura stroke:#FF69B4 - style ParachainSystem stroke:#FF69B4 - style Balances stroke:#FF69B4 - style TransactionPayment stroke:#FF69B4 - style Sudo stroke:#FF69B4 - style SS1 stroke-dasharray: 5 - style SS2 stroke-dasharray: 5 - style SS3 stroke-dasharray: 5 - style SS4 stroke-dasharray: 5 - style SS5 stroke-dasharray: 5 - style SS6 stroke-dasharray: 5 - - end - subgraph AP["Available FRAME Pallets"] - direction LR - A1[Aura]~~~A2[Parachain
    System]~~~A3[Transaction
    Payment]~~~A4[Sudo] - B1[Identity]~~~B2[Balances]~~~B3[Assets]~~~B4[EVM] - C1[Timestamp]~~~C2[Staking]~~~C3[Contracts]~~~C4[and more...] - end - AP --> SP -``` - -### Cumulus: Parachain-Specific Functionality - -Cumulus is what transforms a Polkadot SDK-based runtime into a parachain-capable runtime. It provides the essential components for communicating with the relay chain, participating in Polkadot's consensus, and handling parachain-specific operations like block validation and collation. - -Key Cumulus components include: - -- **Parachain system pallet**: Core parachain functionality and relay chain communication. -- **Collator consensus**: Block production logic for parachain collators. -- **Relay chain interface**: APIs for interacting with the Polkadot relay chain. -- **Validation data**: Handling proof-of-validity data required by relay chain validators. - -## Where to Go Next - -Building a parachain requires understanding the relationship between your chain and the Polkadot relay chain. The Polkadot SDK provides all the tools needed to design custom runtime logic, enable cross-chain communication, and deploy your parachain to production. - -The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. - -
    - -- Guide __Launch a Simple Parachain__ - - --- - - Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. - - [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) - - -- Guide __Customize Your Runtime__ - - --- - - Design your parachain's runtime logic and choose appropriate pallets for your use case. - - [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) - -- Guide __Interoperability__ - - --- - - Implement XCM for trustless cross-chain communication with other parachains. - - [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/) - -- Guide __Runtime Upgrades__ - - --- - - Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. - - [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) - -
    - - ---- - -Page Title: Polkadot Omni Node - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/omninode/ -- Summary: Run parachain nodes easily with the polkadot-omni-node, a white-labeled binary that can run parachain nodes using a single pre-built solution. - -# Polkadot Omni Node - -## Introduction - -The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\_blank} file, allowing it to adapt dynamically to different parachains. - -This approach enables it to act as a white-labeled node binary, capable of running most parachains that do not require custom node-level logic or extensions. Developers can leverage this flexibility to test, deploy, or operate parachain nodes without maintaining a dedicated codebase for each network. - -This guide provides step-by-step instructions for installing the `polkadot-omni-node`, obtaining a chain specification, and spinning up a parachain node. - -## Prerequisites - -Before getting started, ensure you have the following prerequisites: - -- **[Rust](https://rust-lang.org/tools/install/){target=\_blank}**: Required to build and install the `polkadot-omni-node` binary. - -Ensure Rust's `cargo` command is available in your terminal by running: - -```bash -cargo --version -``` - -## Install Polkadot Omni Node - -To install `polkadot-omni-node` globally using `cargo`, run: - -```bash -cargo install --locked polkadot-omni-node@0.7.0 -``` - -This command downloads and installs version 0.7.0 of the binary, making it available system-wide. - -To confirm the installation, run: - -```bash -polkadot-omni-node --version -``` - -You should see the installed version number printed to the terminal, confirming a successful installation. - -## Obtain Chain Specifications - -The `polkadot-omni-node` binary uses a chain specification file to configure and launch a parachain node. This file defines the parachain's genesis state and network settings. - -The most common source for official chain specifications is the [`paritytech/chainspecs`](https://github.com/paritytech/chainspecs){target=\_blank} repository. These specifications are also browsable in a user-friendly format via the [Chainspec Collection](https://paritytech.github.io/chainspecs/){target=\_blank} website. - -To obtain a chain specification: - -1. Visit the [Chainspec Collection](https://paritytech.github.io/chainspecs/){target=\_blank} website. -2. Find the parachain you want to run. -3. Click the chain spec to open it. -4. Copy the JSON content and save it locally as a `.json` file, e.g., `chain_spec.json`. - -## Run a Parachain Full Node - -Once you've installed `polkadot-omni-node` and saved the appropriate chain specification file, you can start a full node for your chosen parachain. - -To see all available flags and configuration options, run: - -```bash -polkadot-omni-node --help -``` - -To launch the node, run the following command, replacing `./INSERT_PARACHAIN_CHAIN_SPEC.json` with the actual path to your saved chain spec file. - -This command will: - -- Load the chain specification. -- Initialize the node using the provided network configuration. -- Begin syncing with the parachain network. - -```bash -polkadot-omni-node --chain ./INSERT_PARACHAIN_CHAIN_SPEC.json --sync warp -``` - -- The `--chain` flag tells the `polkadot-omni-node` which parachain to run by pointing to its chain specification file. -- The `--sync warp` flag enables warp sync, allowing the node to quickly catch up to the latest finalized state. Historical blocks are fetched in the background as the node continues operating. - -Once started, the node will begin connecting to peers and syncing with the network. You’ll see logs in your terminal reflecting its progress. - -## Interact with the Node - -By default, `polkadot-omni-node` exposes a WebSocket endpoint at `ws://localhost:9944`, which you can use to interact with the running node. You can connect using: - -- **[Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank}**: A web-based interface for exploring and interacting with Polkadot SDK-based chains. -- Custom scripts using compatible [libraries](/develop/toolkit/api-libraries/){target=\_blank}. - -Once connected, you can review blocks, call extrinsics, inspect storage, and interact with the runtime. - -## Parachain Compatibility - -The `polkadot-omni-node` is designed to work with most parachains out of the box; however, your parachain's runtime must meet specific requirements and follow certain conventions to be compatible. This section outlines what your runtime needs to implement and configure to work seamlessly with the `polkadot-omni-node`: - -- Your runtime must implement the required runtime APIs (see below). -- Your runtime must include and configure the required pallets. - -The [`parachain-template`](https://github.com/paritytech/polkadot-sdk-parachain-template/tree/v0.0.4){target=_blank} provides a complete reference implementation that is fully compatible with the `polkadot-omni-node`. You can use it as a starting point or reference for ensuring your runtime meets all compatibility requirements. - -### Required Runtime APIs - -Your parachain runtime must implement the following runtime APIs for the `polkadot-omni-node` to function properly: - -- **GetParachainInfo Runtime API**: The omni-node requires the [`GetParachainInfo`](https://paritytech.github.io/polkadot-sdk/master/cumulus_primitives_core/trait.GetParachainInfo.html){target=\_blank} runtime API to identify and configure the parachain correctly. This API provides the parachain ID to the node. - - ```rust title="runtime/src/apis.rs" - impl cumulus_primitives_core::GetParachainInfo for Runtime { - fn parachain_id() -> cumulus_primitives_core::ParaId { - // Return your parachain ID - ParachainInfo::parachain_id() - } - } - ``` - -- **Aura Runtime API**: For consensus, the `polkadot-omni-node` expects the [Aura runtime API](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/apis/trait.AuraApi.html){target=\_blank} to be implemented. - - ```rust title="runtime/src/apis.rs" - impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION) - } - - fn authorities() -> Vec { - Aura::authorities().into_inner() - } - } - ``` - -### Required Pallets - -Your runtime must include and properly configure the following pallets: - -- **System Pallet**: The System pallet ([`frame-system`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/prelude/frame_system/index.html){target=\_blank}) is fundamental and must be configured with appropriate types. - - ```rust title="runtime/src/lib.rs" - #[frame_support::runtime] - impl frame_system::Config for Runtime { - type Block = Block; - type BlockNumber = BlockNumber; - // ... other configurations - } - - // Must be named "System" for omni-node compatibility - pub type System = frame_system::Pallet; - ``` - -- **ParachainSystem Pallet**: This pallet ([`cumulus-pallet-parachain-system`](https://paritytech.github.io/polkadot-sdk/master/cumulus_pallet_parachain_system/index.html){target=\_blank}) enables parachain functionality and handles low-level details of being a parachain. - - ```rust title="runtime/src/lib.rs" - impl cumulus_pallet_parachain_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - // ... other configurations - } - - // Must be named "ParachainSystem" for omni-node compatibility - pub type ParachainSystem = cumulus_pallet_parachain_system::Pallet; - ``` - -- **Aura Pallet**: For block authoring consensus ([`pallet-aura`](https://paritytech.github.io/polkadot-sdk/master/pallet_aura/index.html){target=\_blank}). - - ```rust title="runtime/src/lib.rs" - impl pallet_aura::Config for Runtime { - type AuthorityId = AuraId; - type DisabledValidators = (); - type MaxAuthorities = MaxAuthorities; - type AllowMultipleBlocksPerSlot = ConstBool; - } - - pub type Aura = pallet_aura::Pallet; - ``` - -- **ParachainInfo Pallet**: Provides parachain metadata ([`parachain-info`](https://paritytech.github.io/polkadot-sdk/master/staging_parachain_info/index.html){target=\_blank}). - - ```rust title="runtime/src/lib.rs" - impl parachain_info::Config for Runtime {} - - pub type ParachainInfo = parachain_info::Pallet; - ``` - -If you're migrating an existing parachain to use the `polkadot-omni-node`, you may need to perform runtime upgrades to add the required runtime APIs and pallets. Follow the standard parachain [runtime upgrade](/parachains/runtime-maintenance/runtime-upgrades/){target=\_blank} procedures to implement these changes on your live network. - - ---- - -Page Title: Polkadot SDK Accounts - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/accounts/ -- Summary: Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. - -# Accounts - -## Introduction - -Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains. - -This page will guide you through the essential aspects of accounts, including their data structure, balance types, reference counters, and address formats. You’ll learn how accounts are managed within the runtime, how balances are categorized, and how addresses are encoded and validated. - -## Account Data Structure - -Accounts are foundational to any blockchain, and the Polkadot SDK provides a flexible management system. This section explains how the Polkadot SDK defines accounts and manages their lifecycle through data structures within the runtime. - -### Account - -The [`Account` data type](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/type.Account.html){target=\_blank} is a storage map within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank} that links an account ID to its corresponding data. This structure is fundamental for mapping account-related information within the chain. - -The code snippet below shows how accounts are defined: - -```rs - /// The full account information for a particular account ID. - #[pallet::storage] - #[pallet::getter(fn account)] - pub type Account = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - AccountInfo, - ValueQuery, - >; -``` - -The preceding code block defines a storage map named `Account`. The `StorageMap` is a type of on-chain storage that maps keys to values. In the `Account` map, the key is an account ID, and the value is the account's information. Here, `T` represents the generic parameter for the runtime configuration, which is defined by the pallet's configuration trait (`Config`). - -The `StorageMap` consists of the following parameters: - -- **`_`**: Used in macro expansion and acts as a placeholder for the storage prefix type. Tells the macro to insert the default prefix during expansion. -- **`Blake2_128Concat`**: The hashing function applied to keys in the storage map. -- **`T: :AccountId`**: Represents the key type, which corresponds to the account’s unique ID. -- **`AccountInfo`**: The value type stored in the map. For each account ID, the map stores an `AccountInfo` struct containing: - - - **`T::Nonce`**: A nonce for the account, which is incremented with each transaction to ensure transaction uniqueness. - - **`T: :AccountData`**: Custom account data defined by the runtime configuration, which could include balances, locked funds, or other relevant information. - -- **`ValueQuery`**: Defines how queries to the storage map behave when no value is found; returns a default value instead of `None`. - -For a detailed explanation of storage maps, see the [`StorageMap`](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/struct.StorageMap.html){target=\_blank} entry in the Rust docs. - -### Account Info - -The `AccountInfo` structure is another key element within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank}, providing more granular details about each account's state. This structure tracks vital data, such as the number of transactions and the account’s relationships with other modules. - -```rs -/// Information of an account. -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct AccountInfo { - /// The number of transactions this account has sent. - pub nonce: Nonce, - /// The number of other modules that currently depend on this account's existence. The account - /// cannot be reaped until this is zero. - pub consumers: RefCount, - /// The number of other modules that allow this account to exist. The account may not be reaped - /// until this and `sufficients` are both zero. - pub providers: RefCount, - /// The number of modules that allow this account to exist for their own purposes only. The - /// account may not be reaped until this and `providers` are both zero. - pub sufficients: RefCount, - /// The additional data that belongs to this account. Used to store the balance(s) in a lot of - /// chains. - pub data: AccountData, -} -``` - -The `AccountInfo` structure includes the following components: - -- **`nonce`**: Tracks the number of transactions initiated by the account, which ensures transaction uniqueness and prevents replay attacks. -- **`consumers`**: Counts how many other modules or pallets rely on this account’s existence. The account cannot be removed from the chain (reaped) until this count reaches zero. -- **`providers`**: Tracks how many modules permit this account’s existence. An account can only be reaped once both `providers` and `sufficients` are zero. -- **`sufficients`**: Represents the number of modules that allow the account to exist for internal purposes, independent of any other modules. -- **`AccountData`**: A flexible data structure that can be customized in the runtime configuration, usually containing balances or other user-specific data. - -This structure helps manage an account's state and prevents its premature removal while it is still referenced by other on-chain data or modules. The [`AccountInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.AccountInfo.html){target=\_blank} structure can vary as long as it satisfies the trait bounds defined by the `AccountData` associated type in the [`frame-system::pallet::Config`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/trait.Config.html){target=\_blank} trait. - -### Account Reference Counters - -Polkadot SDK uses reference counters to track an account’s dependencies across different runtime modules. These counters ensure that accounts remain active while data is associated with them. - -The reference counters include: - -- **`consumers`**: Prevents account removal while other pallets still rely on the account. -- **`providers`**: Ensures an account is active before other pallets store data related to it. -- **`sufficients`**: Indicates the account’s independence, ensuring it can exist even without a native token balance, such as when holding sufficient alternative assets. - -#### Providers Reference Counters - -The `providers` counter ensures that an account is ready to be depended upon by other runtime modules. For example, it is incremented when an account has a balance above the existential deposit, which marks the account as active. - -The system requires this reference counter to be greater than zero for the `consumers` counter to be incremented, ensuring the account is stable before any dependencies are added. - -#### Consumers Reference Counters - -The `consumers` counter ensures that the account cannot be reaped until all references to it across the runtime have been removed. This check prevents the accidental deletion of accounts that still have active on-chain data. - -It is the user’s responsibility to clear out any data from other runtime modules if they wish to remove their account and reclaim their existential deposit. - -#### Sufficients Reference Counter - -The `sufficients` counter tracks accounts that can exist independently without relying on a native account balance. This is useful for accounts holding other types of assets, like tokens, without needing a minimum balance in the native token. - -For instance, the [Assets pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank}, may increment this counter for an account holding sufficient tokens. - -#### Account Deactivation - -In Polkadot SDK-based chains, an account is deactivated when its reference counters (such as `providers`, `consumers`, and `sufficient`) reach zero. These counters ensure the account remains active as long as other runtime modules or pallets reference it. - -When all dependencies are cleared and the counters drop to zero, the account becomes deactivated and may be removed from the chain (reaped). This is particularly important in Polkadot SDK-based blockchains, where accounts with balances below the existential deposit threshold are pruned from storage to conserve state resources. - -Each pallet that references an account has cleanup functions that decrement these counters when the pallet no longer depends on the account. Once these counters reach zero, the account is marked for deactivation. - -#### Updating Counters - -The Polkadot SDK provides runtime developers with various methods to manage account lifecycle events, such as deactivation or incrementing reference counters. These methods ensure that accounts cannot be reaped while still in use. - -The following helper functions manage these counters: - -- **`inc_consumers()`**: Increments the `consumer` reference counter for an account, signaling that another pallet depends on it. -- **`dec_consumers()`**: Decrements the `consumer` reference counter, signaling that a pallet no longer relies on the account. -- **`inc_providers()`**: Increments the `provider` reference counter, ensuring the account remains active. -- **`dec_providers()`**: Decrements the `provider` reference counter, allowing for account deactivation when no longer in use. -- **`inc_sufficients()`**: Increments the `sufficient` reference counter for accounts that hold sufficient assets. -- **`dec_sufficients()`**: Decrements the `sufficient` reference counter. - -To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. - -The `System` pallet offers three query functions to assist developers in tracking account states: - -- **[`can_inc_consumer()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_inc_consumer){target=\_blank}**: Checks if the account can safely increment the consumer reference. -- **[`can_dec_provider()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_dec_provider){target=\_blank}**: Ensures that no consumers exist before allowing the decrement of the provider counter. -- **[`is_provider_required()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.is_provider_required){target=\_blank}**: Verifies whether the account still has any active consumer references. - -This modular and flexible system of reference counters tightly controls the lifecycle of accounts in Polkadot SDK-based blockchains, preventing the accidental removal or retention of unneeded accounts. You can refer to the [System pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html){target=\_blank} for more details. - - -## Account Balance Types - -In the Polkadot ecosystem, account balances are categorized into different types based on how the funds are utilized and their availability. These balance types determine the actions that can be performed, such as transferring tokens, paying transaction fees, or participating in governance activities. Understanding these balance types helps developers manage user accounts and implement balance-dependent logic. - -!!! note "A more efficient distribution of account balance types is in development" - Soon, pallets in the Polkadot SDK will implement the [`Fungible` trait](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} (see the [tracking issue](https://github.com/paritytech/polkadot-sdk/issues/226){target=\_blank} for more details). For example, the [`transaction-storage`](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_storage/index.html){target=\_blank} pallet changed the implementation of the [`Currency`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/currency/index.html){target=\_blank} trait (see the [Refactor transaction storage pallet to use fungible traits](https://github.com/paritytech/polkadot-sdk/pull/1800){target=\_blank} PR for further details): - - ```rust - type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - ``` - - To the [`Fungible`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} trait: - - ```rust - type BalanceOf = <::Currency as FnInspect<::AccountId>>::Balance; - ``` - - This update will enable more efficient use of account balances, allowing the free balance to be utilized for on-chain activities such as setting proxies and managing identities. - -### Balance Types - -The five main balance types are: - -- **Free balance**: Represents the total tokens available to the account for any on-chain activity, including staking, governance, and voting. However, it may not be fully spendable or transferrable if portions of it are locked or reserved. -- **Locked balance**: Portions of the free balance that cannot be spent or transferred because they are tied up in specific activities like [staking](https://wiki.polkadot.com/learn/learn-staking/#nominating-validators){target=\_blank}, [vesting](https://wiki.polkadot.com/learn/learn-guides-transfers/#vested-transfers-with-the-polkadot-js-ui){target=\_blank}, or participating in [governance](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank}. While the tokens remain part of the free balance, they are non-transferable for the duration of the lock. -- **Reserved balance**: Funds locked by specific system actions, such as setting up an [identity](https://wiki.polkadot.com/learn/learn-identity/){target=\_blank}, creating [proxies](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}, or submitting [deposits for governance proposals](https://wiki.polkadot.com/learn/learn-guides-polkadot-opengov/#claiming-opengov-deposits){target=\_blank}. These tokens are not part of the free balance and cannot be spent unless they are unreserved. -- **Spendable balance**: The portion of the free balance that is available for immediate spending or transfers. It is calculated by subtracting the maximum of locked or reserved amounts from the free balance, ensuring that existential deposit limits are met. -- **Untouchable balance**: Funds that cannot be directly spent or transferred but may still be utilized for on-chain activities, such as governance participation or staking. These tokens are typically tied to certain actions or locked for a specific period. - -The spendable balance is calculated as follows: - -```text -spendable = free - max(locked - reserved, ED) -``` - -Here, `free`, `locked`, and `reserved` are defined above. The `ED` represents the [existential deposit](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank}, the minimum balance required to keep an account active and prevent it from being reaped. You may find you can't see all balance types when looking at your account via a wallet. Wallet providers often display only spendable, locked, and reserved balances. - -### Locks - -Locks are applied to an account's free balance, preventing that portion from being spent or transferred. Locks are automatically placed when an account participates in specific on-chain activities, such as staking or governance. Although multiple locks may be applied simultaneously, they do not stack. Instead, the largest lock determines the total amount of locked tokens. - -Locks follow these basic rules: - -- If different locks apply to varying amounts, the largest lock amount takes precedence. -- If multiple locks apply to the same amount, the lock with the longest duration governs when the balance can be unlocked. - -#### Locks Example - -Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: - -- 80 DOT is staked with a 28-day lock period. -- 24 DOT is locked for governance with a 1x conviction and a 7-day lock period. -- 4 DOT is locked for governance with a 6x conviction and a 224-day lock period. - -In this case, the total locked amount is 80 DOT because only the largest lock (80 DOT from staking) governs the locked balance. These 80 DOT will be released at different times based on the lock durations. In this example, the 24 DOT locked for governance will be released first since the shortest lock period is seven days. The 80 DOT stake with a 28-day lock period is released next. Now, all that remains locked is the 4 DOT for governance. After 224 days, all 80 DOT (minus the existential deposit) will be free and transferable. - -![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) - -#### Edge Cases for Locks - -In scenarios where multiple convictions and lock periods are active, the lock duration and amount are determined by the longest period and largest amount. For example, if you delegate with different convictions and attempt to undelegate during an active lock period, the lock may be extended for the full amount of tokens. For a detailed discussion on edge case lock behavior, see this [Stack Exchange post](https://substrate.stackexchange.com/questions/5067/delegating-and-undelegating-during-the-lock-period-extends-it-for-the-initial-am){target=\_blank}. - -### Balance Types on Polkadot.js - -Polkadot.js provides a user-friendly interface for managing and visualizing various account balances on Polkadot and Kusama networks. When interacting with Polkadot.js, you will encounter multiple balance types that are critical for understanding how your funds are distributed and restricted. This section explains how different balances are displayed in the Polkadot.js UI and what each type represents. - -![](/images/reference/parachains/accounts/accounts-02.webp) - -The most common balance types displayed on Polkadot.js are: - -- **Total balance**: The total number of tokens available in the account. This includes all tokens, whether they are transferable, locked, reserved, or vested. However, the total balance does not always reflect what can be spent immediately. In this example, the total balance is 0.6274 KSM. - -- **Transferable balance**: Shows how many tokens are immediately available for transfer. It is calculated by subtracting the locked and reserved balances from the total balance. For example, if an account has a total balance of 0.6274 KSM and a transferable balance of 0.0106 KSM, only the latter amount can be sent or spent freely. - -- **Vested balance**: Tokens that allocated to the account but released according to a specific schedule. Vested tokens remain locked and cannot be transferred until fully vested. For example, an account with a vested balance of 0.2500 KSM means that this amount is owned but not yet transferable. - -- **Locked balance**: Tokens that are temporarily restricted from being transferred or spent. These locks typically result from participating in staking, governance, or vested transfers. In Polkadot.js, locked balances do not stack—only the largest lock is applied. For instance, if an account has 0.5500 KSM locked for governance and staking, the locked balance would display 0.5500 KSM, not the sum of all locked amounts. - -- **Reserved balance**: Refers to tokens locked for specific on-chain actions, such as setting an identity, creating a proxy, or making governance deposits. Reserved tokens are not part of the free balance, but can be freed by performing certain actions. For example, removing an identity would unreserve those funds. - -- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period. - -- **Redeemable balance**: The number of tokens that have completed the unbonding period and are ready to be unlocked and transferred again. For example, if an account has a redeemable balance of 0.1000 KSM, those tokens are now available for spending. - -- **Democracy balance**: Reflects the number of tokens locked for governance activities, such as voting on referenda. These tokens are locked for the duration of the governance action and are only released after the lock period ends. - -By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. - -## Address Formats - -The SS58 address format is a core component of the Polkadot SDK that enables accounts to be uniquely identified across Polkadot-based networks. This format is a modified version of Bitcoin's Base58Check encoding, specifically designed to accommodate the multi-chain nature of the Polkadot ecosystem. SS58 encoding allows each chain to define its own set of addresses while maintaining compatibility and checksum validation for security. - -### Basic Format - -SS58 addresses consist of three main components: - -```text -base58encode(concat(,
    , )) -``` - -- **Address type**: A byte or set of bytes that define the network (or chain) for which the address is intended. This ensures that addresses are unique across different Polkadot SDK-based chains. -- **Address**: The public key of the account encoded as bytes. -- **Checksum**: A hash-based checksum which ensures that addresses are valid and unaltered. The checksum is derived from the concatenated address type and address components, ensuring integrity. - -The encoding process transforms the concatenated components into a Base58 string, providing a compact and human-readable format that avoids easily confused characters (e.g., zero '0', capital 'O', lowercase 'l'). This encoding function ([`encode`](https://docs.rs/bs58/latest/bs58/fn.encode.html){target=\_blank}) is implemented exactly as defined in Bitcoin and IPFS specifications, using the same alphabet as both implementations. - -For more details about the SS58 address format implementation, see the [`Ss58Codec`](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Ss58Codec.html){target=\_blank} trait in the Rust Docs. - -### Address Type - -The address type defines how an address is interpreted and to which network it belongs. Polkadot SDK uses different prefixes to distinguish between various chains and address formats: - -- **Address types `0-63`**: Simple addresses, commonly used for network identifiers. -- **Address types `64-127`**: Full addresses that support a wider range of network identifiers. -- **Address types `128-255`**: Reserved for future address format extensions. - -For example, Polkadot’s main network uses an address type of 0, while Kusama uses 2. This ensures that addresses can be used without confusion between networks. - -The address type is always encoded as part of the SS58 address, making it easy to quickly identify the network. Refer to the [SS58 registry](https://github.com/paritytech/ss58-registry){target=\_blank} for the canonical listing of all address type identifiers and how they map to Polkadot SDK-based networks. - -### Address Length - -SS58 addresses can have different lengths depending on the specific format. Address lengths range from as short as 3 to 35 bytes, depending on the complexity of the address and network requirements. This flexibility allows SS58 addresses to adapt to different chains while providing a secure encoding mechanism. - -| Total | Type | Raw account | Checksum | -|-------|------|-------------|----------| -| 3 | 1 | 1 | 1 | -| 4 | 1 | 2 | 1 | -| 5 | 1 | 2 | 2 | -| 6 | 1 | 4 | 1 | -| 7 | 1 | 4 | 2 | -| 8 | 1 | 4 | 3 | -| 9 | 1 | 4 | 4 | -| 10 | 1 | 8 | 1 | -| 11 | 1 | 8 | 2 | -| 12 | 1 | 8 | 3 | -| 13 | 1 | 8 | 4 | -| 14 | 1 | 8 | 5 | -| 15 | 1 | 8 | 6 | -| 16 | 1 | 8 | 7 | -| 17 | 1 | 8 | 8 | -| 35 | 1 | 32 | 2 | - -SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. - -### Checksum Types - -A checksum is applied to validate SS58 addresses. Polkadot SDK uses a Blake2b-512 hash function to calculate the checksum, which is appended to the address before encoding. The checksum length can vary depending on the address format (e.g., 1-byte, 2-byte, or longer), providing varying levels of validation strength. - -The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. - -### Validating Addresses - -SS58 addresses can be validated using the subkey command-line interface or the Polkadot.js API. These tools help ensure an address is correctly formatted and valid for the intended network. The following sections will provide an overview of how validation works with these tools. - -#### Using Subkey - -[Subkey](https://paritytech.github.io/polkadot-sdk/master/subkey/index.html){target=\_blank} is a CLI tool provided by Polkadot SDK for generating and managing keys. It can inspect and validate SS58 addresses. - -The `inspect` command gets a public key and an SS58 address from the provided secret URI. The basic syntax for the `subkey inspect` command is: - -```bash -subkey inspect [flags] [options] uri -``` - -For the `uri` command-line argument, you can specify the secret seed phrase, a hex-encoded private key, or an SS58 address. If the input is a valid address, the `subkey` program displays the corresponding hex-encoded public key, account identifier, and SS58 addresses. - -For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: - -```bash -subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" -``` - -The command displays output similar to the following: - -
    - subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" - Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account: - Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849 - Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR - Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - SS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR -
    - -The `subkey` program assumes an address is based on a public/private key pair. If you inspect an address, the command returns the 32-byte account identifier. - -However, not all addresses in Polkadot SDK-based networks are based on keys. - -Depending on the command-line options you specify and the input you provided, the command output might also display the network for which the address has been encoded. For example: - -```bash -subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" -``` - -The command displays output similar to the following: - -
    - subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" - Public Key URI `12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU` is account: - Network ID/Version: polkadot - Public key (hex): 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Account ID: 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Public key (SS58): 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU - SS58 Address: 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU -
    - -#### Using Polkadot.js API - -To verify an address in JavaScript or TypeScript projects, you can use the functions built into the [Polkadot.js API](https://polkadot.js.org/docs/){target=\_blank}. For example: - -```js -// Import Polkadot.js API dependencies -const { decodeAddress, encodeAddress } = require('@polkadot/keyring'); -const { hexToU8a, isHex } = require('@polkadot/util'); - -// Specify an address to test. -const address = 'INSERT_ADDRESS_TO_TEST'; - -// Check address -const isValidSubstrateAddress = () => { - try { - encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); - - return true; - } catch (error) { - return false; - } -}; - -// Query result -const isValid = isValidSubstrateAddress(); -console.log(isValid); - -``` - -If the function returns `true`, the specified address is a valid address. - -#### Other SS58 Implementations - -Support for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries. - -- **Crystal**: [`wyhaines/base58.cr`](https://github.com/wyhaines/base58.cr){target=\_blank} -- **Go**: [`itering/subscan-plugin`](https://github.com/itering/subscan-plugin){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **TypeScript**: [`subsquid/squid-sdk`](https://github.com/subsquid/squid-sdk){target=\_blank} - - ---- - -Page Title: Randomness - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/randomness/ -- Summary: Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. - -# Randomness - -## Introduction - -Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as "random" numbers on a computer are actually pseudo-random. These numbers rely on an initial "seed," which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\_blank}, [heart rates](https://mdpi.altmetric.com/details/47574324){target=\_blank}, or even [lava lamps](https://en.wikipedia.org/wiki/Lavarand){target=\_blank}. While this may seem random, given the same "seed," the same sequence of numbers will always be generated. - -In a global blockchain network, relying on real-world entropy for randomness isn’t feasible because these inputs vary by time and location. If nodes use different inputs, blockchains can fork. Hence, real-world randomness isn't suitable for use as a seed in blockchain systems. - -Currently, two primary methods for generating randomness in blockchains are used: [`RANDAO`](#randao) and [`VRF`](#vrf) (Verifiable Random Function). Polkadot adopts the `VRF` approach for its randomness. - -## VRF - -A Verifiable Random Function (VRF) is a cryptographic function that generates a random number and proof that ensures the submitter produced the number. This proof allows anyone to verify the validity of the random number. - -Polkadot's VRF is similar to the one used in [**Ouroboros Praos**](https://eprint.iacr.org/2017/573.pdf){target=\_blank}, which secures randomness for block production in systems like [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe){target=\_blank} (Polkadot’s block production mechanism). - -The key difference is that Polkadot's VRF doesn’t rely on a central clock—avoiding the issue of whose clock to trust. Instead, it uses its own past results and slot numbers to simulate time and determine future outcomes. - -### How VRF Works - -Slots on Polkadot are discrete units of time, each lasting six seconds, and can potentially hold a block. Multiple slots form an epoch, with 2400 slots making up one four-hour epoch. - -In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: - -1. A "secret key," unique to each validator, is used for the die roll. -2. An epoch randomness value, derived from the hash of VRF outputs from blocks two epochs ago (N-2), so past randomness influences the current epoch (N). -3. The current slot number. - -This process helps maintain fair randomness across the network. - -Here is a graphical representation: - -![](/images/reference/parachains/randomness/randomness-01.webp) - -The VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). - -The result is checked by the validator against a protocol threshold. If it's below the threshold, the validator becomes a candidate for block production in that slot. - -The validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`. - -So, VRF can be expressed like: - -`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)` - -Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. - -After executing the VRF, the `RESULT` is compared to a protocol-defined `THRESHOLD`. If the `RESULT` is below the `THRESHOLD`, the validator becomes a valid candidate to propose a block for that slot. Otherwise, the validator skips the slot. - -As a result, there may be multiple validators eligible to propose a block for a slot. In this case, the block accepted by other nodes will prevail, provided it is on the chain with the latest finalized block as determined by the GRANDPA finality gadget. It's also possible for no block producers to be available for a slot, in which case the AURA consensus takes over. AURA is a fallback mechanism that randomly selects a validator to produce a block, running in parallel with BABE and only stepping in when no block producers exist for a slot. Otherwise, it remains inactive. - -Because validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. - -To verify resolution of this issue and that Polkadot block times remain near constant-time, see the [PoS Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} page of this documentation. - -## RANDAO - -An alternative on-chain randomness method is Ethereum's RANDAO, where validators perform thousands of hashes on a seed and publish the final hash during a round. The collective input from all validators forms the random number, and as long as one honest validator participates, the randomness is secure. - -To enhance security, RANDAO can optionally be combined with a Verifiable Delay Function (VDF), ensuring that randomness can't be predicted or manipulated during computation. - -For more information about RANDAO, see the [Randomness - RANDAO](https://eth2book.info/capella/part2/building_blocks/randomness/){target=\_blank} section of the Upgrading Ethereum documentation. - -## VDFs - -Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. - -They produce a unique result that can be quickly verified publicly. When combined with RANDAO, feeding RANDAO's output into a VDF introduces a delay that nullifies an attacker's chance to influence the randomness. - -However, VDF likely requires specialized ASIC devices to run separately from standard nodes. - -!!!warning - While only one is needed to secure the system, and they will be open-source and inexpensive, running VDF devices involves significant costs without direct incentives, adding friction for blockchain users. - -## Additional Resources - -For more information about the reasoning for choices made along with proofs, see Polkadot's research on blockchain randomness and sortition in the [Block production](https://research.web3.foundation/Polkadot/protocols/block-production){target=\_blank} entry of the Polkadot Wiki. - -For a discussion with Web3 Foundation researchers about when and under what conditions Polkadot's randomness can be utilized, see the [Discussion on Randomness used in Polkadot](https://github.com/use-ink/ink/issues/57){target=\_blank} issue on GitHub. - - ---- - -Page Title: Register a Local Asset - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md -- Canonical (HTML): https://docs.polkadot.com/chain-interactions/token-operations/register-local-asset/ -- Summary: Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. - -# Register a Local Asset on Asset Hub - -## Introduction - -As detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation. - -This guide will take you through the steps of registering a local asset on the Asset Hub parachain. - -## Prerequisites - -Before you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and a funded wallet with DOT or KSM. - -- For Polkadot Asset Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata. -- For Kusama Asset Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata. - -You need to ensure that your Asset Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees. - -## Steps to Register a Local Asset - -To register a local asset on the Asset Hub parachain, follow these steps: - -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. - - - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`. - - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider. - -2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. - - ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) - -3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column. - - ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) - -4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. - - ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) - -5. Fill in the required fields in the **Create Asset** form: - - 1. **creator account**: The account to be used for creating this asset and setting up the initial metadata. - 2. **asset name**: The descriptive name of the asset you are registering. - 3. **asset symbol**: The symbol that will be used to represent the asset. - 4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface. - 5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested. - 6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id. - 7. Click on the **Next** button. - - ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp) - -6. Choose the accounts for the roles listed below: - - 1. **admin account**: The account designated for continuous administration of the token. - 2. **issuer account**: The account that will be used for issuing this token. - 3. **freezer account**: The account that will be used for performing token freezing operations. - 4. Click on the **Create** button. - - ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp) - -7. Click on the **Sign and Submit** button to complete the asset registration process. - - ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) - -## Verify Asset Registration - -After completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets){target=\_blank} section of the Polkadot.js Apps interface. - -![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp) - -!!! tip - Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field. - -In this way, you have successfully registered a local asset on the Asset Hub parachain. - -For an in-depth explanation about Asset Hub and its features, see the [Asset Hub](/chain-interactions/token-operations/convert-assets/){target=\_blank} entry in the Polkadot Wiki. - -## Test Setup Environment - -You can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank} documentation. - -To set up a test environment, execute the following command: - -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` - -The above command will spawn a lazy fork of Polkadot Asset Hub with the latest block data from the network. If you need to test Kusama Asset Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. - -An Asset Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet. - - ---- - -Page Title: Runtime Upgrades - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md -- Canonical (HTML): https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/ -- Summary: This page covers how runtime versioning and storage migration support forkless upgrades for Polkadot SDK-based networks and how they factor into chain upgrades. - -# Runtime Upgrades - -## Introduction - -One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption. - -Forkless upgrades are achieved through WebAssembly (Wasm) runtimes stored on-chain, which can be securely swapped and upgraded as part of the blockchain's state. By leveraging decentralized consensus, runtime updates can happen trustlessly, ensuring continuous improvement and evolution without halting operations. - -This guide explains how Polkadot's runtime versioning, Wasm deployment, and storage migrations enable these upgrades, ensuring the blockchain evolves smoothly and securely. You'll also learn how different upgrade processes apply to solo chains and parachains, depending on the network setup. - -## How Runtime Upgrades Work - -In FRAME, the [`system`](https://paritytech.github.io/polkadot-sdk/master/frame_system/index.html){target=\_blank} pallet uses the [`set_code`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/enum.Call.html#variant.set_code){target=\_blank} extrinsic to update the Wasm code for the runtime. This method allows solo chains to upgrade without disruption. - -For parachains, upgrades are more complex. Parachains must first call `authorize_upgrade`, followed by `apply_authorized_upgrade`, to ensure the relay chain approves and applies the changes. Additionally, changes to current functionality that impact storage often require a [storage migration](#storage-migrations). - -### Runtime Versioning - -The executor is the component that selects the runtime execution environment to communicate with. Although you can override the default execution strategies for custom scenarios, in most cases, the executor selects the appropriate binary to use by evaluating and comparing key parameters from the native and Wasm runtime binaries. - -The runtime includes a [runtime version struct](https://paritytech.github.io/polkadot-sdk/master/sp_version/struct.RuntimeVersion.html){target=\_blank} to provide the needed parameter information to the executor process. A sample runtime version struct might look as follows: - -```rust -pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("node-template"), - impl_name: create_runtime_str!("node-template"), - authoring_version: 1, - spec_version: 1, - impl_version: 1, - apis: RUNTIME_API_VERSIONS, - transaction_version: 1, -}; -``` - -The struct provides the following parameter information to the executor: - -- **`spec_name`**: The identifier for the different runtimes. -- **`impl_name`**: The name of the implementation of the spec. Serves only to differentiate code of different implementation teams. -- **`authoring_version`**: The version of the authorship interface. An authoring node won't attempt to author blocks unless this is equal to its native runtime. -- **`spec_version`**: The version of the runtime specification. A full node won't attempt to use its native runtime in substitute for the on-chain Wasm runtime unless the `spec_name`, `spec_version`, and `authoring_version` are all the same between the Wasm and native binaries. Updates to the `spec_version` can be automated as a CI process. This parameter is typically incremented when there's an update to the `transaction_version`. -- **`impl_version`**: The version of the implementation of the specification. Nodes can ignore this. It is only used to indicate that the code is different. As long as the `authoring_version` and the `spec_version` are the same, the code might have changed, but the native and Wasm binaries do the same thing. In general, only non-logic-breaking optimizations would result in a change of the `impl_version`. -- **`transaction_version`**: The version of the interface for handling transactions. This parameter can be useful to synchronize firmware updates for hardware wallets or other signing devices to verify that runtime transactions are valid and safe to sign. This number must be incremented if there is a change in the index of the pallets in the `construct_runtime!` macro or if there are any changes to dispatchable functions, such as the number of parameters or parameter types. If `transaction_version` is updated, then the `spec_version` must also be updated. -- **`apis`**: A list of supported [runtime APIs](https://paritytech.github.io/polkadot-sdk/master/sp_api/macro.impl_runtime_apis.html){target=\_blank} along with their versions. - -The executor follows the same consensus-driven logic for both the native runtime and the Wasm runtime before deciding which to execute. Because runtime versioning is a manual process, there is a risk that the executor could make incorrect decisions if the runtime version is misrepresented or incorrectly defined. - -### Accessing the Runtime Version - -The runtime version can be accessed through the `state.getRuntimeVersion` RPC endpoint, which accepts an optional block identifier. It can also be accessed through the runtime metadata to understand the APIs the runtime exposes and how to interact with them. - -The runtime metadata should only change when the chain's [runtime `spec_version`](https://paritytech.github.io/polkadot-sdk/master/sp_version/struct.RuntimeVersion.html#structfield.spec_version){target=\_blank} changes. - -## Storage Migrations - -Some runtime upgrades require updating how data is stored to match new formats or layouts. This process is called a Storage Migration. It ensures the runtime can interpret existing state correctly after an upgrade. - -For detailed guidance, scenarios, and implementation patterns, see the [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/){target=\_blank} page. - - ---- - -Page Title: Set Up the Polkadot SDK Parachain Template - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md -- Canonical (HTML): https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/ -- Summary: Learn how to set up and run the Polkadot SDK Parachain Template locally, creating a ready-to-customize foundation for your parachain. - -# Set Up the Polkadot SDK Parachain Template - -## Introduction - -The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs. - -Among these, the [Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a preconfigured runtime with commonly used pallets, making it an ideal starting point for most parachain development projects. - -This guide walks you through the full process of working with this template. You will: - -- Set up the Polkadot SDK Parachain Template. -- Understand the project structure and key components. -- Verify your template is ready for development. -- Run the parachain template locally in development mode. - -By the end of this guide, you'll have a working template ready to customize and deploy as a parachain. - -## Prerequisites - -Before getting started, ensure you have done the following: - -- Completed the [Install Polkadot SDK](/parachains/install-polkadot-sdk/){target=\_blank} guide and successfully installed [Rust](https://www.rust-lang.org/){target=\_blank} and the required packages to set up your development environment. - -For this tutorial series, you need to use Rust `1.86`. Newer versions of the compiler may not work with this parachain template version. - -Run the following commands to set up the correct Rust version: - -=== "macOS" - - ```bash - rustup install 1.86 - rustup default 1.86 - rustup target add wasm32-unknown-unknown --toolchain 1.86-aarch64-apple-darwin - rustup component add rust-src --toolchain 1.86-aarch64-apple-darwin - ``` - -=== "Ubuntu" - - ```bash - rustup toolchain install 1.86.0 - rustup default 1.86.0 - rustup target add wasm32-unknown-unknown --toolchain 1.86.0 - rustup component add rust-src --toolchain 1.86.0 - ``` - -## Polkadot SDK Utility Tools - -This tutorial requires two essential tools: - -- [**Chain spec builder**](https://crates.io/crates/staging-chain-spec-builder/10.0.0){target=\_blank}: A Polkadot SDK utility for generating chain specifications. Refer to the [Generate Chain Specs](/develop/parachains/deployment/generate-chain-specs/){target=\_blank} documentation for detailed usage. - - Install it by executing the following command: - - ```bash - cargo install --locked staging-chain-spec-builder@10.0.0 - ``` - - This command installs the `chain-spec-builder` binary. - -- [**Polkadot Omni Node**](https://crates.io/crates/polkadot-omni-node/0.5.0){target=\_blank}: A white-labeled binary, released as a part of Polkadot SDK that can act as the collator of a parachain in production, with all the related auxiliary functionalities that a normal collator node has: RPC server, archiving state, etc. Moreover, it can also run the Wasm blob of the parachain locally for testing and development. - - To install it, run the following command: - - ```bash - cargo install --locked polkadot-omni-node@0.5.0 - ``` - - This command installs the `polkadot-omni-node` binary. - -## Clone the Template - -The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a ready-to-use development environment for building with the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. Follow these steps to set up the template: - -1. Clone the template repository: - - ```bash - git clone https://github.com/paritytech/polkadot-sdk-parachain-template.git parachain-template - ``` - -2. Navigate into the project directory: - - ```bash - cd parachain-template - ``` - -## Explore the Project Structure - -Before building the template, take a moment to familiarize yourself with its structure. Understanding this organization will help you navigate the codebase as you develop your parachain. - -The template follows a standard Polkadot SDK project layout: - -```text -parachain-template/ -├── node/ # Node implementation and client -├── pallets/ # Custom pallets for your parachain -├── runtime/ # Runtime configuration and logic -├── Cargo.toml # Workspace configuration -└── README.md # Documentation -``` - -Key directories explained: - -- **runtime/**: Contains your parachain's state transition function and pallet configuration. This is where you'll define what your blockchain can do. -- **node/**: Houses the client implementation that runs your blockchain, handles networking, and manages the database. -- **pallets/**: Where you'll create custom business logic modules (pallets) for your specific use case. -- **Cargo.toml**: The workspace configuration that ties all components together. - -!!!note - The runtime is compiled to WebAssembly (Wasm), enabling forkless upgrades. The node binary remains constant while the runtime can be updated on-chain. - -## Compile the Runtime - -Now that you understand the template structure, let's compile the runtime to ensure everything is working correctly. - -1. Compile the runtime: - - ```bash - cargo build --release --locked - ``` - - !!!tip - Initial compilation may take several minutes, depending on your machine specifications. Use the `--release` flag for improved runtime performance compared to the default `--debug` build. If you need to troubleshoot issues, the `--debug` build provides better diagnostics. - - For production deployments, consider using a dedicated `--profile production` flag - this can provide an additional 15-30% performance improvement over the standard `--release` profile. - -2. Upon successful compilation, you should see output indicating the build was successful. The compiled runtime will be located at: - - `./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm` - -## Verify the Build - -After compilation completes, verify that the runtime was created successfully by checking for the Wasm blob: - -```bash -ls -la ./target/release/wbuild/parachain-template-runtime/ -``` - -You should see the `parachain_template_runtime.compact.compressed.wasm` file in the output, confirming the build was successful. - -## Run the Node Locally - -After successfully compiling your runtime, you can spin up a local chain and produce blocks. This process will start your local parachain using the Polkadot Omni Node and allow you to interact with it. You'll first need to generate a chain specification that defines your network's identity, initial connections, and genesis state, providing the foundational configuration for how your nodes connect and what initial state they agree upon. - -Follow these steps to launch your node in development mode: - -1. Generate the chain specification file of your parachain: - - ```bash - chain-spec-builder create -t development \ - --relay-chain paseo \ - --para-id 1000 \ - --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ - named-preset development - ``` - -2. Start the Omni Node with the generated chain spec. You'll start it in development mode (without a relay chain config), producing and finalizing blocks: - - ```bash - polkadot-omni-node --chain ./chain_spec.json --dev - ``` - - The `--dev` option does the following: - - - Deletes all active data (keys, blockchain database, networking information) when stopped. - - Ensures a clean working state each time you restart the node. - -3. Verify that your node is running by reviewing the terminal output. You should see log messages indicating block production and finalization. - -4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output. - -The details of the log output will be explored in a later tutorial. For now, knowing that your node is running and producing blocks is sufficient. - -## Interact with the Node - -When running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} interface, follow these steps: - -1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner: - - ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp) - -2. Connect to your local node: - - 1. Scroll to the bottom and select **Development**. - 2. Choose **Custom**. - 3. Enter `ws://localhost:9944` in the **custom endpoint** input field. - 4. Click the **Switch** button. - - ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp) - -3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain. - - ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp) - -You are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\_blank} available on the Polkadot Wiki. - -## Stop the Node - -When you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time. - -To stop the local node: - -1. Return to the terminal window where the node output is displayed. -2. Press `Control-C` to stop the running process. -3. Verify that your terminal returns to the prompt in the `parachain-template` directory. - -## Where to Go Next - -
    - -- Tutorial __Deploy to Polkadot__ - - --- - - Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks. - - [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md) - -
    - - ---- - -Page Title: Smart Contracts Cookbook Index - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/ -- Summary: Explore our full collection of tutorials and guides to learn step-by-step how to build, deploy, and work with smart contracts on Polkadot. - -# Smart Contracts Cookbook - -Welcome to the Polkadot smart contracts cookbook index. - -This page contains a list of all relevant tutorials and guides to help you get started coding smart contracts and dApps in Polkadot. - - - - -## Get Tokens from the Faucet - -| Title | Difficulty | Tools | Description | -|------------------------------------|:-----------:|-------|-----------------------------------------------------------------------------------------------------------------------| -| [Faucet](/smart-contracts/faucet/) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. | - -## EVM/PVM Smart Contracts - -| Title | Difficulty | Tools | Description | -|---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. | -| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | - -## Port Ethereum DApps - -| Title | Difficulty | Tools | Description | -|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| -| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | - - ---- - -Page Title: Smart Contracts Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ -- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. - -# Smart Contracts on Polkadot - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. - -Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. - -These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. - -## Native Smart Contracts - -### Introduction - -Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. - -### Smart Contract Development - -The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. - -Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. - -### Technical Architecture - -PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: - -- Enhanced performance for smart contract execution. -- Improved gas efficiency for complex operations. -- Native compatibility with Polkadot's runtime environment. -- Optimized storage and state management. - -### Development Tools and Resources - -Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: - -- Contract development in Solidity or Rust. -- Support for standard Ethereum development libraries. -- Integration with widely used development environments. -- Access to blockchain explorers and indexing solutions. -- Compatibility with contract monitoring and management tools. - -### Cross-Chain Capabilities - -Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. - -### Use Cases - -Polkadot Hub's smart contract platform is suitable for a wide range of applications: - -- DeFi protocols leveraging _cross-chain capabilities_. -- NFT platforms utilizing Polkadot's native token standards. -- Governance systems integrated with Polkadot's democracy mechanisms. -- Cross-chain bridges and asset management solutions. - -## Other Smart Contract Environments - -Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: - -- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). - -- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. - - -Each environment provides unique advantages based on developer preferences and application requirements. - -## Where to Go Next - -Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. - -Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. - -
    - -- Guide __Libraries__ - - --- - - Explore essential libraries to optimize smart contract development and interaction. - - [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) - -- Guide __Dev Environments__ - - --- - - Set up your development environment for seamless contract deployment and testing. - - [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) - -
    - - ---- - -Page Title: Storage Migrations - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md -- Canonical (HTML): https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/ -- Summary: Ensure smooth runtime upgrades with storage migrations, update data formats, and prevent errors. Learn when and how to implement migrations efficiently. - -# Storage Migrations - -## Introduction - -Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime state. - -Storage migrations must be executed precisely during the runtime upgrade process to ensure data consistency and prevent [runtime panics](https://doc.rust-lang.org/std/macro.panic.html){target=\_blank}. The migration code needs to run as follows: - -- After the new runtime is deployed. -- Before any other code from the new runtime executes. -- Before any [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hooks run. -- Before any transactions are processed. - -This timing is critical because the new runtime expects data to be in the updated format. Any attempt to decode the old data format without proper migration could result in runtime panics or undefined behavior. - -## Storage Migration Scenarios - -A storage migration is necessary whenever a runtime upgrade changes the storage layout or the encoding/interpretation of existing data. Even if the underlying data type appears to still "fit" the new storage representation, a migration may be required if the interpretation of the stored values has changed. - -Storage migrations ensure data consistency and prevent corruption during runtime upgrades. Below are common scenarios categorized by their impact on storage and migration requirements: - -- Migration required: - - Reordering or mutating fields of an existing data type to change the encoded/decoded data representation. - - Removal of a pallet or storage item warrants cleaning up storage via a migration to avoid state bloat. - -- Migration not required: - - Adding a new storage item would not require any migration since no existing data needs transformation. - - Adding or removing an extrinsic introduces no new interpretation of preexisting data, so no migration is required. - -The following are some common scenarios where a storage migration is needed: - -- **Changing data types**: Changing the underlying data type requires a migration to convert the existing values. - - ```rust - #[pallet::storage] - pub type FooValue = StorageValue<_, Foo>; - // old - pub struct Foo(u32) - // new - pub struct Foo(u64) - ``` - -- **Changing data representation**: Modifying the representation of the stored data, even if the size appears unchanged, requires a migration to ensure the runtime can correctly interpret the existing values. - - ```rust - #[pallet::storage] - pub type FooValue = StorageValue<_, Foo>; - // old - pub struct Foo(u32) - // new - pub struct Foo(i32) - // or - pub struct Foo(u16, u16) - ``` - -- **Extending an enum**: Adding new variants to an enum requires a migration if you reorder existing variants, insert new variants between existing ones, or change the data type of existing variants. No migration is required when adding new variants at the end of the enum. - - ```rust - #[pallet::storage] - pub type FooValue = StorageValue<_, Foo>; - // old - pub enum Foo { A(u32), B(u32) } - // new (New variant added at the end. No migration required) - pub enum Foo { A(u32), B(u32), C(u128) } - // new (Reordered variants. Requires migration) - pub enum Foo { A(u32), C(u128), B(u32) } - ``` - -- **Changing the storage key**: Modifying the storage key, even if the underlying data type remains the same, requires a migration to ensure the runtime can locate the correct stored values. - - ```rust - #[pallet::storage] - pub type FooValue = StorageValue<_, u32>; - // new - #[pallet::storage] - pub type BarValue = StorageValue<_, u32>; - ``` - -!!!warning - In general, any change to the storage layout or data encoding used in your runtime requires careful consideration of the need for a storage migration. Overlooking a necessary migration can lead to undefined behavior or data loss during a runtime upgrade. - -## Implement Storage Migrations - -The [`OnRuntimeUpgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.OnRuntimeUpgrade.html){target=\_blank} trait provides the foundation for implementing storage migrations in your runtime. Here's a detailed look at its essential functions: - -```rust -pub trait OnRuntimeUpgrade { - fn on_runtime_upgrade() -> Weight { ... } - fn try_on_runtime_upgrade(checks: bool) -> Result { ... } - fn pre_upgrade() -> Result, TryRuntimeError> { ... } - fn post_upgrade(_state: Vec) -> Result<(), TryRuntimeError> { ... } -} -``` - -### Core Migration Function - -The [`on_runtime_upgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_runtime_upgrade){target=\_blank} function executes when the FRAME Executive pallet detects a runtime upgrade. Important considerations when using this function include: - -- It runs before any pallet's `on_initialize` hooks. -- Critical storage items (like [`block_number`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.block_number){target=\_blank}) may not be set. -- Execution is mandatory and must be completed. -- Careful weight calculation is required to prevent bricking the chain. - -When implementing the migration logic, your code must handle several vital responsibilities. A migration implementation must do the following to operate correctly: - -- Read existing storage values in their original format. -- Transform data to match the new format. -- Write updated values back to storage. -- Calculate and return consumed weight. - -### Migration Testing Hooks - -The `OnRuntimeUpgrade` trait provides some functions designed specifically for testing migrations. These functions never execute on-chain but are essential for validating migration behavior in test environments. The migration test hooks are as follows: - -- **[`try_on_runtime_upgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.OnRuntimeUpgrade.html#method.try_on_runtime_upgrade){target=\_blank}**: This function serves as the primary orchestrator for testing the complete migration process. It coordinates the execution flow from `pre-upgrade` checks through the actual migration to `post-upgrade` verification. Handling the entire migration sequence ensures that storage modifications occur correctly and in the proper order. Preserving this sequence is particularly valuable when testing multiple dependent migrations, where the execution order matters. - -- **[`pre_upgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.pre_upgrade){target=\_blank}**: Before a runtime upgrade begins, the `pre_upgrade` function performs preliminary checks and captures the current state. It returns encoded state data that can be used for `post-upgrade` verification. This function must never modify storage: it should only read and verify the existing state. The data it returns includes critical state values that should remain consistent or transform predictably during migration. - -- **[`post_upgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.post_upgrade){target=\_blank}**: After the migration completes, `post_upgrade` validates its success. It receives the state data captured by `pre_upgrade` to verify that the migration was executed correctly. This function checks for storage consistency and ensures all data transformations are completed as expected. Like `pre_upgrade`, it operates exclusively in testing environments and should not modify storage. - -### Migration Structure - -There are two approaches to implementing storage migrations. The first method involves directly implementing `OnRuntimeUpgrade` on structs. This approach requires manually checking the on-chain storage version against the new [`StorageVersion`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/struct.StorageVersion.html){target=\_blank} and executing the transformation logic only when the check passes. This version verification prevents multiple executions of the migration during subsequent runtime upgrades. - -The recommended approach is to implement [`UncheckedOnRuntimeUpgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.UncheckedOnRuntimeUpgrade.html){target=\_blank} and wrap it with [`VersionedMigration`](https://paritytech.github.io/polkadot-sdk/master/frame_support/migrations/struct.VersionedMigration.html){target=\_blank}. `VersionedMigration` implements `OnRuntimeUpgrade` and handles storage version management automatically, following best practices and reducing potential errors. - -`VersionedMigration` requires five type parameters: - -- **`From`**: The source version for the upgrade. -- **`To`**: The target version for the upgrade. -- **`Inner`**: The `UncheckedOnRuntimeUpgrade` implementation. -- **`Pallet`**: The pallet being upgraded. -- **`Weight`**: The runtime's [`RuntimeDbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} implementation. - -Examine the following migration example that transforms a simple `StorageValue` storing a `u32` into a more complex structure that tracks both current and previous values using the `CurrentAndPreviousValue` struct: - -- Old `StorageValue` format: - - ```rust - #[pallet::storage] - pub type Value = StorageValue<_, u32>; - ``` - -- New `StorageValue` format: - - ```rust - /// Example struct holding the most recently set [`u32`] and the - /// second most recently set [`u32`] (if one existed). - #[docify::export] - #[derive( - Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen, - )] - pub struct CurrentAndPreviousValue { - /// The most recently set value. - pub current: u32, - /// The previous value, if one existed. - pub previous: Option, - } - #[pallet::storage] - pub type Value = StorageValue<_, CurrentAndPreviousValue>; - ``` - -- Migration: - - ```rust - use frame_support::{ - storage_alias, - traits::{Get, UncheckedOnRuntimeUpgrade}, - }; - - #[cfg(feature = "try-runtime")] - use alloc::vec::Vec; - - /// Collection of storage item formats from the previous storage version. - /// - /// Required so we can read values in the v0 storage format during the migration. - mod v0 { - use super::*; - - /// V0 type for [`crate::Value`]. - #[storage_alias] - pub type Value = StorageValue, u32>; - } - - /// Implements [`UncheckedOnRuntimeUpgrade`], migrating the state of this pallet from V0 to V1. - /// - /// In V0 of the template [`crate::Value`] is just a `u32`. In V1, it has been upgraded to - /// contain the struct [`crate::CurrentAndPreviousValue`]. - /// - /// In this migration, update the on-chain storage for the pallet to reflect the new storage - /// layout. - pub struct InnerMigrateV0ToV1(core::marker::PhantomData); - - impl UncheckedOnRuntimeUpgrade for InnerMigrateV0ToV1 { - /// Return the existing [`crate::Value`] so we can check that it was correctly set in - /// `InnerMigrateV0ToV1::post_upgrade`. - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { - use codec::Encode; - - // Access the old value using the `storage_alias` type - let old_value = v0::Value::::get(); - // Return it as an encoded `Vec` - Ok(old_value.encode()) - } - - /// Migrate the storage from V0 to V1. - /// - /// - If the value doesn't exist, there is nothing to do. - /// - If the value exists, it is read and then written back to storage inside a - /// [`crate::CurrentAndPreviousValue`]. - fn on_runtime_upgrade() -> frame_support::weights::Weight { - // Read the old value from storage - if let Some(old_value) = v0::Value::::take() { - // Write the new value to storage - let new = crate::CurrentAndPreviousValue { current: old_value, previous: None }; - crate::Value::::put(new); - // One read + write for taking the old value, and one write for setting the new value - T::DbWeight::get().reads_writes(1, 2) - } else { - // No writes since there was no old value, just one read for checking - T::DbWeight::get().reads(1) - } - } + ```toml title="relaychain-example-node-groups.toml" + [relaychain] + default_command = "polkadot" + default_image = "polkadot-debug:master" + chain = "rococo-local" + chain_spec_path = "INSERT_PATH_TO_CHAIN_SPEC" + default_args = ["--chain", "rococo-local"] - /// Verifies the storage was migrated correctly. - /// - /// - If there was no old value, the new value should not be set. - /// - If there was an old value, the new value should be a [`crate::CurrentAndPreviousValue`]. - #[cfg(feature = "try-runtime")] - fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { - use codec::Decode; - use frame_support::ensure; + [[relaychain.node_groups]] + name = "group-1" + count = 2 + image = "polkadot-debug:master" + command = "polkadot" + args = ["--chain", "rococo-local"] + # ... - let maybe_old_value = Option::::decode(&mut &state[..]).map_err(|_| { - sp_runtime::TryRuntimeError::Other("Failed to decode old value from storage") - })?; + ``` - match maybe_old_value { - Some(old_value) => { - let expected_new_value = - crate::CurrentAndPreviousValue { current: old_value, previous: None }; - let actual_new_value = crate::Value::::get(); +=== "JSON" - ensure!(actual_new_value.is_some(), "New value not set"); - ensure!( - actual_new_value == Some(expected_new_value), - "New value not set correctly" - ); - }, - None => { - ensure!(crate::Value::::get().is_none(), "New value unexpectedly set"); - }, - }; - Ok(()) - } + ```json title="relaychain-example-node-groups.json" + { + "relaychain": { + "default_command": "polkadot", + "default_image": "polkadot-debug:master", + "chain": "rococo-local", + "chain_spec_path": "INSERT_PATH_TO_CHAIN-SPEC.JSON", + "default_args": ["--chain", "rococo-local"], + "node_groups": [ + { + "name": "group-1", + "count": 2, + "image": "polkadot-debug:master", + "command": "polkadot", + "args": ["--chain", "rococo-local"] + } + ], + "...": {} + }, + "...": {} } - /// [`UncheckedOnRuntimeUpgrade`] implementation [`InnerMigrateV0ToV1`] wrapped in a - /// [`VersionedMigration`](frame_support::migrations::VersionedMigration), which ensures that: - /// - The migration only runs once when the on-chain storage version is 0 - /// - The on-chain storage version is updated to `1` after the migration executes - /// - Reads/Writes from checking/settings the on-chain storage version are accounted for - pub type MigrateV0ToV1 = frame_support::migrations::VersionedMigration< - 0, // The migration will only execute when the on-chain storage version is 0 - 1, // The on-chain storage version will be set to 1 after the migration is complete - InnerMigrateV0ToV1, - crate::pallet::Pallet, - ::DbWeight, - >; ``` -### Migration Organization +### Parachain Configuration -Best practices recommend organizing migrations in a separate module within your pallet. Here's the recommended file structure: +The `parachain` keyword defines further parameters for the parachain. The available keys are: -```plain -my-pallet/ -├── src/ -│ ├── lib.rs # Main pallet implementation -│ └── migrations/ # All migration-related code -│ ├── mod.rs # Migrations module definition -│ ├── v1.rs # V0 -> V1 migration -│ └── v2.rs # V1 -> V2 migration -└── Cargo.toml -``` +- **`id`** ++"number"++: The id to assign to this parachain. Must be unique. +- **`chain?`** ++"string"++: The chain name. +- **`force_decorator?`** ++"string"++: Force the use of a specific decorator. +- **`genesis?`** ++"JSON"++: The genesis configuration. +- **`balance?`** ++"number"++: Balance to set in balances for parachain's account. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -This structure provides several benefits: + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` -- Separates migration logic from core pallet functionality. -- Makes migrations easier to test and maintain. -- Provides explicit versioning of storage changes. -- Simplifies the addition of future migrations. +- **`add_to_genesis?`** ++"boolean"++: Flag to add parachain to genesis or register in runtime. Defaults to `true`. +- **`register_para?`** ++"boolean"++: Flag to specify whether the para should be registered. The `add_to_genesis` flag must be set to false for this flag to have any effect. Defaults to `true`. +- **`onboard_as_parachain?`** ++"boolean"++: Flag to specify whether the para should be onboarded as a parachain, rather than remaining a parathread. Defaults to `true`. +- **`genesis_wasm_path?`** ++"string"++: Path to the Wasm file to use. +- **`genesis_wasm_generator?`** ++"string"++: Command to generate the Wasm file. +- **`genesis_state_path?`** ++"string"++: Path to the state file to use. +- **`genesis_state_generator?`** ++"string"++: Command to generate the state file. +- **`chain_spec_path?`** ++"string"++: Path to the chain spec file. +- **`chain_spec_command?`** ++"string"++: Command to generate the chain spec. +- **`cumulus_based?`** ++"boolean"++: Flag to use cumulus command generation. Defaults to `true`. +- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. +- **`prometheus_prefix?`** ++"string"++: Parameter for customizing the metric's prefix for all parachain nodes/collators. Defaults to `substrate`. +- **`collator?`** ++"Collator"++: Further defined in the [Collator Configuration](#collator-configuration) section. +- **`collator_groups?`** ++"CollatorGroup[]"++: An array of collator groups to spawn. It is further defined in the [Collator Groups Configuration](#collator-groups-configuration) section. + +For example, the following configuration file defines a minimal example for the parachain: -### Scheduling Migrations +=== "TOML" -To execute migrations during a runtime upgrade, you must configure them in your runtime's Executive pallet. Add your migrations in `runtime/src/lib.rs`: + ```toml title="parachain-example.toml" + [parachain] + id = 100 + add_to_genesis = true + cumulus_based = true + genesis_wasm_path = "INSERT_PATH_TO_WASM" + genesis_state_path = "INSERT_PATH_TO_STATE" + # ... -```rust -/// Tuple of migrations (structs that implement `OnRuntimeUpgrade`) -type Migrations = ( - pallet_my_pallet::migrations::v1::Migration, - // More migrations can be added here -); -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, - Migrations, // Include migrations here ->; + ``` -``` +=== "JSON" -## Single-Block Migrations + ```json title="parachain-example.json" + { + "parachain": { + "id": 100, + "add_to_genesis": true, + "cumulus_based": true, + "genesis_wasm_path": "INSERT_PATH_TO_WASM", + "genesis_state_path": "INSERT_PATH_TO_STATE", + "...": {} + }, + "...": {} + } -Single-block migrations execute their logic within one block immediately following a runtime upgrade. They run as part of the runtime upgrade process through the `OnRuntimeUpgrade` trait implementation and must be completed before any other runtime logic executes. + ``` -While single-block migrations are straightforward to implement and provide immediate data transformation, they carry significant risks. The most critical consideration is that they must complete within one block's weight limits. This is especially crucial for parachains, where exceeding block weight limits will brick the chain. +#### Collator Configuration -Use single-block migrations only when you can guarantee: +One specific key capable of receiving more subkeys is the `collator` key. This key defines further parameters for the nodes. The available keys are: -- The migration has a bounded execution time. -- Weight calculations are thoroughly tested. -- Total weight will never exceed block limits. +- **`name`** ++"string"++: Name of the collator. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). +- **`image?`** ++"string"++: Image to use for the collator. +- **`command_with_args?`** ++"string"++: Overrides both command and arguments for the collator. +- **`validator`** ++"boolean"++: Pass the `--validator` flag to the command. Defaults to `true`. +- **`invulnerable`** ++"boolean"++: If true, add the collator to invulnerables in the chain spec. Defaults to `false`. +- **`balance`** ++"number"++: Balance to set in balances for collator's account. Defaults to `2000000000000`. +- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. +- **`add_to_bootnodes?`** ++"boolean"++: Add this collator to the bootnode list. Defaults to `false`. +- **`ws_port?`** ++"number"++: WS port to use. +- **`rpc_port?`** ++"number"++: RPC port to use. +- **`prometheus_port?`** ++"number"++: Prometheus port to use. +- **`p2p_port?`** ++"number"++: P2P port to use. +- **`p2p_cert_hash?`** ++"string"++: Libp2p certhash to use with webRTC transport. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -For a complete implementation example of a single-block migration, refer to the [single-block migration example]( https://paritytech.github.io/polkadot-sdk/master/pallet_example_single_block_migrations/index.html){target=\_blank} in the Polkadot SDK documentation. + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` -## Multi Block Migrations +- **`command?`** ++"string"++: Override default command to run. +- **`args?`** ++"string[]"++: Arguments to be passed to the command. +- **`env?`** ++"envVars[]"++: Environment variables to set in the container. -Multi-block migrations distribute the migration workload across multiple blocks, providing a safer approach for production environments. The migration state is tracked in storage, allowing the process to pause and resume across blocks. + ??? child "`envVars` interface definition" + ```js + export interface EnvVars { + name: string; + value: string; + } + ``` -This approach is essential for production networks and parachains as the risk of exceeding block weight limits is eliminated. Multi-block migrations can safely handle large storage collections, unbounded data structures, and complex nested data types where weight consumption might be unpredictable. +- **`overrides?`** ++"Override[]"++: Array of overrides definitions. -Multi-block migrations are ideal when dealing with: + ??? child "`Override` interface definition" + ```js + export interface Override { + local_path: string; + remote_name: string; + } + ``` -- Large-scale storage migrations. -- Unbounded storage items or collections. -- Complex data structures with uncertain weight costs. +- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. +- **`db_snapshot?`** ++"string"++: Database snapshot to use. +- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. -The primary trade-off is increased implementation complexity, as you must manage the migration state and handle partial completion scenarios. However, multi-block migrations' significant safety benefits and operational reliability are typically worth the increased complexity. + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } + ``` + +- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. + + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` -For a complete implementation example of multi-block migrations, refer to the [official example](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/examples/multi-block-migrations){target=\_blank} in the Polkadot SDK. +- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. +The configuration file below defines a minimal example for the collator: ---- +=== "TOML" -Page Title: Technical Reference Overview + ```toml title="collator-example.toml" + [parachain] + id = 100 + add_to_genesis = true + cumulus_based = true + genesis_wasm_path = "INSERT_PATH_TO_WASM" + genesis_state_path = "INSERT_PATH_TO_STATE" -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md -- Canonical (HTML): https://docs.polkadot.com/reference/ -- Summary: Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. + [[parachain.collators]] + name = "alice" + image = "polkadot-parachain" + command = "polkadot-parachain" + # ... -## Introduction + ``` -The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need. +=== "JSON" -Polkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\_blank} to the [governance](/reference/glossary#governance){target=\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants. + ```json title="collator-example.json" + { + "parachain": { + "id": 100, + "add_to_genesis": true, + "cumulus_based": true, + "genesis_wasm_path": "INSERT_PATH_TO_WASM", + "genesis_state_path": "INSERT_PATH_TO_STATE", + "collators": [ + { + "name": "alice", + "image": "polkadot-parachain", + "command": "polkadot-parachain", + "...": {} + } + ] + }, + "...": {} + } -This guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem. + ``` -## Polkadot Hub +#### Collator Groups Configuration -[Polkadot Hub](/reference/polkadot-hub/){target=\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain. +The `collator_groups` key defines further parameters for the collator groups. The available keys are: -The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: +- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). +- **`image?`** ++"string"++: Override default Docker image to use for this node. +- **`command?`** ++"string"++: Override default command to run. +- **`args?`** ++"string[]"++: Arguments to be passed to the command. +- **`env?`** ++"envVars[]"++: Environment variables to set in the container. -- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications. -- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem. -- **Staking**: Participate in network security and earn rewards by staking DOT. -- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov. -- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities. -- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem. -- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations. + ??? child "`envVars` interface definition" + ```js + export interface EnvVars { + name: string; + value: string; + } + ``` -## Parachains +- **`overrides?`** ++"Override[]"++: Array of overrides definitions. -[Parachains](/reference/parachains/){target=\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers: + ??? child "`Override` interface definition" + ```js + export interface Override { + local_path: string; + remote_name: string; + } + ``` -- **Accounts**: Deep dive into account types, storage, and management on parachains. -- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms. -- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus. -- **Chain data**: Explore data structures, storage layouts, and state management. -- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains. -- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility. -- **Networks**: Learn about networking protocols and peer-to-peer communication. -- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\_blank}, the standard for cross-chain communication. -- **Randomness**: Understand how randomness is generated and used in Polkadot chains. -- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. +- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. +- **`db_snapshot?`** ++"string"++: Database snapshot to use. +- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. -## On-Chain Governance + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } + ``` -[On-Chain governance](/reference/governance/){target=\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details: +- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. -- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums. -- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity. -- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance. -- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system. + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` -## Glossary +- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. +- **`count`** ++"number | string"++: Number of nodes to launch for this group. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` -- Blockchain concepts (blocks, transactions, state) -- Consensus mechanisms (validators, collators, finality) -- Polkadot-specific terms (relay chain, parachain, XCM, FRAME) -- Network components (nodes, runtimes, storage) -- Governance terminology (origins, tracks, referendums) +For instance, the configuration file below defines a minimal example for the collator groups: -## Tools +=== "TOML" -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: + ```toml title="collator-groups-example.toml" + [parachain] + id = 100 + add_to_genesis = true + cumulus_based = true + genesis_wasm_path = "INSERT_PATH_TO_WASM" + genesis_state_path = "INSERT_PATH_TO_STATE" -- **Light clients**: Lightweight solutions for interacting with the network without running full nodes. -- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\_blank} and [PAPI](/reference/tools/papi/){target=\_blank} for building applications. -- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\_blank} and other Rust-based libraries for SDK development. -- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\_blank} for Python developers. -- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\_blank}, and [Omninode](/reference/tools/omninode/){target=\_blank} for smart contract and parachain testing. -- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\_blank} for substrate interaction. -- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\_blank} for XCM integration and asset transfers. + [[parachain.collator_groups]] + name = "group-1" + count = 2 + image = "polkadot-parachain" + command = "polkadot-parachain" + # ... -## Where to Go Next + ``` -For detailed exploration of specific areas, proceed to any of the main sections: +=== "JSON" -
    + ```json title="collator-groups-example.json" + { + "parachain": { + "id": 100, + "add_to_genesis": true, + "cumulus_based": true, + "genesis_wasm_path": "INSERT_PATH_TO_WASM", + "genesis_state_path": "INSERT_PATH_TO_STATE", + "collator_groups": [ + { + "name": "group-1", + "count": 2, + "image": "polkadot-parachain", + "command": "polkadot-parachain", + "...": {} + } + ] + }, + "...": {} + } -- Learn **Polkadot Hub** + ``` - --- +### XCM Configuration - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. +You can use the `hrmp_channels` keyword to define further parameters for the XCM channels at start-up. The available keys are: - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) +- **`hrmp_channels`** ++"HrmpChannelsConfig[]"++: Array of Horizontal Relay-routed Message Passing (HRMP) channel configurations. -- Learn **Parachains** + ??? child "`HrmpChannelsConfig` interface definition" + ```js + export interface HrmpChannelsConfig { + sender: number; + recipient: number; + max_capacity: number; + max_message_size: number; + } + ``` + Each of the `HrmpChannelsConfig` keys are defined as follows: - --- + - **`sender` ++"number"++**: Parachain ID of the sender. + - **`recipient` ++"number"++**: Parachain ID of the recipient. + - **`max_capacity` ++"number"++**: Maximum capacity of the HRMP channel. + - **`max_message_size` ++"number"++**: Maximum message size allowed in the HRMP channel. - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. +## Where to Go Next - [:octicons-arrow-right-24: Reference](/reference/parachains/) +
    -- Learn **On-Chain Governance** +- External __Zombienet Support__ --- - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. - - [:octicons-arrow-right-24: Reference](/reference/governance/) + [Parity Technologies](https://www.parity.io/){target=\_blank} has designed and developed this framework, now maintained by the Zombienet team. -- Guide **Glossary** + For further support and information, refer to the following contact points: - --- + [:octicons-arrow-right-24: Zombienet repository](https://github.com/paritytech/zombienet){target=\_blank} - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. + [:octicons-arrow-right-24: Element public channel](https://matrix.to/#/!FWyuEyNvIFygLnWNMh:parity.io?via=parity.io&via=matrix.org&via=web3.foundation){target=\_blank} - [:octicons-arrow-right-24: Reference](/reference/glossary/) -- Guide **Tools** +- Tutorial __Spawn a Basic Chain with Zombienet__ --- - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. + Learn to spawn, connect to and monitor a basic blockchain network with Zombienet, using customizable configurations for streamlined development and debugging. - [:octicons-arrow-right-24: Reference](/reference/tools/) + [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/spawn-basic-chain/)
    --- -Page Title: Transactions +Page Title: Runtime Upgrades -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/ -- Summary: Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md +- Canonical (HTML): https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/ +- Summary: This page covers how runtime versioning and storage migration support forkless upgrades for Polkadot SDK-based networks and how they factor into chain upgrades. -# Transactions +# Runtime Upgrades ## Introduction -Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions. - -This guide walks you through the different transaction types and how they're formatted, validated, and processed within the Polkadot ecosystem. You'll also learn how to customize transaction formats and construct transactions for FRAME-based runtimes, ensuring a complete understanding of how transactions are built and executed in Polkadot SDK-based chains. - -## What Is a Transaction? - -In the Polkadot SDK, transactions represent operations that modify the chain's state, bundled into blocks for execution. The term extrinsic is often used to refer to any data that originates outside the runtime and is included in the chain. While other blockchain systems typically refer to these operations as "transactions," the Polkadot SDK adopts the broader term "extrinsic" to capture the wide variety of data types that can be added to a block. - -There are three primary types of transactions (extrinsics) in the Polkadot SDK: +One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption. -- **Signed transactions**: Signed by the submitting account, often carrying transaction fees. -- **Unsigned transactions**: Submitted without a signature, often requiring custom validation logic. -- **Inherent transactions**: Typically inserted directly into blocks by block authoring nodes, without gossiping between peers. +Forkless upgrades are achieved through WebAssembly (Wasm) runtimes stored on-chain, which can be securely swapped and upgraded as part of the blockchain's state. By leveraging decentralized consensus, runtime updates can happen trustlessly, ensuring continuous improvement and evolution without halting operations. -Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. +This guide explains how Polkadot's runtime versioning, Wasm deployment, and storage migrations enable these upgrades, ensuring the blockchain evolves smoothly and securely. You'll also learn how different upgrade processes apply to solo chains and parachains, depending on the network setup. -### Signed Transactions +## How Runtime Upgrades Work -Signed transactions require an account's signature and typically involve submitting a request to execute a runtime call. The signature serves as a form of cryptographic proof that the sender has authorized the action, using their private key. These transactions often involve a transaction fee to cover the cost of execution and incentivize block producers. +In FRAME, the [`system`](https://paritytech.github.io/polkadot-sdk/master/frame_system/index.html){target=\_blank} pallet uses the [`set_code`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/enum.Call.html#variant.set_code){target=\_blank} extrinsic to update the Wasm code for the runtime. This method allows solo chains to upgrade without disruption. -Signed transactions are the most common type of transaction and are integral to user-driven actions, such as token transfers. For instance, when you transfer tokens from one account to another, the sending account must sign the transaction to authorize the operation. +For parachains, upgrades are more complex. Parachains must first call `authorize_upgrade`, followed by `apply_authorized_upgrade`, to ensure the relay chain approves and applies the changes. Additionally, changes to current functionality that impact storage often require a [storage migration](#storage-migrations). -For example, the [`pallet_balances::Call::transfer_allow_death`](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/pallet/struct.Pallet.html#method.transfer_allow_death){target=\_blank} extrinsic in the Balances pallet allows you to transfer tokens. Since your account initiates this transaction, your account key is used to sign it. You'll also be responsible for paying the associated transaction fee, with the option to include an additional tip to incentivize faster inclusion in the block. +### Runtime Versioning -### Unsigned Transactions +The executor is the component that selects the runtime execution environment to communicate with. Although you can override the default execution strategies for custom scenarios, in most cases, the executor selects the appropriate binary to use by evaluating and comparing key parameters from the native and Wasm runtime binaries. -Unsigned transactions do not require a signature or account-specific data from the sender. Unlike signed transactions, they do not come with any form of economic deterrent, such as fees, which makes them susceptible to spam or replay attacks. Custom validation logic must be implemented to mitigate these risks and ensure these transactions are secure. +The runtime includes a [runtime version struct](https://paritytech.github.io/polkadot-sdk/master/sp_version/struct.RuntimeVersion.html){target=\_blank} to provide the needed parameter information to the executor process. A sample runtime version struct might look as follows: -Unsigned transactions typically involve scenarios where including a fee or signature is unnecessary or counterproductive. However, due to the absence of fees, they require careful validation to protect the network. For example, [`pallet_im_online::Call::heartbeat`](https://paritytech.github.io/polkadot-sdk/master/pallet_im_online/pallet/struct.Pallet.html#method.heartbeat){target=\_blank} extrinsic allows validators to send a heartbeat signal, indicating they are active. Since only validators can make this call, the logic embedded in the transaction ensures that the sender is a validator, making the need for a signature or fee redundant. +```rust +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("node-template"), + impl_name: create_runtime_str!("node-template"), + authoring_version: 1, + spec_version: 1, + impl_version: 1, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, +}; +``` -Unsigned transactions are more resource-intensive than signed ones because custom validation is required, but they play a crucial role in certain operational scenarios, especially when regular user accounts aren't involved. +The struct provides the following parameter information to the executor: -### Inherent Transactions +- **`spec_name`**: The identifier for the different runtimes. +- **`impl_name`**: The name of the implementation of the spec. Serves only to differentiate code of different implementation teams. +- **`authoring_version`**: The version of the authorship interface. An authoring node won't attempt to author blocks unless this is equal to its native runtime. +- **`spec_version`**: The version of the runtime specification. A full node won't attempt to use its native runtime in substitute for the on-chain Wasm runtime unless the `spec_name`, `spec_version`, and `authoring_version` are all the same between the Wasm and native binaries. Updates to the `spec_version` can be automated as a CI process. This parameter is typically incremented when there's an update to the `transaction_version`. +- **`impl_version`**: The version of the implementation of the specification. Nodes can ignore this. It is only used to indicate that the code is different. As long as the `authoring_version` and the `spec_version` are the same, the code might have changed, but the native and Wasm binaries do the same thing. In general, only non-logic-breaking optimizations would result in a change of the `impl_version`. +- **`transaction_version`**: The version of the interface for handling transactions. This parameter can be useful to synchronize firmware updates for hardware wallets or other signing devices to verify that runtime transactions are valid and safe to sign. This number must be incremented if there is a change in the index of the pallets in the `construct_runtime!` macro or if there are any changes to dispatchable functions, such as the number of parameters or parameter types. If `transaction_version` is updated, then the `spec_version` must also be updated. +- **`apis`**: A list of supported [runtime APIs](https://paritytech.github.io/polkadot-sdk/master/sp_api/macro.impl_runtime_apis.html){target=\_blank} along with their versions. -Inherent transactions are a specialized type of unsigned transaction that is used primarily for block authoring. Unlike signed or other unsigned transactions, inherent transactions are added directly by block producers and are not broadcasted to the network or stored in the transaction queue. They don't require signatures or the usual validation steps and are generally used to insert system-critical data directly into blocks. +The executor follows the same consensus-driven logic for both the native runtime and the Wasm runtime before deciding which to execute. Because runtime versioning is a manual process, there is a risk that the executor could make incorrect decisions if the runtime version is misrepresented or incorrectly defined. -A key example of an inherent transaction is inserting a timestamp into each block. The [`pallet_timestamp::Call::now`](https://paritytech.github.io/polkadot-sdk/master/pallet_timestamp/pallet/struct.Pallet.html#method.now-1){target=\_blank} extrinsic allows block authors to include the current time in the block they are producing. Since the block producer adds this information, there is no need for transaction validation, like signature verification. The validation in this case is done indirectly by the validators, who check whether the timestamp is within an acceptable range before finalizing the block. +### Accessing the Runtime Version -Another example is the [`paras_inherent::Call::enter`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/paras_inherent/pallet/struct.Pallet.html#method.enter){target=\_blank} extrinsic, which enables parachain collator nodes to send validation data to the relay chain. This inherent transaction ensures that the necessary parachain data is included in each block without the overhead of gossiped transactions. +The runtime version can be accessed through the `state.getRuntimeVersion` RPC endpoint, which accepts an optional block identifier. It can also be accessed through the runtime metadata to understand the APIs the runtime exposes and how to interact with them. -Inherent transactions serve a critical role in block authoring by allowing important operational data to be added directly to the chain without needing the validation processes required for standard transactions. +The runtime metadata should only change when the chain's [runtime `spec_version`](https://paritytech.github.io/polkadot-sdk/master/sp_version/struct.RuntimeVersion.html#structfield.spec_version){target=\_blank} changes. -## Transaction Formats +## Storage Migrations -Understanding the structure of signed and unsigned transactions is crucial for developers building on Polkadot SDK-based chains. Whether you're optimizing transaction processing, customizing formats, or interacting with the transaction pool, knowing the format of extrinsics, Polkadot's term for transactions, is essential. +Some runtime upgrades require updating how data is stored to match new formats or layouts. This process is called a Storage Migration. It ensures the runtime can interpret existing state correctly after an upgrade. -### Types of Transaction Formats +For detailed guidance, scenarios, and implementation patterns, see the [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/){target=\_blank} page. -In Polkadot SDK-based chains, extrinsics can fall into three main categories: -- **Unchecked extrinsics**: Typically used for signed transactions that require validation. They contain a signature and additional data, such as a nonce and information for fee calculation. Unchecked extrinsics are named as such because they require validation checks before being accepted into the transaction pool. -- **Checked extrinsics**: Typically used for inherent extrinsics (unsigned transactions); these don't require signature verification. Instead, they carry information such as where the extrinsic originates and any additional data required for the block authoring process. -- **Opaque extrinsics**: Used when the format of an extrinsic is not yet fully committed or finalized. They are still decodable, but their structure can be flexible depending on the context. +--- -### Signed Transaction Data Structure +Page Title: Set Up the Polkadot SDK Parachain Template -A signed transaction typically includes the following components: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md +- Canonical (HTML): https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/ +- Summary: Learn how to set up and run the Polkadot SDK Parachain Template locally, creating a ready-to-customize foundation for your parachain. -- **Signature**: Verifies the authenticity of the transaction sender. -- **Call**: The actual function or method call the transaction is requesting (for example, transferring funds). -- **Nonce**: Tracks the number of prior transactions sent from the account, helping to prevent replay attacks. -- **Tip**: An optional incentive to prioritize the transaction in block inclusion. -- **Additional data**: Includes details such as spec version, block hash, and genesis hash to ensure the transaction is valid within the correct runtime and chain context. +# Set Up the Polkadot SDK Parachain Template -Here's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime: +## Introduction -``` code - + + -``` +The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs. -Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. +Among these, the [Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a preconfigured runtime with commonly used pallets, making it an ideal starting point for most parachain development projects. -### Signed Extensions +This guide walks you through the full process of working with this template. You will: -Polkadot SDK also provides the concept of [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}, which allow developers to extend extrinsics with additional data or validation logic before they are included in a block. The [`SignedExtension`](https://paritytech.github.io/try-runtime-cli/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} set helps enforce custom rules or protections, such as ensuring the transaction's validity or calculating priority. +- Set up the Polkadot SDK Parachain Template. +- Understand the project structure and key components. +- Verify your template is ready for development. +- Run the parachain template locally in development mode. -The transaction queue regularly calls signed extensions to verify a transaction's validity before placing it in the ready queue. This safeguard ensures transactions won't fail in a block. Signed extensions are commonly used to enforce validation logic and protect the transaction pool from spam and replay attacks. +By the end of this guide, you'll have a working template ready to customize and deploy as a parachain. -In FRAME, a signed extension can hold any of the following types by default: +## Prerequisites -- **[`AccountId`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/types_common/type.AccountId.html){target=\_blank}**: To encode the sender's identity. -- **[`Call`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Call){target=\_blank}**: To encode the pallet call to be dispatched. This data is used to calculate transaction fees. -- **[`AdditionalSigned`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.AdditionalSigned){target=\_blank}**: To handle any additional data to go into the signed payload allowing you to attach any custom logic prior to dispatching a transaction. -- **[`Pre`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Pre){target=\_blank}**: To encode the information that can be passed from before a call is dispatched to after it gets dispatched. +Before getting started, ensure you have done the following: -Signed extensions can enforce checks like: +- Completed the [Install Polkadot SDK](/parachains/install-polkadot-sdk/){target=\_blank} guide and successfully installed [Rust](https://www.rust-lang.org/){target=\_blank} and the required packages to set up your development environment. -- **[`CheckSpecVersion`](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/extensions/check_spec_version.rs.html){target=\_blank}**: Ensures the transaction is compatible with the runtime's current version. -- **[`CheckWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.CheckWeight.html){target=\_blank}**: Calculates the weight (or computational cost) of the transaction, ensuring the block doesn't exceed the maximum allowed weight. +For this tutorial series, you need to use Rust `1.86`. Newer versions of the compiler may not work with this parachain template version. -These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. +Run the following commands to set up the correct Rust version: -## Transaction Construction +=== "macOS" -Building transactions in the Polkadot SDK involves constructing a payload that can be verified, signed, and submitted for inclusion in a block. Each runtime in the Polkadot SDK has its own rules for validating and executing transactions, but there are common patterns for constructing a signed transaction. + ```bash + rustup install 1.86 + rustup default 1.86 + rustup target add wasm32-unknown-unknown --toolchain 1.86-aarch64-apple-darwin + rustup component add rust-src --toolchain 1.86-aarch64-apple-darwin + ``` -### Construct a Signed Transaction +=== "Ubuntu" -A signed transaction in the Polkadot SDK includes various pieces of data to ensure security, prevent replay attacks, and prioritize processing. Here's an overview of how to construct one: + ```bash + rustup toolchain install 1.86.0 + rustup default 1.86.0 + rustup target add wasm32-unknown-unknown --toolchain 1.86.0 + rustup component add rust-src --toolchain 1.86.0 + ``` -1. **Construct the unsigned payload**: Gather the necessary information for the call, including: +## Polkadot SDK Utility Tools - - **Pallet index**: Identifies the pallet where the runtime function resides. - - **Function index**: Specifies the particular function to call in the pallet. - - **Parameters**: Any additional arguments required by the function call. +This tutorial requires two essential tools: -2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: +- [**Chain spec builder**](https://crates.io/crates/staging-chain-spec-builder/10.0.0){target=\_blank}: A Polkadot SDK utility for generating chain specifications. Refer to the [Generate Chain Specs](/develop/parachains/deployment/generate-chain-specs/){target=\_blank} documentation for detailed usage. + + Install it by executing the following command: + + ```bash + cargo install --locked staging-chain-spec-builder@10.0.0 + ``` - - **Transaction nonce**: Unique identifier to prevent replay attacks. - - **Era information**: Defines how long the transaction is valid before it's dropped from the pool. - - **Block hash**: Ensures the transaction doesn't execute on the wrong chain or fork. + This command installs the `chain-spec-builder` binary. -3. **Sign the payload**: Using the sender's private key, sign the payload to ensure that the transaction can only be executed by the account holder. -4. **Serialize the signed payload**: Once signed, the transaction must be serialized into a binary format, ensuring the data is compact and easy to transmit over the network. -5. **Submit the serialized transaction**: Finally, submit the serialized transaction to the network, where it will enter the transaction pool and wait for processing by an authoring node. +- [**Polkadot Omni Node**](https://crates.io/crates/polkadot-omni-node/0.5.0){target=\_blank}: A white-labeled binary, released as a part of Polkadot SDK that can act as the collator of a parachain in production, with all the related auxiliary functionalities that a normal collator node has: RPC server, archiving state, etc. Moreover, it can also run the Wasm blob of the parachain locally for testing and development. -The following is an example of how a signed transaction might look: + To install it, run the following command: -``` rust -node_runtime::UncheckedExtrinsic::new_signed( - function.clone(), // some call - sp_runtime::AccountId32::from(sender.public()).into(), // some sending account - node_runtime::Signature::Sr25519(signature.clone()), // the account's signature - extra.clone(), // the signed extensions -) -``` + ```bash + cargo install --locked polkadot-omni-node@0.5.0 + ``` -### Transaction Encoding + This command installs the `polkadot-omni-node` binary. -Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: +## Clone the Template -- **`[1]`**: Compact encoded length in bytes of the entire transaction. -- **`[2]`**: A u8 containing 1 byte to indicate whether the transaction is signed or unsigned (1 bit) and the encoded transaction version ID (7 bits). -- **`[3]`**: If signed, this field contains an account ID, an SR25519 signature, and some extra data. -- **`[4]`**: Encoded call data, including pallet and function indices and any required arguments. +The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a ready-to-use development environment for building with the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. Follow these steps to set up the template: -This encoded format ensures consistency and efficiency in processing transactions across the network. By adhering to this format, applications can construct valid transactions and pass them to the network for execution. +1. Clone the template repository: -To learn more about how compact encoding works using SCALE, see the [SCALE Codec](https://github.com/paritytech/parity-scale-codec){target=\_blank} README on GitHub. + ```bash + git clone https://github.com/paritytech/polkadot-sdk-parachain-template.git parachain-template + ``` -### Customize Transaction Construction +2. Navigate into the project directory: -Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: + ```bash + cd parachain-template + ``` -- **Custom pallets**: You can define new pallets with custom function calls, each with its own parameters and validation logic. -- **Signed extensions**: Developers can implement custom extensions that modify how transactions are prioritized, validated, or included in blocks. +## Explore the Project Structure -By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. +Before building the template, take a moment to familiarize yourself with its structure. Understanding this organization will help you navigate the codebase as you develop your parachain. -## Lifecycle of a Transaction +The template follows a standard Polkadot SDK project layout: -In the Polkadot SDK, transactions are often referred to as extrinsics because the data in transactions originates outside of the runtime. These transactions contain data that initiates changes to the chain state. The most common type of extrinsic is a signed transaction, which is cryptographically verified and typically incurs a fee. This section focuses on how signed transactions are processed, validated, and ultimately included in a block. +```text +parachain-template/ +├── node/ # Node implementation and client +├── pallets/ # Custom pallets for your parachain +├── runtime/ # Runtime configuration and logic +├── Cargo.toml # Workspace configuration +└── README.md # Documentation +``` -### Define Transaction Properties +Key directories explained: -The Polkadot SDK runtime defines key transaction properties, such as: +- **runtime/**: Contains your parachain's state transition function and pallet configuration. This is where you'll define what your blockchain can do. +- **node/**: Houses the client implementation that runs your blockchain, handles networking, and manages the database. +- **pallets/**: Where you'll create custom business logic modules (pallets) for your specific use case. +- **Cargo.toml**: The workspace configuration that ties all components together. -- **Transaction validity**: Ensures the transaction meets all runtime requirements. -- **Signed or unsigned**: Identifies whether a transaction needs to be signed by an account. -- **State changes**: Determines how the transaction modifies the state of the chain. +!!!note + The runtime is compiled to WebAssembly (Wasm), enabling forkless upgrades. The node binary remains constant while the runtime can be updated on-chain. -Pallets, which compose the runtime's logic, define the specific transactions that your chain supports. When a user submits a transaction, such as a token transfer, it becomes a signed transaction, verified by the user's account signature. If the account has enough funds to cover fees, the transaction is executed, and the chain's state is updated accordingly. +## Compile the Runtime -### Process on a Block Authoring Node +Now that you understand the template structure, let's compile the runtime to ensure everything is working correctly. -In Polkadot SDK-based networks, some nodes are authorized to author blocks. These nodes validate and process transactions. When a transaction is sent to a node that can produce blocks, it undergoes a lifecycle that involves several stages, including validation and execution. Non-authoring nodes gossip the transaction across the network until an authoring node receives it. The following diagram illustrates the lifecycle of a transaction that's submitted to a network and processed by an authoring node. +1. Compile the runtime: -![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } + ```bash + cargo build --release --locked + ``` -### Validate and Queue + !!!tip + Initial compilation may take several minutes, depending on your machine specifications. Use the `--release` flag for improved runtime performance compared to the default `--debug` build. If you need to troubleshoot issues, the `--debug` build provides better diagnostics. + + For production deployments, consider using a dedicated `--profile production` flag - this can provide an additional 15-30% performance improvement over the standard `--release` profile. -Once a transaction reaches an authoring node, it undergoes an initial validation process to ensure it meets specific conditions defined in the runtime. This validation includes checks for: +2. Upon successful compilation, you should see output indicating the build was successful. The compiled runtime will be located at: + + `./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm` -- **Correct nonce**: Ensures the transaction is sequentially valid for the account. -- **Sufficient funds**: Confirms the account can cover any associated transaction fees. -- **Signature validity**: Verifies that the sender's signature matches the transaction data. +## Verify the Build -After these checks, valid transactions are placed in the transaction pool, where they are queued for inclusion in a block. The transaction pool regularly re-validates queued transactions to ensure they remain valid before being processed. To reach consensus, two-thirds of the nodes must agree on the order of the transactions executed and the resulting state change. Transactions are validated and queued on the local node in a transaction pool to prepare for consensus. +After compilation completes, verify that the runtime was created successfully by checking for the Wasm blob: -#### Transaction Pool +```bash +ls -la ./target/release/wbuild/parachain-template-runtime/ +``` -The transaction pool is responsible for managing valid transactions. It ensures that only transactions that pass initial validity checks are queued. Transactions that fail validation, expire, or become invalid for other reasons are removed from the pool. +You should see the `parachain_template_runtime.compact.compressed.wasm` file in the output, confirming the build was successful. -The transaction pool organizes transactions into two queues: +## Run the Node Locally -- **Ready queue**: Transactions that are valid and ready to be included in a block. -- **Future queue**: Transactions that are not yet valid but could be in the future, such as transactions with a nonce too high for the current state. +After successfully compiling your runtime, you can spin up a local chain and produce blocks. This process will start your local parachain using the Polkadot Omni Node and allow you to interact with it. You'll first need to generate a chain specification that defines your network's identity, initial connections, and genesis state, providing the foundational configuration for how your nodes connect and what initial state they agree upon. -Details on how the transaction pool validates transactions, including fee and signature handling, can be found in the [`validate_transaction`](https://paritytech.github.io/polkadot-sdk/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction){target=\_blank} method. +Follow these steps to launch your node in development mode: -#### Invalid Transactions +1. Generate the chain specification file of your parachain: -If a transaction is invalid, for example, due to an invalid signature or insufficient funds, it is rejected and won't be added to the block. Invalid transactions might be rejected for reasons such as: + ```bash + chain-spec-builder create -t development \ + --relay-chain paseo \ + --para-id 1000 \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ + named-preset development + ``` -- The transaction has already been included in a block. -- The transaction's signature does not match the sender. -- The transaction is too large to fit in the current block. +2. Start the Omni Node with the generated chain spec. You'll start it in development mode (without a relay chain config), producing and finalizing blocks: -### Transaction Ordering and Priority + ```bash + polkadot-omni-node --chain ./chain_spec.json --dev + ``` -When a node is selected as the next block author, it prioritizes transactions based on weight, length, and tip amount. The goal is to fill the block with high-priority transactions without exceeding its maximum size or computational limits. Transactions are ordered as follows: + The `--dev` option does the following: -- **Inherents first**: Inherent transactions, such as block timestamp updates, are always placed first. -- **Nonce-based ordering**: Transactions from the same account are ordered by their nonce. -- **Fee-based ordering**: Among transactions with the same nonce or priority level, those with higher fees are prioritized. + - Deletes all active data (keys, blockchain database, networking information) when stopped. + - Ensures a clean working state each time you restart the node. -### Transaction Execution +3. Verify that your node is running by reviewing the terminal output. You should see log messages indicating block production and finalization. -Once a block author selects transactions from the pool, the transactions are executed in priority order. As each transaction is processed, the state changes are written directly to the chain's storage. It's important to note that these changes are not cached, meaning a failed transaction won't revert earlier state changes, which could leave the block in an inconsistent state. +4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output. -Events are also written to storage. Runtime logic should not emit an event before performing the associated actions. If the associated transaction fails after the event was emitted, the event will not revert. +The details of the log output will be explored in a later tutorial. For now, knowing that your node is running and producing blocks is sufficient. -## Transaction Mortality +## Interact with the Node -Transactions in the network can be configured as either mortal (with expiration) or immortal (without expiration). Every transaction payload contains a block checkpoint (reference block number and hash) and an era/validity period that determines how many blocks after the checkpoint the transaction remains valid. +When running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} interface, follow these steps: -When a transaction is submitted, the network validates it against these parameters. If the transaction is not included in a block within the specified validity window, it is automatically removed from the transaction queue. +1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner: + + ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp) -- **Mortal transactions**: Have a finite lifespan and will expire after a specified number of blocks. For example, a transaction with a block checkpoint of 1000 and a validity period of 64 blocks will be valid from blocks 1000 to 1064. +2. Connect to your local node: -- **Immortal transactions**: Never expire and remain valid indefinitely. To create an immortal transaction, set the block checkpoint to 0 (genesis block), use the genesis hash as a reference, and set the validity period to 0. + 1. Scroll to the bottom and select **Development**. + 2. Choose **Custom**. + 3. Enter `ws://localhost:9944` in the **custom endpoint** input field. + 4. Click the **Switch** button. + + ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp) -However, immortal transactions pose significant security risks through replay attacks. If an account is reaped (balance drops to zero, account removed) and later re-funded, malicious actors can replay old immortal transactions. +3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain. + + ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp) -The blockchain maintains only a limited number of prior block hashes for reference validation, called `BlockHashCount`. If your validity period exceeds `BlockHashCount`, the effective validity period becomes the minimum of your specified period and the block hash count. +You are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\_blank} available on the Polkadot Wiki. -## Unique Identifiers for Extrinsics +## Stop the Node -Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. +When you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time. -Key differences from traditional blockchains: +To stop the local node: -- Transaction hashes serve only as fingerprints of transaction information. -- Multiple valid transactions can share the same hash. -- Hash uniqueness assumptions lead to serious issues. +1. Return to the terminal window where the node output is displayed. +2. Press `Control-C` to stop the running process. +3. Verify that your terminal returns to the prompt in the `parachain-template` directory. -For example, when an account is reaped (removed due to insufficient balance) and later recreated, it resets to nonce 0, allowing identical transactions to be valid at different points: +## Where to Go Next -| Block | Extrinsic Index | Hash | Origin | Nonce | Call | Result | -|-------|----------------|------|-----------|-------|---------------------|-------------------------------| -| 100 | 0 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Account A reaped | -| 150 | 5 | 0x02 | Account B | 4 | Transfer 7 DOT to A | Account A created (nonce = 0) | -| 200 | 2 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Successful transaction | +
    -Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. +- Tutorial __Deploy to Polkadot__ -Additional complexity comes from Polkadot SDK's origin abstraction. Origins can represent collectives, governance bodies, or other non-account entities that don't maintain nonces like regular accounts and might dispatch identical calls multiple times with the same hash values. Each execution occurs in different chain states with different results. + --- -The correct way to uniquely identify an extrinsic on a Polkadot SDK-based chain is to use the block ID (height or hash) and the extrinsic index. Since the Polkadot SDK defines blocks as headers plus ordered arrays of extrinsics, the index position within a canonical block provides guaranteed uniqueness. + Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks. -## Additional Resources + [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md) -For a video overview of the lifecycle of transactions and the types of transactions that exist, see the [Transaction lifecycle](https://www.youtube.com/watch?v=3pfM0GOp02c){target=\_blank} seminar from Parity Tech. +
    --- -Page Title: Transactions and Fees on Asset Hub +Page Title: Smart Contracts Cookbook Index -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-blocks-transactions-fees.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/blocks-transactions-fees/ -- Summary: Explore how Asset Hub smart contracts handle blocks, transactions, and fees with EVM compatibility, supporting various Ethereum transaction types. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/ +- Summary: Explore our full collection of tutorials and guides to learn step-by-step how to build, deploy, and work with smart contracts on Polkadot. -# Blocks, Transactions, and Fees +# Smart Contracts Cookbook -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction +Welcome to the Polkadot smart contracts cookbook index. -Asset Hub smart contracts operate within the Polkadot ecosystem using the [`pallet_revive`](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/){target=\_blank} implementation, which provides EVM compatibility. While many aspects of blocks and transactions are inherited from the underlying parachain architecture, there are specific considerations and mechanisms unique to smart contract operations on Asset Hub. +This page contains a list of all relevant tutorials and guides to help you get started coding smart contracts and dApps in Polkadot. -## Smart Contract Blocks -Smart contract blocks in Asset Hub follow the same fundamental structure as parachain blocks, inheriting all standard parachain block components. The `pallet_revive` implementation maintains this consistency while adding necessary [EVM-specific features](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm){target=\_blank}. For detailed implementation specifics, the [`Block`](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.Block.html){target=\_blank} struct in `pallet_revive` demonstrates how parachain and smart contract block implementations align. -## Smart Contract Transactions -Asset Hub implements a sophisticated transaction system that supports various transaction types and formats, encompassing both traditional parachain operations and EVM-specific interactions. +## Get Tokens from the Faucet -### EVM Transaction Types +| Title | Difficulty | Tools | Description | +|------------------------------------|:-----------:|-------|-----------------------------------------------------------------------------------------------------------------------| +| [Faucet](/smart-contracts/faucet/) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. | -The system provides a fundamental [`eth_transact`](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/pallet/dispatchables/fn.eth_transact.html){target=\_blank} interface for processing raw EVM transactions dispatched through [Ethereum JSON-RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank}. This interface acts as a wrapper for Ethereum transactions, requiring an encoded signed transaction payload, though it cannot be dispatched directly. Building upon this foundation, the system supports multiple transaction formats to accommodate different use cases and optimization needs: +## EVM/PVM Smart Contracts -- **[Legacy transactions](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.TransactionLegacyUnsigned.html){target=\_blank}**: The original Ethereum transaction format, providing basic transfer and contract interaction capabilities. These transactions use a simple pricing mechanism and are supported for backward compatibility. +| Title | Difficulty | Tools | Description | +|---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. | +| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | -- **[EIP-1559 transactions](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.Transaction1559Unsigned.html){target=\_blank}**: An improved transaction format that introduces a more predictable fee mechanism with base fee and priority fee components. This format helps optimize gas fee estimation and network congestion management. +## Port Ethereum DApps -- **[EIP-2930 transactions](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.Transaction2930Unsigned.html){target=\_blank}**: Introduces access lists to optimize gas costs for contract interactions by pre-declaring accessed addresses and storage slots. +| Title | Difficulty | Tools | Description | +|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| +| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | -- **[EIP-4844 transactions](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.Transaction4844Unsigned.html){target=\_blank}**: Implements blob-carrying transactions, designed to optimize Layer 2 scaling solutions by providing dedicated space for roll-up data. -Each transaction type can exist in both signed and unsigned states, with appropriate validation and processing mechanisms for each. +--- -## Fees and Gas +Page Title: Smart Contracts Overview -Asset Hub implements a sophisticated resource management system that combines parachain transaction fees with EVM gas mechanics, providing both Ethereum compatibility and enhanced features. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ +- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. -### Gas Model Overview +# Smart Contracts on Polkadot -Gas serves as the fundamental unit for measuring computational costs, with each network operation consuming a specified amount. This implementation maintains compatibility with Ethereum's approach while adding parachain-specific optimizations. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -- **Dynamic gas scaling**: Asset Hub implements a dynamic pricing mechanism that reflects actual execution performance. This results in: +Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. - - More efficient pricing for computational instructions relative to I/O operations. - - Better correlation between gas costs and actual resource consumption. - - Need for developers to implement flexible gas calculation rather than hardcoding values. +Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. -- **Multi-dimensional resource metering**: Asset Hub extends beyond the traditional single-metric gas model to track three distinct resources. +These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. - - `ref_time` (computation time): +## Native Smart Contracts - - Functions as traditional gas equivalent. - - Measures actual computational resource usage. - - Primary metric for basic operation costs. +### Introduction +Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. - - `proof_size` (verification overhead): +### Smart Contract Development - - Tracks state proof size required for validator verification. - - Helps manage consensus-related resource consumption. - - Important for cross-chain operations. +The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. +Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. - - `storage_deposit` (state management): +### Technical Architecture - - Manages blockchain state growth. - - Implements a deposit-based system for long-term storage. - - Refundable when storage is freed. +PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: -These resources can be limited at both transaction and contract levels, similar to Ethereum's gas limits. For more information, check the [Gas Model](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm#gas-model){target=\_blank} section in the [EVM vs PolkaVM](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/){target=\_blank} article. +- Enhanced performance for smart contract execution. +- Improved gas efficiency for complex operations. +- Native compatibility with Polkadot's runtime environment. +- Optimized storage and state management. -### Fee Components +### Development Tools and Resources -- Base fees: +Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: - - Storage deposit for contract deployment. - - Minimum transaction fee for network access. - - Network maintenance costs. +- Contract development in Solidity or Rust. +- Support for standard Ethereum development libraries. +- Integration with widely used development environments. +- Access to blockchain explorers and indexing solutions. +- Compatibility with contract monitoring and management tools. -- Execution fees: +### Cross-Chain Capabilities - - Computed based on gas consumption. - - Converted to native currency using network-defined rates. - - Reflects actual computational resource usage. +Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. -- Storage fees: +### Use Cases - - Deposit for long-term storage usage. - - Refundable when storage is freed. - - Helps prevent state bloat. +Polkadot Hub's smart contract platform is suitable for a wide range of applications: -### Gas Calculation and Conversion +- DeFi protocols leveraging _cross-chain capabilities_. +- NFT platforms utilizing Polkadot's native token standards. +- Governance systems integrated with Polkadot's democracy mechanisms. +- Cross-chain bridges and asset management solutions. -The system maintains precise conversion mechanisms between: +## Other Smart Contract Environments -- Substrate weights and EVM gas units. -- Native currency and gas costs. -- Different resource metrics within the multi-dimensional model. +Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: -This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. +- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). +- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. ---- -Page Title: Transactions Weights and Fees +Each environment provides unique advantages based on developer preferences and application requirements. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/ -- Summary: Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. +## Where to Go Next -# Transactions Weights and Fees +Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. -## Introductions +Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. -When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop the network from producing new blocks. To protect blockchain resources from being drained or overloaded, you need to manage how they are made available and how they are consumed. The resources to be aware of include: +
    -- Memory usage -- Storage input and output -- Computation -- Transaction and block size -- State database size +- Guide __Libraries__ -The Polkadot SDK provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource. Two of the most important mechanisms available to block authors are weights and transaction fees. + --- -[Weights](/reference/glossary/#weight){target=\_blank} manage the time it takes to validate a block and characterize the time it takes to execute the calls in the block's body. By controlling the execution time a block can consume, weights set limits on storage input, output, and computation. + Explore essential libraries to optimize smart contract development and interaction. -Some of the weight allowed for a block is consumed as part of the block's initialization and finalization. The weight might also be used to execute mandatory inherent extrinsic calls. To help ensure blocks don’t consume too much execution time and prevent malicious users from overloading the system with unnecessary calls, weights are combined with transaction fees. + [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) -[Transaction fees](/reference/parachains/blocks-transactions-fees/transactions/#transaction-fees){target=\_blank} provide an economic incentive to limit execution time, computation, and the number of calls required to perform operations. Transaction fees are also used to make the blockchain economically sustainable because they are typically applied to transactions initiated by users and deducted before a transaction request is executed. +- Guide __Dev Environments__ -## How Fees are Calculated + --- -The final fee for a transaction is calculated using the following parameters: + Set up your development environment for seamless contract deployment and testing. -- **`base fee`**: This is the minimum amount a user pays for a transaction. It is declared a base weight in the runtime and converted to a fee using the [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} conversion. -- **`weight fee`**: A fee proportional to the execution time (input and output and computation) that a transaction consumes. -- **`length fee`**: A fee proportional to the encoded length of the transaction. -- **`tip`**: An optional tip to increase the transaction’s priority, giving it a higher chance to be included in the transaction queue. + [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) -The base fee and proportional weight and length fees constitute the inclusion fee. The inclusion fee is the minimum fee that must be available for a transaction to be included in a block. +
    -```text -inclusion fee = base fee + weight fee + length fee -``` -Transaction fees are withdrawn before the transaction is executed. After the transaction is executed, the weight can be adjusted to reflect the resources used. If a transaction uses fewer resources than expected, the transaction fee is corrected, and the adjusted transaction fee is deposited. +--- -## Using the Transaction Payment Pallet +Page Title: Storage Migrations -The [Transaction Payment pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/transaction-payment){target=\_blank} provides the basic logic for calculating the inclusion fee. You can also use the Transaction Payment pallet to: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md +- Canonical (HTML): https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/ +- Summary: Ensure smooth runtime upgrades with storage migrations, update data formats, and prevent errors. Learn when and how to implement migrations efficiently. -- Convert a weight value into a deductible fee based on a currency type using [`Config::WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank}. -- Update the fee for the next block by defining a multiplier based on the chain’s final state at the end of the previous block using [`Config::FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank}. -- Manage the withdrawal, refund, and deposit of transaction fees using [`Config::OnChargeTransaction`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.OnChargeTransaction){target=\_blank}. +# Storage Migrations -You can learn more about these configuration traits in the [Transaction Payment documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_payment/index.html){target=\_blank}. +## Introduction -### Understanding the Inclusion Fee +Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime state. -The formula for calculating the inclusion fee is as follows: +Storage migrations must be executed precisely during the runtime upgrade process to ensure data consistency and prevent [runtime panics](https://doc.rust-lang.org/std/macro.panic.html){target=\_blank}. The migration code needs to run as follows: -```text -inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] -``` +- After the new runtime is deployed. +- Before any other code from the new runtime executes. +- Before any [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hooks run. +- Before any transactions are processed. -And then, for calculating the final fee: +This timing is critical because the new runtime expects data to be in the updated format. Any attempt to decode the old data format without proper migration could result in runtime panics or undefined behavior. -```text -final_fee = inclusion_fee + tip -``` +## Storage Migration Scenarios -In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. +A storage migration is necessary whenever a runtime upgrade changes the storage layout or the encoding/interpretation of existing data. Even if the underlying data type appears to still "fit" the new storage representation, a migration may be required if the interpretation of the stored values has changed. -- The `base_fee` derived from the base weight covers inclusion overhead like signature verification. -- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic. -- The `weight_fee` fee is calculated using two parameters: - - The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics. - - The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity. +Storage migrations ensure data consistency and prevent corruption during runtime upgrades. Below are common scenarios categorized by their impact on storage and migration requirements: -To convert the weight to `Currency`, the runtime must define a `WeightToFee` struct that implements a conversion function, [`Convert`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/struct.Pallet.html#method.weight_to_fee){target=\_blank}. +- Migration required: + - Reordering or mutating fields of an existing data type to change the encoded/decoded data representation. + - Removal of a pallet or storage item warrants cleaning up storage via a migration to avoid state bloat. -Note that the extrinsic sender is charged the inclusion fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution. +- Migration not required: + - Adding a new storage item would not require any migration since no existing data needs transformation. + - Adding or removing an extrinsic introduces no new interpretation of preexisting data, so no migration is required. -### Accounts with an Insufficient Balance +The following are some common scenarios where a storage migration is needed: -If an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum existential deposit—then you should ensure the transaction is canceled so that no fee is deducted and the transaction does not begin execution. +- **Changing data types**: Changing the underlying data type requires a migration to convert the existing values. -The Polkadot SDK doesn't enforce this rollback behavior. However, this scenario would be rare because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block. + ```rust + #[pallet::storage] + pub type FooValue = StorageValue<_, Foo>; + // old + pub struct Foo(u32) + // new + pub struct Foo(u64) + ``` -### Fee Multipliers +- **Changing data representation**: Modifying the representation of the stored data, even if the size appears unchanged, requires a migration to ensure the runtime can correctly interpret the existing values. -The inclusion fee formula always results in the same fee for the same input. However, weight can be dynamic and—based on how [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} is defined—the final fee can include some degree of variability. -The Transaction Payment pallet provides the [`FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank} configurable parameter to account for this variability. + ```rust + #[pallet::storage] + pub type FooValue = StorageValue<_, Foo>; + // old + pub struct Foo(u32) + // new + pub struct Foo(i32) + // or + pub struct Foo(u16, u16) + ``` -The Polkadot network inspires the default update function and implements a targeted adjustment in which a target saturation level of block weight is defined. If the previous block is more saturated, the fees increase slightly. Similarly, if the last block has fewer transactions than the target, fees are decreased by a small amount. For more information about fee multiplier adjustments, see the [Web3 Research Page](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank}. +- **Extending an enum**: Adding new variants to an enum requires a migration if you reorder existing variants, insert new variants between existing ones, or change the data type of existing variants. No migration is required when adding new variants at the end of the enum. -## Transactions with Special Requirements + ```rust + #[pallet::storage] + pub type FooValue = StorageValue<_, Foo>; + // old + pub enum Foo { A(u32), B(u32) } + // new (New variant added at the end. No migration required) + pub enum Foo { A(u32), B(u32), C(u128) } + // new (Reordered variants. Requires migration) + pub enum Foo { A(u32), C(u128), B(u32) } + ``` -Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: +- **Changing the storage key**: Modifying the storage key, even if the underlying data type remains the same, requires a migration to ensure the runtime can locate the correct stored values. -- Bonds are a type of fee that might be returned or slashed after some on-chain event. For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior. -- Deposits are fees that might be returned later. For example, you might require users to pay a deposit to execute an operation that uses storage. The user’s deposit could be returned if a subsequent operation frees up storage. -- Burn operations are used to pay for a transaction based on its internal logic. For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased state size. -- Limits enable you to enforce constant or configurable limits on specific operations. For example, the default [Staking pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/staking){target=\_blank} only allows nominators to nominate 16 validators to limit the complexity of the validator election process. + ```rust + #[pallet::storage] + pub type FooValue = StorageValue<_, u32>; + // new + #[pallet::storage] + pub type BarValue = StorageValue<_, u32>; + ``` -It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. +!!!warning + In general, any change to the storage layout or data encoding used in your runtime requires careful consideration of the need for a storage migration. Overlooking a necessary migration can lead to undefined behavior or data loss during a runtime upgrade. -## Default Weight Annotations +## Implement Storage Migrations -All dispatchable functions in the Polkadot SDK must specify a weight. The way of doing that is using the annotation-based system that lets you combine fixed values for database read/write weight and/or fixed values based on benchmarks. The most basic example would look like this: +The [`OnRuntimeUpgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.OnRuntimeUpgrade.html){target=\_blank} trait provides the foundation for implementing storage migrations in your runtime. Here's a detailed look at its essential functions: ```rust -#[pallet::weight(100_000)] -fn my_dispatchable() { - // ... +pub trait OnRuntimeUpgrade { + fn on_runtime_upgrade() -> Weight { ... } + fn try_on_runtime_upgrade(checks: bool) -> Result { ... } + fn pre_upgrade() -> Result, TryRuntimeError> { ... } + fn post_upgrade(_state: Vec) -> Result<(), TryRuntimeError> { ... } } ``` -Note that the [`ExtrinsicBaseWeight`](https://crates.parity.io/frame_support/weights/constants/struct.ExtrinsicBaseWeight.html){target=\_blank} is automatically added to the declared weight to account for the costs of simply including an empty extrinsic into a block. +### Core Migration Function + +The [`on_runtime_upgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_runtime_upgrade){target=\_blank} function executes when the FRAME Executive pallet detects a runtime upgrade. Important considerations when using this function include: -### Weights and Database Read/Write Operations +- It runs before any pallet's `on_initialize` hooks. +- Critical storage items (like [`block_number`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.block_number){target=\_blank}) may not be set. +- Execution is mandatory and must be completed. +- Careful weight calculation is required to prevent bricking the chain. -To make weight annotations independent of the deployed database backend, they are defined as a constant and then used in the annotations when expressing database accesses performed by the dispatchable: +When implementing the migration logic, your code must handle several vital responsibilities. A migration implementation must do the following to operate correctly: -```rust -#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] -fn my_dispatchable() { - // ... -} -``` +- Read existing storage values in their original format. +- Transform data to match the new format. +- Write updated values back to storage. +- Calculate and return consumed weight. + +### Migration Testing Hooks -This dispatchable allows one database to read and two to write, in addition to other things that add the additional 20,000. Database access is generally every time a value declared inside the [`#[pallet::storage]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} block is accessed. However, unique accesses are counted because after a value is accessed, it is cached, and reaccessing it does not result in a database operation. That is: +The `OnRuntimeUpgrade` trait provides some functions designed specifically for testing migrations. These functions never execute on-chain but are essential for validating migration behavior in test environments. The migration test hooks are as follows: -- Multiple reads of the exact value count as one read. -- Multiple writes of the exact value count as one write. -- Multiple reads of the same value, followed by a write to that value, count as one read and one write. -- A write followed by a read-only counts as one write. +- **[`try_on_runtime_upgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.OnRuntimeUpgrade.html#method.try_on_runtime_upgrade){target=\_blank}**: This function serves as the primary orchestrator for testing the complete migration process. It coordinates the execution flow from `pre-upgrade` checks through the actual migration to `post-upgrade` verification. Handling the entire migration sequence ensures that storage modifications occur correctly and in the proper order. Preserving this sequence is particularly valuable when testing multiple dependent migrations, where the execution order matters. -### Dispatch Classes +- **[`pre_upgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.pre_upgrade){target=\_blank}**: Before a runtime upgrade begins, the `pre_upgrade` function performs preliminary checks and captures the current state. It returns encoded state data that can be used for `post-upgrade` verification. This function must never modify storage: it should only read and verify the existing state. The data it returns includes critical state values that should remain consistent or transform predictably during migration. -Dispatches are broken into three classes: +- **[`post_upgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.post_upgrade){target=\_blank}**: After the migration completes, `post_upgrade` validates its success. It receives the state data captured by `pre_upgrade` to verify that the migration was executed correctly. This function checks for storage consistency and ensures all data transformations are completed as expected. Like `pre_upgrade`, it operates exclusively in testing environments and should not modify storage. -- Normal -- Operational -- Mandatory +### Migration Structure -If a dispatch is not defined as `Operational` or `Mandatory` in the weight annotation, the dispatch is identified as `Normal` by default. You can specify that the dispatchable uses another class like this: +There are two approaches to implementing storage migrations. The first method involves directly implementing `OnRuntimeUpgrade` on structs. This approach requires manually checking the on-chain storage version against the new [`StorageVersion`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/struct.StorageVersion.html){target=\_blank} and executing the transformation logic only when the check passes. This version verification prevents multiple executions of the migration during subsequent runtime upgrades. -```rust -#[pallet::dispatch((DispatchClass::Operational))] -fn my_dispatchable() { - // ... -} -``` +The recommended approach is to implement [`UncheckedOnRuntimeUpgrade`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.UncheckedOnRuntimeUpgrade.html){target=\_blank} and wrap it with [`VersionedMigration`](https://paritytech.github.io/polkadot-sdk/master/frame_support/migrations/struct.VersionedMigration.html){target=\_blank}. `VersionedMigration` implements `OnRuntimeUpgrade` and handles storage version management automatically, following best practices and reducing potential errors. -This tuple notation also allows you to specify a final argument determining whether the user is charged based on the annotated weight. If you don't specify otherwise, `Pays::Yes` is assumed: +`VersionedMigration` requires five type parameters: -```rust -#[pallet::dispatch(DispatchClass::Normal, Pays::No)] -fn my_dispatchable() { - // ... -} -``` +- **`From`**: The source version for the upgrade. +- **`To`**: The target version for the upgrade. +- **`Inner`**: The `UncheckedOnRuntimeUpgrade` implementation. +- **`Pallet`**: The pallet being upgraded. +- **`Weight`**: The runtime's [`RuntimeDbWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/struct.RuntimeDbWeight.html){target=\_blank} implementation. + +Examine the following migration example that transforms a simple `StorageValue` storing a `u32` into a more complex structure that tracks both current and previous values using the `CurrentAndPreviousValue` struct: -#### Normal Dispatches +- Old `StorageValue` format: -Dispatches in this class represent normal user-triggered transactions. These types of dispatches only consume a portion of a block's total weight limit. For information about the maximum portion of a block that can be consumed for normal dispatches, see [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Normal dispatches are sent to the transaction pool. + ```rust + #[pallet::storage] + pub type Value = StorageValue<_, u32>; + ``` -#### Operational Dispatches +- New `StorageValue` format: -Unlike normal dispatches, which represent the usage of network capabilities, operational dispatches are those that provide network capabilities. Operational dispatches can consume the entire weight limit of a block. They are not bound by the [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Dispatches in this class are given maximum priority and are exempt from paying the [`length_fee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/){target=\_blank}. + ```rust + /// Example struct holding the most recently set [`u32`] and the + /// second most recently set [`u32`] (if one existed). + #[docify::export] + #[derive( + Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen, + )] + pub struct CurrentAndPreviousValue { + /// The most recently set value. + pub current: u32, + /// The previous value, if one existed. + pub previous: Option, + } + #[pallet::storage] + pub type Value = StorageValue<_, CurrentAndPreviousValue>; + ``` -#### Mandatory Dispatches +- Migration: -Mandatory dispatches are included in a block even if they cause the block to surpass its weight limit. You can only use the mandatory dispatch class for inherent transactions that the block author submits. This dispatch class is intended to represent functions in the block validation process. Because these dispatches are always included in a block regardless of the function weight, the validation process must prevent malicious nodes from abusing the function to craft valid but impossibly heavy blocks. You can typically accomplish this by ensuring that: + ```rust + use frame_support::{ + storage_alias, + traits::{Get, UncheckedOnRuntimeUpgrade}, + }; -- The operation performed is always light. -- The operation can only be included in a block once. + #[cfg(feature = "try-runtime")] + use alloc::vec::Vec; -To make it more difficult for malicious nodes to abuse mandatory dispatches, they cannot be included in blocks that return errors. This dispatch class serves the assumption that it is better to allow an overweight block to be created than not to allow any block to be created at all. + /// Collection of storage item formats from the previous storage version. + /// + /// Required so we can read values in the v0 storage format during the migration. + mod v0 { + use super::*; -### Dynamic Weights + /// V0 type for [`crate::Value`]. + #[storage_alias] + pub type Value = StorageValue, u32>; + } -In addition to purely fixed weights and constants, the weight calculation can consider the input arguments of a dispatchable. The weight should be trivially computable from the input arguments with some basic arithmetic: + /// Implements [`UncheckedOnRuntimeUpgrade`], migrating the state of this pallet from V0 to V1. + /// + /// In V0 of the template [`crate::Value`] is just a `u32`. In V1, it has been upgraded to + /// contain the struct [`crate::CurrentAndPreviousValue`]. + /// + /// In this migration, update the on-chain storage for the pallet to reflect the new storage + /// layout. + pub struct InnerMigrateV0ToV1(core::marker::PhantomData); -```rust -use frame_support:: { - dispatch:: { - DispatchClass::Normal, - Pays::Yes, - }, - weights::Weight, -}; + impl UncheckedOnRuntimeUpgrade for InnerMigrateV0ToV1 { + /// Return the existing [`crate::Value`] so we can check that it was correctly set in + /// `InnerMigrateV0ToV1::post_upgrade`. + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + use codec::Encode; -#[pallet::weight(FunctionOf( - |args: (&Vec,)| args.0.len().saturating_mul(10_000), - ) -] -fn handle_users(origin, calls: Vec) { - // Do something per user -} -``` + // Access the old value using the `storage_alias` type + let old_value = v0::Value::::get(); + // Return it as an encoded `Vec` + Ok(old_value.encode()) + } -## Post Dispatch Weight Correction + /// Migrate the storage from V0 to V1. + /// + /// - If the value doesn't exist, there is nothing to do. + /// - If the value exists, it is read and then written back to storage inside a + /// [`crate::CurrentAndPreviousValue`]. + fn on_runtime_upgrade() -> frame_support::weights::Weight { + // Read the old value from storage + if let Some(old_value) = v0::Value::::take() { + // Write the new value to storage + let new = crate::CurrentAndPreviousValue { current: old_value, previous: None }; + crate::Value::::put(new); + // One read + write for taking the old value, and one write for setting the new value + T::DbWeight::get().reads_writes(1, 2) + } else { + // No writes since there was no old value, just one read for checking + T::DbWeight::get().reads(1) + } + } -Depending on the execution logic, a dispatchable function might consume less weight than was prescribed pre-dispatch. To correct weight, the function declares a different return type and returns its actual weight: + /// Verifies the storage was migrated correctly. + /// + /// - If there was no old value, the new value should not be set. + /// - If there was an old value, the new value should be a [`crate::CurrentAndPreviousValue`]. + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), sp_runtime::TryRuntimeError> { + use codec::Decode; + use frame_support::ensure; -```rust -#[pallet::weight(10_000 + 500_000_000)] -fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo { - let was_heavy = do_calculation(input); - - if (was_heavy) { - // None means "no correction" from the weight annotation. - Ok(None.into()) - } else { - // Return the actual weight consumed. - Ok(Some(10_000).into()) - } -} -``` + let maybe_old_value = Option::::decode(&mut &state[..]).map_err(|_| { + sp_runtime::TryRuntimeError::Other("Failed to decode old value from storage") + })?; -## Custom Fees + match maybe_old_value { + Some(old_value) => { + let expected_new_value = + crate::CurrentAndPreviousValue { current: old_value, previous: None }; + let actual_new_value = crate::Value::::get(); -You can also define custom fee systems through custom weight functions or inclusion fee functions. + ensure!(actual_new_value.is_some(), "New value not set"); + ensure!( + actual_new_value == Some(expected_new_value), + "New value not set correctly" + ); + }, + None => { + ensure!(crate::Value::::get().is_none(), "New value unexpectedly set"); + }, + }; + Ok(()) + } + } -### Custom Weights + /// [`UncheckedOnRuntimeUpgrade`] implementation [`InnerMigrateV0ToV1`] wrapped in a + /// [`VersionedMigration`](frame_support::migrations::VersionedMigration), which ensures that: + /// - The migration only runs once when the on-chain storage version is 0 + /// - The on-chain storage version is updated to `1` after the migration executes + /// - Reads/Writes from checking/settings the on-chain storage version are accounted for + pub type MigrateV0ToV1 = frame_support::migrations::VersionedMigration< + 0, // The migration will only execute when the on-chain storage version is 0 + 1, // The on-chain storage version will be set to 1 after the migration is complete + InnerMigrateV0ToV1, + crate::pallet::Pallet, + ::DbWeight, + >; + ``` -Instead of using the default weight annotations, you can create a custom weight calculation type using the weights module. The custom weight calculation type must implement the following traits: +### Migration Organization -- [`WeighData`](https://crates.parity.io/frame_support/weights/trait.WeighData.html){target=\_blank} to determine the weight of the dispatch. -- [`ClassifyDispatch`](https://crates.parity.io/frame_support/weights/trait.ClassifyDispatch.html){target=\_blank} to determine the class of the dispatch. -- [`PaysFee`](https://crates.parity.io/frame_support/weights/trait.PaysFee.html){target=\_blank} to determine whether the sender of the dispatch pays fees. - -The Polkadot SDK then bundles the output information of the three traits into the [`DispatchInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.DispatchInfo.html){target=\_blank} struct and provides it by implementing the [`GetDispatchInfo`](https://docs.rs/frame-support/latest/frame_support/dispatch/trait.GetDispatchInfo.html){target=\_blank} for all `Call` variants and opaque extrinsic types. This is used internally by the System and Executive modules. +Best practices recommend organizing migrations in a separate module within your pallet. Here's the recommended file structure: -`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over T, which gets resolved into the tuple of all dispatch arguments except for the origin. The following example illustrates a struct that calculates the weight as `m * len(args)`, where `m` is a given multiplier and args is the concatenated tuple of all dispatch arguments. In this example, the dispatch class is `Operational` if the transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length exceeds 10 bytes. +```plain +my-pallet/ +├── src/ +│ ├── lib.rs # Main pallet implementation +│ └── migrations/ # All migration-related code +│ ├── mod.rs # Migrations module definition +│ ├── v1.rs # V0 -> V1 migration +│ └── v2.rs # V1 -> V2 migration +└── Cargo.toml +``` -```rust -struct LenWeight(u32); -impl WeighData for LenWeight { - fn weigh_data(&self, target: T) -> Weight { - let multiplier = self.0; - let encoded_len = target.encode().len() as u32; - multiplier * encoded_len - } -} +This structure provides several benefits: -impl ClassifyDispatch for LenWeight { - fn classify_dispatch(&self, target: T) -> DispatchClass { - let encoded_len = target.encode().len() as u32; - if encoded_len > 100 { - DispatchClass::Operational - } else { - DispatchClass::Normal - } - } -} +- Separates migration logic from core pallet functionality. +- Makes migrations easier to test and maintain. +- Provides explicit versioning of storage changes. +- Simplifies the addition of future migrations. -impl PaysFee { - fn pays_fee(&self, target: T) -> Pays { - let encoded_len = target.encode().len() as u32; - if encoded_len > 10 { - Pays::Yes - } else { - Pays::No - } - } -} -``` +### Scheduling Migrations -A weight calculator function can also be coerced to the final type of the argument instead of defining it as a vague type that can be encoded. The code would roughly look like this: +To execute migrations during a runtime upgrade, you must configure them in your runtime's Executive pallet. Add your migrations in `runtime/src/lib.rs`: ```rust -struct CustomWeight; -impl WeighData<(&u32, &u64)> for CustomWeight { - fn weigh_data(&self, target: (&u32, &u64)) -> Weight { - ... - } -} +/// Tuple of migrations (structs that implement `OnRuntimeUpgrade`) +type Migrations = ( + pallet_my_pallet::migrations::v1::Migration, + // More migrations can be added here +); +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, + Migrations, // Include migrations here +>; -// given a dispatch: -#[pallet::call] -impl, I: 'static> Pallet { - #[pallet::weight(CustomWeight)] - fn foo(a: u32, b: u64) { ... } -} ``` -In this example, the `CustomWeight` can only be used in conjunction with a dispatch with a particular signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because there aren't any assumptions about ``. +## Single-Block Migrations -#### Custom Inclusion Fee +Single-block migrations execute their logic within one block immediately following a runtime upgrade. They run as part of the runtime upgrade process through the `OnRuntimeUpgrade` trait implementation and must be completed before any other runtime logic executes. -The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. +While single-block migrations are straightforward to implement and provide immediate data transformation, they carry significant risks. The most critical consideration is that they must complete within one block's weight limits. This is especially crucial for parachains, where exceeding block weight limits will brick the chain. -```rust -// Assume this is the balance type -type Balance = u64; - -// Assume we want all the weights to have a `100 + 2 * w` conversion to fees -struct CustomWeightToFee; -impl WeightToFee for CustomWeightToFee { - fn convert(w: Weight) -> Balance { - let a = Balance::from(100); - let b = Balance::from(2); - let w = Balance::from(w); - a + b * w - } -} +Use single-block migrations only when you can guarantee: -parameter_types! { - pub const ExtrinsicBaseWeight: Weight = 10_000_000; -} +- The migration has a bounded execution time. +- Weight calculations are thoroughly tested. +- Total weight will never exceed block limits. -impl frame_system::Config for Runtime { - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; -} +For a complete implementation example of a single-block migration, refer to the [single-block migration example]( https://paritytech.github.io/polkadot-sdk/master/pallet_example_single_block_migrations/index.html){target=\_blank} in the Polkadot SDK documentation. -parameter_types! { - pub const TransactionByteFee: Balance = 10; -} +## Multi Block Migrations -impl transaction_payment::Config { - type TransactionByteFee = TransactionByteFee; - type WeightToFee = CustomWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} +Multi-block migrations distribute the migration workload across multiple blocks, providing a safer approach for production environments. The migration state is tracked in storage, allowing the process to pause and resume across blocks. -struct TargetedFeeAdjustment(sp_std::marker::PhantomData); -impl> WeightToFee for TargetedFeeAdjustment { - fn convert(multiplier: Fixed128) -> Fixed128 { - // Don't change anything. Put any fee update info here. - multiplier - } -} -``` +This approach is essential for production networks and parachains as the risk of exceeding block weight limits is eliminated. Multi-block migrations can safely handle large storage collections, unbounded data structures, and complex nested data types where weight consumption might be unpredictable. -## Additional Resources +Multi-block migrations are ideal when dealing with: + +- Large-scale storage migrations. +- Unbounded storage items or collections. +- Complex data structures with uncertain weight costs. -You now know the weight system, how it affects transaction fee computation, and how to specify weights for your dispatchable calls. The next step is determining the correct weight for your dispatchable operations. You can use Substrate benchmarking functions and frame-benchmarking calls to test your functions with different parameters and empirically determine the proper weight in their worst-case scenarios. +The primary trade-off is increased implementation complexity, as you must manage the migration state and handle partial completion scenarios. However, multi-block migrations' significant safety benefits and operational reliability are typically worth the increased complexity. -- [Benchmark](/parachains/customize-runtime/pallet-development/benchmark-pallet/) -- [`SignedExtension`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} -- [Custom weights for the Example pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/examples/basic/src/weights.rs){target=\_blank} -- [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} +For a complete implementation example of multi-block migrations, refer to the [official example](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/examples/multi-block-migrations){target=\_blank} in the Polkadot SDK. --- -Page Title: Unit Test Pallets +Page Title: Transactions and Fees on Asset Hub -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md -- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/ -- Summary: Learn how to efficiently test pallets in the Polkadot SDK, ensuring the reliability and security of your pallets operations. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-blocks-transactions-fees.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/blocks-transactions-fees/ +- Summary: Explore how Asset Hub smart contracts handle blocks, transactions, and fees with EVM compatibility, supporting various Ethereum transaction types. -# Unit Test Pallets +# Blocks, Transactions, and Fees +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries. +Asset Hub smart contracts operate within the Polkadot ecosystem using the [`pallet_revive`](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/){target=\_blank} implementation, which provides EVM compatibility. While many aspects of blocks and transactions are inherited from the underlying parachain architecture, there are specific considerations and mechanisms unique to smart contract operations on Asset Hub. -To begin unit testing, you must first set up a mock runtime that simulates blockchain behavior, incorporating the necessary pallets. For a deeper understanding, consult the [Mock Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/){target=\_blank} guide. +## Smart Contract Blocks -## Writing Unit Tests +Smart contract blocks in Asset Hub follow the same fundamental structure as parachain blocks, inheriting all standard parachain block components. The `pallet_revive` implementation maintains this consistency while adding necessary [EVM-specific features](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm){target=\_blank}. For detailed implementation specifics, the [`Block`](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.Block.html){target=\_blank} struct in `pallet_revive` demonstrates how parachain and smart contract block implementations align. -Once the mock runtime is in place, the next step is to write unit tests that evaluate the functionality of your pallet. Unit tests allow you to test specific pallet features in isolation, ensuring that each function behaves correctly under various conditions. These tests typically reside in your pallet module's `test.rs` file. +## Smart Contract Transactions -Unit tests in the Polkadot SDK use the Rust testing framework, and the mock runtime you've defined earlier will serve as the test environment. Below are the typical steps involved in writing unit tests for a pallet. +Asset Hub implements a sophisticated transaction system that supports various transaction types and formats, encompassing both traditional parachain operations and EVM-specific interactions. -The tests confirm that: +### EVM Transaction Types -- **Pallets initialize correctly**: At the start of each test, the system should initialize with block number 0, and the pallets should be in their default states. -- **Pallets modify each other's state**: The second test shows how one pallet can trigger changes in another pallet's internal state, confirming proper cross-pallet interactions. -- **State transitions between blocks are seamless**: By simulating block transitions, the tests validate that the runtime responds correctly to changes in the block number. +The system provides a fundamental [`eth_transact`](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/pallet/dispatchables/fn.eth_transact.html){target=\_blank} interface for processing raw EVM transactions dispatched through [Ethereum JSON-RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank}. This interface acts as a wrapper for Ethereum transactions, requiring an encoded signed transaction payload, though it cannot be dispatched directly. Building upon this foundation, the system supports multiple transaction formats to accommodate different use cases and optimization needs: -Testing pallet interactions within the runtime is critical for ensuring the blockchain behaves as expected under real-world conditions. Writing integration tests allows validation of how pallets function together, preventing issues that might arise when the system is fully assembled. +- **[Legacy transactions](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.TransactionLegacyUnsigned.html){target=\_blank}**: The original Ethereum transaction format, providing basic transfer and contract interaction capabilities. These transactions use a simple pricing mechanism and are supported for backward compatibility. -This approach provides a comprehensive view of the runtime's functionality, ensuring the blockchain is stable and reliable. +- **[EIP-1559 transactions](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.Transaction1559Unsigned.html){target=\_blank}**: An improved transaction format that introduces a more predictable fee mechanism with base fee and priority fee components. This format helps optimize gas fee estimation and network congestion management. -### Test Initialization +- **[EIP-2930 transactions](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.Transaction2930Unsigned.html){target=\_blank}**: Introduces access lists to optimize gas costs for contract interactions by pre-declaring accessed addresses and storage slots. -Each test starts by initializing the runtime environment, typically using the `new_test_ext()` function, which sets up the mock storage and environment. +- **[EIP-4844 transactions](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/evm/struct.Transaction4844Unsigned.html){target=\_blank}**: Implements blob-carrying transactions, designed to optimize Layer 2 scaling solutions by providing dedicated space for roll-up data. -```rust -#[test] -fn test_pallet_functionality() { - new_test_ext().execute_with(|| { - // Test logic goes here - }); -} -``` +Each transaction type can exist in both signed and unsigned states, with appropriate validation and processing mechanisms for each. -### Function Call Testing +## Fees and Gas -Call the pallet's extrinsics or functions to simulate user interaction or internal logic. Use the `assert_ok!` macro to check for successful execution and `assert_err!` to verify that errors are correctly handled. +Asset Hub implements a sophisticated resource management system that combines parachain transaction fees with EVM gas mechanics, providing both Ethereum compatibility and enhanced features. -```rust -#[test] -fn it_works_for_valid_input() { - new_test_ext().execute_with(|| { - // Call an extrinsic or function - assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param)); - }); -} +### Gas Model Overview -#[test] -fn it_fails_for_invalid_input() { - new_test_ext().execute_with(|| { - // Call an extrinsic with invalid input and expect an error - assert_err!( - TemplateModule::some_function(Origin::signed(1), invalid_param), - Error::::InvalidInput - ); - }); -} -``` +Gas serves as the fundamental unit for measuring computational costs, with each network operation consuming a specified amount. This implementation maintains compatibility with Ethereum's approach while adding parachain-specific optimizations. -### Storage Testing +- **Dynamic gas scaling**: Asset Hub implements a dynamic pricing mechanism that reflects actual execution performance. This results in: -After calling a function or extrinsic in your pallet, it's essential to verify that the state changes in the pallet's storage match the expected behavior to ensure data is updated correctly based on the actions taken. + - More efficient pricing for computational instructions relative to I/O operations. + - Better correlation between gas costs and actual resource consumption. + - Need for developers to implement flexible gas calculation rather than hardcoding values. -The following example shows how to test the storage behavior before and after the function call: +- **Multi-dimensional resource metering**: Asset Hub extends beyond the traditional single-metric gas model to track three distinct resources. -```rust -#[test] -fn test_storage_update_on_extrinsic_call() { - new_test_ext().execute_with(|| { - // Check the initial storage state (before the call) - assert_eq!(Something::::get(), None); + - `ref_time` (computation time): - // Dispatch a signed extrinsic, which modifies storage - assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42)); + - Functions as traditional gas equivalent. + - Measures actual computational resource usage. + - Primary metric for basic operation costs. - // Validate that the storage has been updated as expected (after the call) - assert_eq!(Something::::get(), Some(42)); - }); -} -``` + - `proof_size` (verification overhead): -### Event Testing + - Tracks state proof size required for validator verification. + - Helps manage consensus-related resource consumption. + - Important for cross-chain operations. -It's also crucial to test the events that your pallet emits during execution. By default, events generated in a pallet using the [`#generate_deposit`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.generate_deposit.html){target=\_blank} macro are stored under the system's event storage key (system/events) as [`EventRecord`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.EventRecord.html){target=\_blank} entries. These can be accessed using [`System::events()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.events){target=\_blank} or verified with specific helper methods provided by the system pallet, such as [`assert_has_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_has_event){target=\_blank} and [`assert_last_event`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.assert_last_event){target=\_blank}. -Here's an example of testing events in a mock runtime: + - `storage_deposit` (state management): -```rust -#[test] -fn it_emits_events_on_success() { - new_test_ext().execute_with(|| { - // Call an extrinsic or function - assert_ok!(TemplateModule::some_function(Origin::signed(1), valid_param)); + - Manages blockchain state growth. + - Implements a deposit-based system for long-term storage. + - Refundable when storage is freed. - // Verify that the expected event was emitted - assert!(System::events().iter().any(|record| { - record.event == Event::TemplateModule(TemplateEvent::SomeEvent) - })); - }); -} -``` +These resources can be limited at both transaction and contract levels, similar to Ethereum's gas limits. For more information, check the [Gas Model](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm#gas-model){target=\_blank} section in the [EVM vs PolkaVM](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/){target=\_blank} article. -Some key considerations are: +### Fee Components -- **Block number**: Events are not emitted on the genesis block, so you need to set the block number using [`System::set_block_number()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.set_block_number){target=\_blank} to ensure events are triggered. -- **Converting events**: Use `.into()` when instantiating your pallet's event to convert it into a generic event type, as required by the system's event storage. +- Base fees: -## Where to Go Next + - Storage deposit for contract deployment. + - Minimum transaction fee for network access. + - Network maintenance costs. -- Dive into the full implementation of the [`mock.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/mock.rs){target=\_blank} and [`test.rs`](https://github.com/paritytech/polkadot-sdk/blob/master/templates/solochain/pallets/template/src/tests.rs){target=\_blank} files in the [Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=_blank}. +- Execution fees: -
    + - Computed based on gas consumption. + - Converted to native currency using network-defined rates. + - Reflects actual computational resource usage. -- Guide __Benchmarking__ +- Storage fees: - --- + - Deposit for long-term storage usage. + - Refundable when storage is freed. + - Helps prevent state bloat. - Explore methods to measure the performance and execution cost of your pallet. +### Gas Calculation and Conversion - [:octicons-arrow-right-24: Reference](/develop/parachains/testing/benchmarking) +The system maintains precise conversion mechanisms between: -
    +- Substrate weights and EVM gas units. +- Native currency and gas costs. +- Different resource metrics within the multi-dimensional model. + +This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. --- @@ -12761,91 +9097,3 @@ Here's how to submit this XCM using Astar (Parachain 2006) as an example: After submitting the transaction, wait for it to be finalized and then verify that your parachain has been successfully unlocked by following the steps described in the [Check if the Parachain is Locked](#check-if-the-parachain-is-locked) section. If the parachain shows as unlocked, your operation has been successful. If it still appears locked, verify that your XCM transaction was processed correctly and consider troubleshooting the XCM built. ![](/images/parachains/runtime-maintenance/unlock-parachains/unlock-parachain-6.webp) - - ---- - -Page Title: XCM Tools - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/xcm-tools/ -- Summary: Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. - -# XCM Tools - -## Introduction - -As described in the [Interoperability](/develop/interoperability){target=\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem. - -As XCM is central to enabling communication between blockchains, developers need robust tools to help interact with, build, and test XCM messages. Several XCM tools simplify working with the protocol by providing libraries, frameworks, and utilities that enhance the development process, ensuring that applications built within the Polkadot ecosystem can efficiently use cross-chain functionalities. - -## Popular XCM Tools - -### Moonsong Labs XCM Tools - -[Moonsong Labs XCM Tools](https://github.com/Moonsong-Labs/xcm-tools){target=\_blank} provides a collection of scripts for managing and testing XCM operations between Polkadot SDK-based runtimes. These tools allow performing tasks like asset registration, channel setup, and XCM initialization. Key features include: - -- **Asset registration**: Registers assets, setting units per second (up-front fees), and configuring error (revert) codes. -- **XCM initializer**: Initializes XCM, sets default XCM versions, and configures revert codes for XCM-related precompiles. -- **HRMP manipulator**: Manages HRMP channel actions, including opening, accepting, or closing channels. -- **XCM-Transactor-Info-Setter**: Configures transactor information, including extra weight and fee settings. -- **Decode XCM**: Decodes XCM messages on the relay chain or parachains to help interpret cross-chain communication. - -To get started, clone the repository and install the required dependencies: - -```bash -git clone https://github.com/Moonsong-Labs/xcm-tools && -cd xcm-tools && -yarn install -``` - -For a full overview of each script, visit the [scripts](https://github.com/Moonsong-Labs/xcm-tools/tree/main/scripts){target=\_blank} directory or refer to the [official documentation](https://github.com/Moonsong-Labs/xcm-tools/blob/main/README.md){target=\_blank} on GitHub. - -### ParaSpell - -[ParaSpell](/reference/tools/paraspell/){target=\_blank} is a collection of open-source XCM tools that streamline cross-chain asset transfers and interactions across the Polkadot and Kusama ecosystems. It provides developers with an intuitive interface to build, test, and deploy interoperable dApps, featuring message composition, decoding, and practical utilities for parachain interactions that simplify debugging and cross-chain communication optimization. - -### Astar XCM Tools - -The [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks: - -- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command. -- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments. -- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs. - -To start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\_blank} and compile the xcm-tools package: - -```bash -git clone https://github.com/AstarNetwork/Astar && -cd Astar && -cargo build --release -p xcm-tools -``` - -After compiling, verify the setup with the following command: - -```bash -./target/release/xcm-tools --help -``` -For more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\_blank}. - -### Chopsticks - -The Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\_blank} about XCM. - -### Moonbeam XCM SDK - -The [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank} of the origin or destination assets or which extrinsics are used on which networks. - -The SDK consists of two main packages: - -- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem. -- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum. - -Key features include: - -- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection. -- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems. -- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality. -- **Comprehensive documentation**: Includes usage guides and API references for both packages. - -For detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\_blank}. diff --git a/.ai/categories/polkadot-protocol.md b/.ai/categories/polkadot-protocol.md index a118a0ac9..77b27d7a5 100644 --- a/.ai/categories/polkadot-protocol.md +++ b/.ai/categories/polkadot-protocol.md @@ -476,5883 +476,2748 @@ Launch your parachain locally and start producing blocks: --- -Page Title: Agile Coretime +Page Title: Contract Deployment -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/agile-coretime/ -- Summary: Explore the efficient scheduling mechanisms to access Polkadot cores to produce blockspace continuously or on-demand. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-contract-deployment.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/contract-deployment/ +- Summary: Compare deployment flows for REVM and PVM-based smart contracts on the Polkadot Hub. Includes single-step REVM flows and PVM’s two-step deployment model. -# Agile Coretime +# Contract Deployment ## Introduction -Agile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains. - -``` mermaid -graph TB - A[Cores Designation] - B[Bulk Coretime] - C[On-Demand Coretime] - A --continuous--> B - A --flexible--> C -``` - -Cores can be designated to a parachain either continuously through [bulk coretime](#bulk-coretime) or dynamically via [on-demand coretime](#on-demand-coretime). Additionally, Polkadot supports scheduling multiple cores in parallel through [elastic scaling](https://wiki.polkadot.com/learn/learn-elastic-scaling/){target=\_blank}, which is a feature under active development on Polkadot. This flexibility empowers parachains to optimize their resource usage and block production according to their unique needs. - -In this guide, you'll learn how bulk coretime enables continuous core access with features like interlacing and splitting, and how on-demand coretime provides flexible, pay-per-use scheduling for parachains. For a deep dive on Agile Coretime and its terminology, refer to the [Wiki doc](https://wiki.polkadot.com/learn/learn-agile-coretime/#introduction-to-agile-coretime){target=\_blank}. - -## Bulk Coretime - -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be purchased through [coretime sales](#coretime-sales) in DOT and can be split, shared, or resold. Currently, the duration of bulk coretime is set to 28 days. Coretime purchased in bulk and assigned to a single parachain is eligible for a price-capped renewal, providing a form of rent-controlled access, which is important for predicting the running costs in the near future. Suppose the bulk coretime is [interlaced](#coretime-interlacing) or [split](#coretime-splitting) or is kept idle without assigning it to a parachain. In that case, it will be ineligible for the price-capped renewal. - -### Coretime Interlacing - -It is the action of dividing bulk coretime across multiple parachains that produce blocks spaced uniformly in time. For example, think of multiple parachains taking turns producing blocks, demonstrating a simple form of interlacing. This feature can be used by parachains with a low transaction volume and need not continuously produce blocks. - -### Coretime Splitting - -It is the action of dividing bulk coretime into multiple contiguous regions. This feature can be used by parachains that need to produce blocks continuously but do not require the whole 28 days of bulk coretime and require only part of it. - -## On-Demand Coretime - -Polkadot has dedicated cores assigned to provide core time on demand. These cores are excluded from the coretime sales and are reserved for on-demand parachains, which pay in DOT per block. - +Polkadot's smart contract platform supports two distinct virtual machine backends: Rust Ethereum Virtual Machine (REVM) and PolkaVM. Each backend has its own deployment characteristics and optimization strategies. REVM provides full Ethereum compatibility with familiar single-step deployment, while the RISC-V-based PolkaVM uses a more structured two-step approach optimized for its architecture. Understanding these differences ensures smooth deployment regardless of which backend you choose for your smart contracts. ---- +## REVM Deployment -Page Title: Asset Hub +The REVM backend enables seamless deployment of Ethereum contracts without modification. Contracts deploy exactly as they would on Ethereum, using familiar tools and workflows. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/assets-and-smart-contracts/ -- Summary: Learn about Asset Hub in Polkadot, managing on-chain assets, foreign asset integration, and using XCM for cross-chain asset transfers. +With REVM, deployment mirrors the Ethereum flow exactly including: -# Asset Hub +- Contracts are bundled and deployed in a single transaction. +- Factory contracts can create new contracts at runtime. +- Runtime code generation, including inline assembly, is supported. +- Existing familiar tools like Hardhat, Foundry, and Remix work out of the box. -## Introduction +## PolkaVM Deployment -The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integration using XCM, as well as essential tools like [API Sidecar](#api-sidecar) and [`TxWrapper`](#txwrapper) for developers working with on-chain assets. +PolkaVM implements a fundamentally different deployment model optimized for its RISC-V architecture. While simple contract deployments work seamlessly, advanced patterns like factory contracts require understanding the two-step deployment process. -## Assets Basics +### Standard Contract Deployment -In the Polkadot ecosystem, the relay chain does not natively support additional assets beyond its native token (DOT for Polkadot, KSM for Kusama). The Asset Hub parachain on Polkadot and Kusama provides a fungible and non-fungible assets framework. Asset Hub allows developers and users to create, manage, and use assets across the ecosystem. +For most use cases, such as deploying ERC-20 tokens, NFT collections, or standalone contracts, deployment is transparent and requires no special steps. The [Revive compiler](https://github.com/paritytech/revive){target=\_blank} handles the deployment process automatically when using standard Solidity patterns. -Asset creators can use Asset Hub to track their asset issuance across multiple parachains and manage assets through operations such as minting, burning, and transferring. Projects that need a standardized method of handling on-chain assets will find this particularly useful. The fungible asset interface provided by Asset Hub closely resembles Ethereum's ERC-20 standard but is directly integrated into Polkadot's runtime, making it more efficient in terms of speed and transaction fees. +### Two-Step Deployment Model -Integrating with Asset Hub offers several key benefits, particularly for infrastructure providers and users: +PolkaVM separates contract deployment into distinct phases: -- **Support for non-native on-chain assets**: Asset Hub enables seamless asset creation and management, allowing projects to develop tokens or assets that can interact with the broader ecosystem. -- **Lower transaction fees**: Asset Hub offers significantly lower transaction costs—approximately one-tenth of the fees on the relay chain, providing cost-efficiency for regular operations. -- **Reduced deposit requirements**: Depositing assets in Asset Hub is more accessible, with deposit requirements that are around one one-hundredth of those on the relay chain. -- **Payment of transaction fees with non-native assets**: Users can pay transaction fees in assets other than the native token (DOT or KSM), offering more flexibility for developers and users. +1. **Code upload**: Contract bytecode must be uploaded to the chain before instantiation. +2. **Contract instantiation**: Contracts are created by referencing previously uploaded code via its hash. -Assets created on the Asset Hub are stored as part of a map, where each asset has a unique ID that links to information about the asset, including details like: +This architecture differs from the EVM's bundled approach and has important implications for specific deployment patterns. -- The management team. -- The total supply. -- The number of accounts holding the asset. -- **Sufficiency for account existence**: Whether the asset alone is enough to maintain an account without a native token balance. -- The metadata of the asset, including its name, symbol, and the number of decimals for representation. +### Factory Pattern Considerations -Some assets can be regarded as sufficient to maintain an account's existence, meaning that users can create accounts on the network without needing a native token balance (i.e., no existential deposit required). Developers can also set minimum balances for their assets. If an account's balance drops below the minimum, the balance is considered dust and may be cleared. +The common EVM pattern, where contracts dynamically create other contracts, requires adaptation for PolkaVM as follows: -## Assets Pallet +**EVM Factory Pattern:** +```solidity +// This works on REVM but requires modification for PolkaVM +contract Factory { + function createToken() public returns (address) { + // EVM bundles bytecode in the factory + return address(new Token()); + } +} +``` -The Polkadot SDK's Assets pallet is a powerful module designated for creating and managing fungible asset classes with a fixed supply. It offers a secure and flexible way to issue, transfer, freeze, and destroy assets. The pallet supports various operations and includes permissioned and non-permissioned functions to cater to simple and advanced use cases. +**PolkaVM Requirements:** -Visit the [Assets Pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank} for more in-depth information. +- **Pre-upload dependent contracts**: All contracts that will be instantiated at runtime must be uploaded to the chain before the factory attempts to create them. +- **Code hash references**: Factory contracts work with pre-uploaded code hashes rather than embedding bytecode. +- **No runtime code generation**: Dynamic bytecode generation is not supported due to PolkaVM's RISC-V format. -### Key Features +### Migration Strategy for Factory Contracts -Key features of the Assets pallet include: +When migrating factory contracts from Ethereum to PolkaVM: -- **Asset issuance**: Allows the creation of a new asset, where the total supply is assigned to the creator's account. -- **Asset transfer**: Enables transferring assets between accounts while maintaining a balance in both accounts. -- **Asset freezing**: Prevents transfers of a specific asset from one account, locking it from further transactions. -- **Asset destruction**: Allows accounts to burn or destroy their holdings, removing those assets from circulation. -- **Non-custodial transfers**: A non-custodial mechanism to enable one account to approve a transfer of assets on behalf of another. +1. **Identify all contracts**: Determine which contracts will be instantiated at runtime. +2. **Upload dependencies first**: Deploy all dependent contracts to the chain before deploying the factory. +3. **Use on-chain constructors**: Leverage PolkaVM's on-chain constructor feature for flexible instantiation. +4. **Avoid assembly creation**: Don't use `create` or `create2` opcodes in assembly blocks for manual deployment. -### Main Functions +### Architecture-Specific Limitations -The Assets pallet provides a broad interface for managing fungible assets. Some of the main dispatchable functions include: +PolkaVM's deployment model creates several specific constraints: -- **`create()`**: Create a new asset class by placing a deposit, applicable when asset creation is permissionless. -- **`issue()`**: Mint a fixed supply of a new asset and assign it to the creator's account. -- **`transfer()`**: Transfer a specified amount of an asset between two accounts. -- **`approve_transfer()`**: Approve a non-custodial transfer, allowing a third party to move assets between accounts. -- **`destroy()`**: Destroy an entire asset class, removing it permanently from the chain. -- **`freeze()` and `thaw()`**: Administrators or privileged users can lock or unlock assets from being transferred. +- **`EXTCODECOPY` limitations**: Contracts using `EXTCODECOPY` to manipulate code at runtime will encounter issues. +- **Runtime code modification**: Patterns that construct and mutate contract code on-the-fly are not supported. +- **Assembly-based factories**: Factory contracts written in YUL assembly that generate code at runtime will fail with `CodeNotFound` errors. -For a full list of dispatchable and privileged functions, see the [dispatchables Rust docs](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/enum.Call.html){target=\_blank}. +These patterns are rare in practice and typically require dropping down to assembly, making them non-issues for standard Solidity development. -### Querying Functions +### On-Chain Constructors -The Assets pallet exposes several key querying functions that developers can interact with programmatically. These functions allow you to query asset information and perform operations essential for managing assets across accounts. The two main querying functions are: +PolkaVM provides on-chain constructors as an elegant alternative to runtime code modification: -- **`balance(asset_id, account)`**: Retrieves the balance of a given asset for a specified account. Useful for checking the holdings of an asset class across different accounts. +- Enable contract instantiation without runtime code generation. +- Support flexible initialization patterns. +- Maintain separation between code upload and contract creation. +- Provide predictable deployment costs. -- **`total_supply(asset_id)`**: Returns the total supply of the asset identified by `asset_id`. Allows users to verify how much of the asset exists on-chain. +## Gas Estimation vs Actual Consumption -In addition to these basic functions, other utility functions are available for querying asset metadata and performing asset transfers. You can view the complete list of querying functions in the [Struct Pallet Rust docs](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/struct.Pallet.html){target=\_blank}. +Both REVM and PolkaVM deployments may show significant differences between gas estimation and actual consumption. You might see estimates that are several times higher than the actual gas consumed (often around 30% of the estimate). This is normal behavior because pre-dispatch estimation cannot distinguish between computation weight and storage deposits, leading to conservative overestimation. Contract deployments are particularly affected as they consume significant storage deposits for code storage. -### Permission Models and Roles +## Deployment Comparison -The Assets pallet incorporates a robust permission model, enabling control over who can perform specific operations like minting, transferring, or freezing assets. The key roles within the permission model are: +| Feature | REVM Backend | PolkaVM Backend | +|:-------:|:-------------:|:----------------:| +| **Deployment Model** | Single-step bundled | Two-step upload and instantiate | +| **Factory Patterns** | Direct runtime creation | Requires pre-uploaded code | +| **Code Bundling** | Bytecode in transaction | Code hash references | +| **Runtime Codegen** | Fully supported | Not supported | +| **Simple Contracts** | No modifications needed | No modifications needed | +| **Assembly Creation** | Supported | Discouraged, limited support | -- **Admin**: Can freeze (preventing transfers) and forcibly transfer assets between accounts. Admins also have the power to reduce the balance of an asset class across arbitrary accounts. They manage the more sensitive and administrative aspects of the asset class. -- **Issuer**: Responsible for minting new tokens. When new assets are created, the Issuer is the account that controls their distribution to other accounts. -- **Freezer**: Can lock the transfer of assets from an account, preventing the account holder from moving their balance. This function is useful for freezing accounts involved in disputes or fraud. -- **Owner**: Has overarching control, including destroying an entire asset class. Owners can also set or update the Issuer, Freezer, and Admin roles. +## Conclusion -These permissions provide fine-grained control over assets, enabling developers and asset managers to ensure secure, controlled operations. Each of these roles is crucial for managing asset lifecycles and ensuring that assets are used appropriately across the network. +Both backends support contract deployment effectively, with REVM offering drop-in Ethereum compatibility and PolkaVM providing a more structured two-step approach. For the majority of use cases—deploying standard contracts like tokens or applications—both backends work seamlessly. Advanced patterns like factory contracts may require adjustment for PolkaVM, but these adaptations are straightforward with proper planning. -### Asset Freezing -The Assets pallet allows you to freeze assets. This feature prevents transfers or spending from a specific account, effectively locking the balance of an asset class until it is explicitly unfrozen. Asset freezing is beneficial when assets are restricted due to security concerns or disputes. +--- -Freezing assets is controlled by the Freezer role, as mentioned earlier. Only the account with the Freezer privilege can perform these operations. Here are the key freezing functions: +Page Title: Deploy an ERC-20 to Polkadot Hub -- **`freeze(asset_id, account)`**: Locks the specified asset of the account. While the asset is frozen, no transfers can be made from the frozen account. -- **`thaw(asset_id, account)`**: Corresponding function for unfreezing, allowing the asset to be transferred again. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/ +- Summary: Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Hardhat. -This approach enables secure and flexible asset management, providing administrators the tools to control asset movement in special circumstances. +# Deploy an ERC-20 to Polkadot Hub -### Non-Custodial Transfers (Approval API) +## Introduction -The Assets pallet also supports non-custodial transfers through the Approval API. This feature allows one account to approve another account to transfer a specific amount of its assets to a third-party recipient without granting full control over the account's balance. Non-custodial transfers enable secure transactions where trust is required between multiple parties. +[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. -Here's a brief overview of the key functions for non-custodial asset transfers: +This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Hardhat](https://hardhat.org/){target=\_blank}, an Ethereum development environment. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. -- **`approve_transfer(asset_id, delegate, amount)`**: Approves a delegate to transfer up to a certain amount of the asset on behalf of the original account holder. -- **`cancel_approval(asset_id, delegate)`**: Cancels a previous approval for the delegate. Once canceled, the delegate no longer has permission to transfer the approved amount. -- **`transfer_approved(asset_id, owner, recipient, amount)`**: Executes the approved asset transfer from the owner’s account to the recipient. The delegate account can call this function once approval is granted. +## Prerequisites -These delegated operations make it easier to manage multi-step transactions and dApps that require complex asset flows between participants. +Before starting, make sure you have: -## Foreign Assets +- Basic understanding of Solidity programming and fungible tokens. +- Node.js v22.13.1 or later. +- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -Foreign assets in Asset Hub refer to assets originating from external blockchains or parachains that are registered in the Asset Hub. These assets are typically native tokens from other parachains within the Polkadot ecosystem or bridged tokens from external blockchains such as Ethereum. +## Set Up Your Project -Once a foreign asset is registered in the Asset Hub by its originating blockchain's root origin, users are able to send these tokens to the Asset Hub and interact with them as they would any other asset within the Polkadot ecosystem. +This tutorial uses a [Hardhat ERC-20 template](https://github.com/polkadot-developers/revm-hardhat-examples/tree/master/erc20-hardhat){target=\_blank} that contains all the necessary files. To get started, take the following steps: -### Handling Foreign Assets +1. Clone the GitHub repository locally: -The Foreign Assets pallet, an instance of the Assets pallet, manages these assets. Since foreign assets are integrated into the same interface as native assets, developers can use the same functionalities, such as transferring and querying balances. However, there are important distinctions when dealing with foreign assets. + ```bash + git clone https://github.com/polkadot-developers/revm-hardhat-examples/ + cd revm-hardhat-examples/erc20-hardhat + ``` -- **Asset identifier**: Unlike native assets, foreign assets are identified using an XCM Multilocation rather than a simple numeric `AssetId`. This multilocation identifier represents the cross-chain location of the asset and provides a standardized way to reference it across different parachains and relay chains. +2. Install the dependencies: -- **Transfers**: Once registered in the Asset Hub, foreign assets can be transferred between accounts, just like native assets. Users can also send these assets back to their originating blockchain if supported by the relevant cross-chain messaging mechanisms. + ```bash + npm i + ``` -## Integration +This will fetch all the necessary packages to help you deploy an ERC-20 with Hardhat to Polkadot. -Asset Hub supports a variety of integration tools that make it easy for developers to manage assets and interact with the blockchain in their applications. The tools and libraries provided by Parity Technologies enable streamlined operations, such as querying asset information, building transactions, and monitoring cross-chain asset transfers. +## Configure Hardhat -Developers can integrate Asset Hub into their projects using these core tools: +Once you've [setup your project](#set-up-your-project), you can configure the `hardhat.config.ts` to your needs. This tutorial has the file prepared to deploy to the Polkadot TestNet. -### API Sidecar +To store and use private keys or network URLs, you can use Hardhat's configuration variables. This can be set via tasks in the **vars** scope. For example, to store the private key to deploy to the Polkadot TestNet, run the following command: -[API Sidecar](https://github.com/paritytech/substrate-api-sidecar){target=\_blank} is a RESTful service that can be deployed alongside Polkadot and Kusama nodes. It provides endpoints to retrieve real-time blockchain data, including asset information. When used with Asset Hub, Sidecar allows querying: +```bash +npx hardhat vars set TESTNET_PRIVATE_KEY +``` -- **Asset look-ups**: Retrieve specific assets using `AssetId`. -- **Asset balances**: View the balance of a particular asset on Asset Hub. +The command will initiate a wizard in which you'll have to enter the value to be stored: -Public instances of API Sidecar connected to Asset Hub are available, such as: +
    + npx hardhat vars set TESTNET_PRIVATE_KEY + ✔ Enter value: · ••••••••• + The configuration variable has been stored in /Users/albertoviera/Library/Preferences/hardhat-nodejs/vars.json +
    -- [Polkadot Asset Hub Sidecar](https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/){target=\_blank} -- [Kusama Asset Hub Sidecar](https://kusama-asset-hub-public-sidecar.parity-chains.parity.io/){target=\_blank} +??? warning "Key Encryption" + This solution just prevents variables to be included in the code repository. You should find a solution that encrypts private keys and access them securely. -These public instances are primarily for ad-hoc testing and quick checks. +You can now use the account related to this private key by importing it into the Hardhat configuration file: -### TxWrapper +```ts title="hardhat.config.ts" hl_lines="1 17" -[`TxWrapper`](https://github.com/paritytech/txwrapper-core){target=\_blank} is a library that simplifies constructing and signing transactions for Polkadot SDK-based chains, including Polkadot and Kusama. This tool includes support for working with Asset Hub, enabling developers to: +const config: HardhatUserConfig = { + solidity: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + networks: { + polkadotTestnet: { + url: vars.get("TESTNET_URL", "http://127.0.0.1:8545"), + accounts: vars.has("TESTNET_PRIVATE_KEY") ? [vars.get("TESTNET_PRIVATE_KEY")] : [], + }, + }, + mocha: { + timeout: 40000, + }, +}; -- Construct offline transactions. -- Leverage asset-specific functions such as minting, burning, and transferring assets. +export default config; +``` -`TxWrapper` provides the flexibility needed to integrate asset operations into custom applications while maintaining the security and efficiency of Polkadot's transaction model. +## Compile your Contract +Once you've configured Hardhat, you can compile the contract. -### Parachain Node +In this tutorial, a simple ERC-20 is provided. Therefore, to compile the contract you can run the following command: -To fully leverage the Asset Hub's functionality, developers will need to run a system parachain node. Setting up an Asset Hub node allows users to interact with the parachain in real time, syncing data and participating in the broader Polkadot ecosystem. Guidelines for setting up an [Asset Hub node](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/cumulus#asset-hub-){target=\_blank} are available in the Parity documentation. +```bash +npx hardhat compile +``` -Using these integration tools, developers can manage assets seamlessly and integrate Asset Hub functionality into their applications, leveraging Polkadot's powerful infrastructure. +If everything compiles successfully, you should see the following output: -## XCM Transfer Monitoring +
    + npx hardhat compile + Generating typings for: 23 artifacts in dir: typechain-types for target: ethers-v6 + Successfully generated 62 typings! + Compiled 21 Solidity files successfully (evm target: paris). +
    -Since Asset Hub facilitates cross-chain asset transfers across the Polkadot ecosystem, XCM transfer monitoring becomes an essential practice for developers and infrastructure providers. This section outlines how to monitor the cross-chain movement of assets between parachains, the relay chain, and other systems. +## Test your Contract -### Monitor XCM Deposits +Hardhat has a native feature to test contracts. You can run tests against the local Hardhat development node, but it could have some technical differences to Polkadot. Therefore, in this tutorial, you'll be testing against the Polkadot TestNet -As assets move between chains, tracking the cross-chain transfers in real time is crucial. Whether assets are transferred via a teleport from system parachains or through a reserve-backed transfer from any other parachain, each transfer emits a relevant event (such as the `balances.minted` event). +This example has a predefined test file located in [`test/Token.test.js`](https://github.com/polkadot-developers/revm-hardhat-examples/blob/master/erc20-hardhat/test/MyToken.test.ts){target=\_blank}, that runs the following tests: -To ensure accurate monitoring of these events: +1. The token was deployed by verifying its **name** and **symbol**. +2. The token has the right owner configured. +3. The token has an initial supply of zero. +4. The owner can mint tokens. +5. The total supply is increased after a mint. +6. Perform multiple mints to different addresses and checks the balance of each address and the new total supply. -- **Track XCM deposits**: Query every new block created in the relay chain or Asset Hub, loop through the events array, and filter for any `balances.minted` events which confirm the asset was successfully transferred to the account. -- **Track event origins**: Each `balances.minted` event points to a specific address. By monitoring this, service providers can verify that assets have arrived in the correct account. +To run the test, you can execute the following command: -### Track XCM Information Back to the Source +```bash +npx hardhat test --network polkadotTestnet +``` -While the `balances.minted` event confirms the arrival of assets, there may be instances where you need to trace the origin of the cross-chain message that triggered the event. In such cases, you can: +If tests are successful, you should see the following logs: -1. Query the relevant chain at the block where the `balances.minted` event was emitted. -2. Look for a `messageQueue(Processed)` event within that block's initialization. This event contains a parameter (`Id`) that identifies the cross-chain message received by the relay chain or Asset Hub. You can use this `Id` to trace the message back to its origin chain, offering full visibility of the asset transfer's journey. +
    + npx hardhat test --network polkadotTestnet + +   MyToken +     Deployment +       ✔ Should have correct name and symbol +       ✔ Should set the right owner +       ✔ Should have zero initial supply +     Minting +       ✔ Should allow owner to mint tokens +       ✔ Should increase total supply on mint +     Multiple mints +       ✔ Should correctly track balance after multiple mints + +   6 passing (369ms) +
    -### Practical Monitoring Examples +## Deploy your Contract -The preceding sections outline the process of monitoring XCM deposits to specific accounts and then tracing back the origin of these deposits. The process of tracking an XCM transfer and the specific events to monitor may vary based on the direction of the XCM message. Here are some examples to showcase the slight differences: +With the Hardhat configuration file ready, the private key stored as a variable under **vars**, and the contract compiled, you can proceed to deploy the contract to a given network. In this tutorial, you are deploying it to the Polkadot TestNet. -- **Transfer from parachain to relay chain**: Track `parachainsystem(UpwardMessageSent)` on the parachain and `messagequeue(Processed)` on the relay chain. -- **Transfer from relay chain to parachain**: Track `xcmPallet(sent)` on the relay chain and `dmpqueue(ExecutedDownward)` on the parachain. -- **Transfer between parachains**: Track `xcmpqueue(XcmpMessageSent)` on the system parachain and `xcmpqueue(Success)` on the destination parachain. +To deploy the contract, run the following command: -### Monitor for Failed XCM Transfers +```bash +npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet +``` -Sometimes, XCM transfers may fail due to liquidity or other errors. Failed transfers emit specific error events, which are key to resolving issues in asset transfers. Monitoring for these failure events helps catch issues before they affect asset balances. +You'll need to confirm the target network (by chain ID): -- **Relay chain to system parachain**: Look for the `dmpqueue(ExecutedDownward)` event on the parachain with an `Incomplete` outcome and an error type such as `UntrustedReserveLocation`. -- **Parachain to parachain**: Monitor for `xcmpqueue(Fail)` on the destination parachain with error types like `TooExpensive`. +
    + npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet + ✔ Confirm deploy to network polkadotTestnet (420420420)? … yes +   + Hardhat Ignition 🚀 +   + Deploying [ TokenModule ] +   + Batch #1 + Executed TokenModule#MyToken +   + Batch #2 + Executed TokenModule#MyToken.mint +   + [ TokenModule ] successfully deployed 🚀 +   + Deployed Addresses +   + TokenModule#MyToken - 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3 +
    -For detailed error management in XCM, see Gavin Wood's blog post on [XCM Execution and Error Management](https://polkadot.com/blog/xcm-part-three-execution-and-error-management/){target=\_blank}. +And that is it! You've successfully deployed an ERC-20 token contract to the Polkadot TestNet using Hardhat. ## Where to Go Next
    -- Tutorial __Register a Local Asset__ - - --- - - Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. - - [:octicons-arrow-right-24: Reference](/chain-interactions/token-operations/register-local-asset/) - -- Tutorial __Register a Foreign Asset__ - - --- - - An in-depth guide to registering a foreign asset on the Asset Hub parachain, providing clear, step-by-step instructions. - - [:octicons-arrow-right-24: Reference](/chain-interactions/token-operations/register-foreign-asset/) - -- Tutorial __Convert Assets__ +- Guide __Deploy an NFT with Remix__ --- - A guide detailing the step-by-step process of converting assets on Asset Hub, helping users efficiently navigate asset management on the platform. + Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. - [:octicons-arrow-right-24: Reference](/chain-interactions/token-operations/convert-assets/) + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/)
    --- -Page Title: Blocks +Page Title: Deploy an ERC-20 to Polkadot Hub -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/ -- Summary: Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/ +- Summary: Deploy an ERC-20 token contract on Polkadot Hub. This guide covers contract creation, compilation, deployment, and interaction via the Remix IDE. -# Blocks +# Deploy an ERC-20 to Polkadot Hub ## Introduction -In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the network. By understanding these concepts, developers can better grasp how blockchains maintain security, consistency, and performance within the Polkadot ecosystem. - -## What is a Block? - -In the Polkadot SDK, a block is a fundamental unit that encapsulates both the header and an array of transactions. The block header includes critical metadata to ensure the integrity and sequence of the blockchain. Here's a breakdown of its components: +[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. -- **Block height**: Indicates the number of blocks created in the chain so far. -- **Parent hash**: The hash of the previous block, providing a link to maintain the blockchain's immutability. -- **Transaction root**: Cryptographic digest summarizing all transactions in the block. -- **State root**: A cryptographic digest representing the post-execution state. -- **Digest**: Additional information that can be attached to a block, such as consensus-related messages. +This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Remix IDE](https://remix.ethereum.org/){target=\_blank}, a web-based development tool. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. -Each transaction is part of a series that is executed according to the runtime's rules. The transaction root is a cryptographic digest of this series, which prevents alterations and enables succinct verification by light clients. This verification process allows light clients to confirm whether a transaction exists in a block with only the block header, avoiding downloading the entire block. +## Prerequisites -## Block Production +Before starting, make sure you have: -When an authoring node is authorized to create a new block, it selects transactions from the transaction queue based on priority. This step, known as block production, relies heavily on the executive module to manage the initialization and finalization of blocks. The process is summarized as follows: +- Basic understanding of Solidity programming and fungible tokens. +- An EVM-compatible wallet [connected to Polkadot Hub](/smart-contracts/integrations/wallets){target=\_blank}. This example utilizes [MetaMask](https://metamask.io/){target=\_blank}. +- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -### Initialize Block +## Create Your Contract -The block initialization process begins with a series of function calls that prepare the block for transaction execution: +To create the ERC-20 contract, you can follow the steps below: -1. **Call `on_initialize`**: The executive module calls the [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hook from the system pallet and other runtime pallets to prepare for the block's transactions. -2. **Coordinate runtime calls**: Coordinates function calls in the order defined by the transaction queue. -3. **Verify information**: Once [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} functions are executed, the executive module checks the parent hash in the block header and the trie root to verify information is consistent. +1. Navigate to the [Polkadot Remix IDE](https://remix.polkadot.io){target=\_blank}. +2. Click in the **Create new file** button under the **contracts** folder, and name your contract as `MyToken.sol`. -### Finalize Block + ![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-1.webp) -Once transactions are processed, the block must be finalized before being broadcast to the network. The finalization steps are as follows: +3. Now, paste the following ERC-20 contract code into the editor: -1. **Call `on_finalize`**: The executive module calls the [`on_finalize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_finalize){target=\_blank} hooks in each pallet to ensure any remaining state updates or checks are completed before the block is sealed and published. -2. **Verify information**: The block's digest and storage root in the header are checked against the initialized block to ensure consistency. -3. **Call `on_idle`**: The [`on_idle`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_idle){target=\_blank} hook is triggered to process any remaining tasks using the leftover weight from the block. + ```solidity title="MyToken.sol" + // SPDX-License-Identifier: MIT + // Compatible with OpenZeppelin Contracts ^5.4.0 + pragma solidity ^0.8.27; -## Block Authoring and Import - -Once the block is finalized, it is gossiped to other nodes in the network. Nodes follow this procedure: - -1. **Receive transactions**: The authoring node collects transactions from the network. -2. **Validate**: Transactions are checked for validity. -3. **Queue**: Valid transactions are placed in the transaction pool for execution. -4. **Execute**: State changes are made as the transactions are executed. -5. **Publish**: The finalized block is broadcast to the network. - -### Block Import Queue - -After a block is published, other nodes on the network can import it into their chain state. The block import queue is part of the outer node in every Polkadot SDK-based node and ensures incoming blocks are valid before adding them to the node's state. - -In most cases, you don't need to know details about how transactions are gossiped or how other nodes on the network import blocks. The following traits are relevant, however, if you plan to write any custom consensus logic or want a deeper dive into the block import queue: + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; + import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -- **[`ImportQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.ImportQueue.html){target=\_blank}**: The trait that defines the block import queue. -- **[`Link`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Link.html){target=\_blank}**: The trait that defines the link between the block import queue and the network. -- **[`BasicQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/struct.BasicQueue.html){target=\_blank}**: A basic implementation of the block import queue. -- **[`Verifier`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Verifier.html){target=\_blank}**: The trait that defines the block verifier. -- **[`BlockImport`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/block_import/trait.BlockImport.html){target=\_blank}**: The trait that defines the block import process. + contract MyToken is ERC20, Ownable, ERC20Permit { + constructor(address initialOwner) + ERC20("MyToken", "MTK") + Ownable(initialOwner) + ERC20Permit("MyToken") + {} -These traits govern how blocks are validated and imported across the network, ensuring consistency and security. + function mint(address to, uint256 amount) public onlyOwner { + _mint(to, amount); + } + } + ``` -## Additional Resources + The key components of the code above are: -To learn more about the block structure in the Polkadot SDK runtime, see the [`Block` reference](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.Block.html){target=\_blank} entry in the Rust Docs. + - Contract imports: + - **[`ERC20.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/ERC20.sol){target=\_blank}**: The base contract for fungible tokens, implementing core functionality like transfers, approvals, and balance tracking. + - **[`ERC20Permit.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/extensions/ERC20Permit.sol){target=\_blank}**: [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612){target=\_blank} extension for ERC-20 that adds the [permit function](https://docs.openzeppelin.com/contracts/5.x/api/token/erc20#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-){target=\_blank}, allowing approvals via off-chain signatures (no on-chain tx from the holder). Manages nonces and EIP-712 domain separator and updates allowances when a valid signature is presented. + - **[`Ownable.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/access/Ownable.sol){target=\_blank}**: Provides basic authorization control, ensuring only the contract owner can mint new tokens. + + - Constructor parameters: ---- + - **`initialOwner`**: Sets the address that will have administrative rights over the contract. + - **`"MyToken"`**: The full name of your token. + - **`"MTK"`**: The symbol representing your token in wallets and exchanges. -Page Title: Bridge Hub + - Key functions: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-bridging.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/bridging/ -- Summary: Learn about the Bridge Hub system parachain, a parachain that facilitates the interactions from Polkadot to the rest of Web3. + - **`mint(address to, uint256 amount)`**: Allows the contract owner to create new tokens for any address. The amount should include 18 decimals (e.g., 1 token = 1000000000000000000). + - Inherited [Standard ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/){target=\_blank} functions: + - **`transfer(address recipient, uint256 amount)`**: Sends a specified amount of tokens to another address. + - **`approve(address spender, uint256 amount)`**: Grants permission for another address to spend a specific number of tokens on behalf of the token owner. + - **`transferFrom(address sender, address recipient, uint256 amount)`**: Transfers tokens from one address to another, if previously approved. + - **`balanceOf(address account)`**: Returns the token balance of a specific address. + - **`allowance(address owner, address spender)`**: Checks how many tokens an address is allowed to spend on behalf of another address. -# Bridge Hub + !!! tip + Use the [OpenZeppelin Contracts Wizard](https://wizard.openzeppelin.com/){target=\_blank} to generate customized smart contracts quickly. Simply configure your contract, copy the generated code, and paste it into the Remix IDE for deployment. Below is an example of an ERC-20 token contract created with it: -## Introduction + ![Screenshot of the OpenZeppelin Contracts Wizard showing an ERC-20 contract configuration.](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-2.webp) + -The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interoperability framework. With built-in support for XCM (Cross-Consensus Messaging), Bridge Hub enables secure, efficient communication between diverse blockchain networks. +## Compile -This guide covers the architecture, components, and deployment of the Bridge Hub system. You'll explore its trustless bridging mechanisms, key pallets for various blockchains, and specific implementations like Snowbridge and the Polkadot <> Kusama bridge. By the end, you'll understand how Bridge Hub enhances connectivity within the Polkadot ecosystem and beyond. +The compilation transforms your Solidity source code into bytecode that can be deployed on the blockchain. During this process, the compiler checks your contract for syntax errors, ensures type safety, and generates the machine-readable instructions needed for blockchain execution. -## Trustless Bridging +To compile your contract, ensure you have it opened in the Remix IDE Editor, and follow the instructions below: -Bridge Hub provides a mode of trustless bridging through its implementation of on-chain light clients and trustless relayers. Trustless bridges are essentially two one-way bridges, where each chain has a method of verifying the state of the other in a trustless manner through consensus proofs. In this context, "trustless" refers to the lack of need to trust a human when interacting with various system components. Trustless systems are based instead on trusting mathematics, cryptography, and code. The target chain and source chain both provide ways of verifying one another's state and actions (such as a transfer) based on the consensus and finality of both chains rather than an external mechanism controlled by a third party. +1. Select the **Solidity Compiler** plugin from the left panel. +2. Click the **Compile MyToken.sol** button. +3. If the compilation succeeded, you'll see a green checkmark indicating success in the **Solidity Compiler** icon. -[BEEFY (Bridge Efficiency Enabling Finality Yielder)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#bridging-beefy){target=\_blank} is instrumental in this solution. It provides a more efficient way to verify the consensus on the relay chain. It allows the participants in a network to verify finality proofs, meaning a remote chain like Ethereum can verify the state of Polkadot at a given block height. +![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-3.gif) -For example, the Ethereum and Polkadot bridging solution that [Snowbridge](https://docs.snowbridge.network/){target=\_blank} implements involves two light clients: one which verifies the state of Polkadot and the other which verifies the state of Ethereum. The light client for Polkadot is implemented in the runtime as a pallet, whereas the light client for Ethereum is implemented as a smart contract on the beacon chain. +## Deploy -## Bridging Components +Deployment is the process of publishing your compiled smart contract to the blockchain, making it permanently available for interaction. During deployment, you'll create a new instance of your contract on the blockchain, which involves: -In any given Bridge Hub implementation (Kusama, Polkadot, or other relay chains), there are a few primary pallets that are utilized: +1. Select the **Deploy & Run Transactions** plugin from the left panel. +2. Configure the deployment settings: + 1. From the **ENVIRONMENT** dropdown, select **Injected Provider - MetaMask** (check the [Deploying Contracts](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} section of the Remix IDE guide for more details). + 2. (Optional) From the **ACCOUNT** dropdown, select the acccount you want to use for the deploy. -- **[Pallet Bridge GRANDPA](https://paritytech.github.io/polkadot-sdk/master/pallet_bridge_grandpa/index.html){target=\_blank}**: An on-chain GRANDPA light client for Substrate based chains. -- **[Pallet Bridge Parachains](https://paritytech.github.io/polkadot-sdk/master/pallet_bridge_parachains/index.html){target=\_blank}**: A finality module for parachains. -- **[Pallet Bridge Messages](https://paritytech.github.io/polkadot-sdk/master/pallet_bridge_messages/index.html){target=\_blank}**: A pallet which allows sending, receiving, and tracking of inbound and outbound messages. -- **[Pallet XCM Bridge](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm_bridge_hub/index.html){target=\_blank}**: A pallet which, with the Bridge Messages pallet, adds XCM support to bridge pallets. +3. Configure the contract parameters: + 1. Enter the address that will own the deployed token contract. + 2. Click the **Deploy** button to initiate the deployment. -### Ethereum-Specific Support +4. **MetaMask will pop up**: Review the transaction details. Click **Confirm** to deploy your contract. +5. If the deployment process succeeded, you will see the transaction details in the terminal, including the contract address and deployment transaction hash. -Bridge Hub also has a set of components and pallets that support a bridge between Polkadot and Ethereum through [Snowbridge](https://github.com/Snowfork/snowbridge){target=\_blank}. +![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-4.gif) -To view the complete list of which pallets are included in Bridge Hub, visit the Subscan [Runtime Modules](https://bridgehub-polkadot.subscan.io/runtime){target=\_blank} page. Alternatively, the source code for those pallets can be found in the Polkadot SDK [Snowbridge Pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/bridges/snowbridge/pallets){target=\_blank} repository. +## Interact with Your Contract -## Deployed Bridges +Once deployed, you can interact with your contract through Remix. Find your contract under **Deployed/Unpinned Contracts**, and click it to expand the available methods. In this example, you'll mint some tokens to a given address: -- [**Snowbridge**](https://wiki.polkadot.com/learn/learn-snowbridge/){target=\_blank}: A general-purpose, trustless bridge between Polkadot and Ethereum. -- [**Hyperbridge**](https://wiki.polkadot.com/learn/learn-hyperbridge/){target=\_blank}: A cross-chain solution built as an interoperability coprocessor, providing state-proof-based interoperability across all blockchains. -- [**Polkadot <> Kusama Bridge**](https://wiki.polkadot.com/learn/learn-dot-ksm-bridge/){target=\_blank}: A bridge that utilizes relayers to bridge the Polkadot and Kusama relay chains trustlessly. +1. Expand the **mint** function: + 1. Enter the recipient address and the amount (remember to add 18 zeros for 1 whole token). + 2. Click **transact**. -## Where to Go Next +2. Click **Approve** to confirm the transaction in the MetaMask popup. -- Go over the Bridge Hub README in the Polkadot SDK [Bridge-hub Parachains](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/cumulus/parachains/runtimes/bridge-hubs/README.md){target=\_blank} repository. -- Take a deeper dive into bridging architecture in the Polkadot SDK [High-Level Bridge](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/bridges/docs/high-level-overview.md){target=\_blank} documentation. -- Read more about [BEEFY and Bridging in the Polkadot Wiki](/reference/polkadot-hub/consensus-and-security/pos-consensus/#bridging-beefy){target=\_blank}. +3. If the transaction succeeds, you will see a green check mark in the terminal. +4. You can also call the **balanceOf** function by passing the address of the **mint** call to confirm the new balance. ---- +![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-5.gif) -Page Title: Chain Data -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/chain-data/ -- Summary: Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. +Other standard functions you can use: -# Chain Data +- **`transfer(address to, uint256 amount)`**: Send tokens to another address. +- **`approve(address spender, uint256 amount)`**: Allow another address to spend your tokens. -## Introduction +Feel free to explore and interact with the contract's other functions using the same approach: select the method, provide any required parameters, and confirm the transaction in MetaMask when needed. -Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you can ensure seamless communication between your applications and the blockchain. +## Where to Go Next -## Application Development +
    -You might not be directly involved in building frontend applications as a blockchain developer. However, most applications that run on a blockchain require some form of frontend or user-facing client to enable users or other programs to access and modify the data that the blockchain stores. For example, you might develop a browser-based, mobile, or desktop application that allows users to submit transactions, post articles, view their assets, or track previous activity. The backend for that application is configured in the runtime logic for your blockchain, but the frontend client makes the runtime features accessible to your users. +- Guide __Deploy an NFT with Remix__ -For your custom chain to be useful to others, you'll need to provide a client application that allows users to view, interact with, or update information that the blockchain keeps track of. In this article, you'll learn how to expose information about your runtime so that client applications can use it, see examples of the information exposed, and explore tools and libraries that use it. + --- -## Understand Metadata + Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. -Polkadot SDK-based blockchain networks are designed to expose their runtime information, allowing developers to learn granular details regarding pallets, RPC calls, and runtime APIs. The metadata also exposes their related documentation. The chain's metadata is [SCALE-encoded](/reference/parachains/data-encoding/){target=\_blank}, allowing for the development of browser-based, mobile, or desktop applications to support the chain's runtime upgrades seamlessly. It is also possible to develop applications compatible with multiple Polkadot SDK-based chains simultaneously. + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) -## Expose Runtime Information as Metadata +
    -To interact with a node or the state of the blockchain, you need to know how to connect to the chain and access the exposed runtime features. This interaction involves a Remote Procedure Call (RPC) through a node endpoint address, commonly through a secure web socket connection. -An application developer typically needs to know the contents of the runtime logic, including the following details: +--- -- Version of the runtime the application is connecting to. -- Supported APIs. -- Implemented pallets. -- Defined functions and corresponding type signatures. -- Defined custom types. -- Exposed parameters users can set. +Page Title: Deploy an NFT to Polkadot Hub with Foundry -As the Polkadot SDK is modular and provides a composable framework for building blockchains, there are limitless opportunities to customize the schema of properties. Each runtime can be configured with its properties, including function calls and types, which can be changed over time with runtime upgrades. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/.foundry/ +- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Foundry, a Rust toolkit with high-performance compilation. -The Polkadot SDK enables you to generate the runtime metadata schema to capture information unique to a runtime. The metadata for a runtime describes the pallets in use and types defined for a specific runtime version. The metadata includes information about each pallet's storage items, functions, events, errors, and constants. The metadata also provides type definitions for any custom types included in the runtime. +# Deploy an NFT with Foundry -Metadata provides a complete inventory of a chain's runtime. It is key to enabling client applications to interact with the node, parse responses, and correctly format message payloads sent back to that chain. +## Introduction -## Generate Metadata +Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. -To efficiently use the blockchain's networking resources and minimize the data transmitted over the network, the metadata schema is encoded using the [Parity SCALE Codec](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank}. This encoding is done automatically through the [`scale-info`](https://docs.rs/scale-info/latest/scale_info/){target=\_blank}crate. +This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. It showcases a secure approach using [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and the [Foundry](https://getfoundry.sh/){target=\_blank} toolchain. Foundry, a fast, Rust-written toolkit, ensures high-performance compilation and is fully compatible with the Hub’s EVM environment via standard Solidity compilation. -At a high level, generating the metadata involves the following steps: +## Prerequisites -1. The pallets in the runtime logic expose callable functions, types, parameters, and documentation that need to be encoded in the metadata. -2. The `scale-info` crate collects type information for the pallets in the runtime, builds a registry of the pallets that exist in a particular runtime, and the relevant types for each pallet in the registry. The type information is detailed enough to enable encoding and decoding for every type. -3. The [`frame-metadata`](https://github.com/paritytech/frame-metadata){target=\_blank} crate describes the structure of the runtime based on the registry provided by the `scale-info` crate. -4. Nodes provide the RPC method `state_getMetadata` to return a complete description of all the types in the current runtime as a hex-encoded vector of SCALE-encoded bytes. +- Basic understanding of Solidity programming and NFT standards. +- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank}. +- A wallet with a private key for signing transactions. -## Retrieve Runtime Metadata +## Set Up Your Project -The type information provided by the metadata enables applications to communicate with nodes using different runtime versions and across chains that expose different calls, events, types, and storage items. The metadata also allows libraries to generate a substantial portion of the code needed to communicate with a given node, enabling libraries like [`subxt`](https://github.com/paritytech/subxt){target=\_blank} to generate frontend interfaces that are specific to a target chain. +To get started, take the following steps: -### Use Polkadot.js +1. Install Foundry: -Visit the [Polkadot.js Portal](https://polkadot.js.org/apps/#/rpc){target=\_blank} and select the **Developer** dropdown in the top banner. Select **RPC Calls** to make the call to request metadata. Follow these steps to make the RPC call: + ```bash + curl -L https://foundry.paradigm.xyz | bash + foundryup + ``` -1. Select **state** as the endpoint to call. -2. Select **`getMetadata(at)`** as the method to call. -3. Click **Submit RPC call** to submit the call and return the metadata in JSON format. +2. Initialize your project: -### Use Curl + ```bash + forge init foundry-nft-deployment + cd foundry-nft-deployment + ``` -You can fetch the metadata for the network by calling the node's RPC endpoint. This request returns the metadata in bytes rather than human-readable JSON: +3. Install OpenZeppelin contracts: -```sh -curl -H "Content-Type: application/json" \ --d '{"id":1, "jsonrpc":"2.0", "method": "state_getMetadata"}' \ -https://rpc.polkadot.io + ```bash + forge install OpenZeppelin/openzeppelin-contracts + ``` -``` +## Configure Foundry -### Use Subxt +Edit `foundry.toml`: -[`subxt`](https://github.com/paritytech/subxt){target=\_blank} may also be used to fetch the metadata of any data in a human-readable JSON format: +```toml title="foundry.toml" +[profile.default] +src = "src" +out = "out" +libs = ["lib"] +remappings = ['@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/'] -```sh -subxt metadata --url wss://rpc.polkadot.io --format json > spec.json +[rpc_endpoints] +polkadot_hub_testnet = "https://testnet-passet-hub-eth-rpc.polkadot.io" ``` -Another option is to use the [`subxt` explorer web UI](https://paritytech.github.io/subxt-explorer/#/){target=\_blank}. - -## Client Applications and Metadata - -The metadata exposes the expected way to decode each type, meaning applications can send, retrieve, and process application information without manual encoding and decoding. Client applications must use the [SCALE codec library](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank} to encode and decode RPC payloads to use the metadata. Client applications use the metadata to interact with the node, parse responses, and format message payloads sent to the node. - -## Metadata Format - -Although the SCALE-encoded bytes can be decoded using the `frame-metadata` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} libraries, there are other tools, such as `subxt` and the Polkadot-JS API, that can convert the raw data to human-readable JSON format. +## Create Your Contract -The types and type definitions included in the metadata returned by the `state_getMetadata` RPC call depend on the runtime's metadata version. +Create `src/MyNFT.sol`: -In general, the metadata includes the following information: +```solidity title="src/MyNFT.sol" +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; -- A constant identifying the file as containing metadata. -- The version of the metadata format used in the runtime. -- Type definitions for all types used in the runtime and generated by the `scale-info` crate. -- Pallet information for the pallets included in the runtime in the order that they are defined in the `construct_runtime` macro. +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; -!!!tip - Depending on the frontend library used (such as the [Polkadot API](https://papi.how/){target=\_blank}), they may format the metadata differently than the raw format shown. +contract MyNFT is ERC721, Ownable { + uint256 private _nextTokenId; -The following example illustrates a condensed and annotated section of metadata decoded and converted to JSON: + constructor(address initialOwner) + ERC721("MyToken", "MTK") + Ownable(initialOwner) + {} -```json -[ - 1635018093, - { - "V14": { - "types": { - "types": [{}] - }, - "pallets": [{}], - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [{}] - }, - "ty": 141 - } + function safeMint(address to) public onlyOwner { + uint256 tokenId = _nextTokenId++; + _safeMint(to, tokenId); } -] - -``` - -The constant `1635018093` is a magic number that identifies the file as a metadata file. The rest of the metadata is divided into the `types`, `pallets`, and `extrinsic` sections: - -- The `types` section contains an index of the types and information about each type's type signature. -- The `pallets` section contains information about each pallet in the runtime. -- The `extrinsic` section describes the type identifier and transaction format version that the runtime uses. - -Different extrinsic versions can have varying formats, especially when considering [signed transactions](/reference/parachains/blocks-transactions-fees/transactions/#signed-transactions){target=\_blank}. - -### Pallets - -The following is a condensed and annotated example of metadata for a single element in the `pallets` array (the [`sudo`](https://paritytech.github.io/polkadot-sdk/master/pallet_sudo/index.html){target=\_blank} pallet): - -```json -{ - "name": "Sudo", - "storage": { - "prefix": "Sudo", - "entries": [ - { - "name": "Key", - "modifier": "Optional", - "ty": { - "Plain": 0 - }, - "default": [0], - "docs": ["The `AccountId` of the sudo key."] - } - ] - }, - "calls": { - "ty": 117 - }, - "event": { - "ty": 42 - }, - "constants": [], - "error": { - "ty": 124 - }, - "index": 8 } - ``` -Every element metadata contains the name of the pallet it represents and information about its storage, calls, events, and errors. You can look up details about the definition of the calls, events, and errors by viewing the type index identifier. The type index identifier is the `u32` integer used to access the type information for that item. For example, the type index identifier for calls in the Sudo pallet is 117. If you view information for that type identifier in the `types` section of the metadata, it provides information about the available calls, including the documentation for each call. +## Compile -For example, the following is a condensed excerpt of the calls for the Sudo pallet: +```bash +forge build +``` -```json -{ - "id": 117, - "type": { - "path": ["pallet_sudo", "pallet", "Call"], - "params": [ - { - "name": "T", - "type": null - } - ], - "def": { - "variant": { - "variants": [ - { - "name": "sudo", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 0, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "sudo_unchecked_weight", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - }, - { - "name": "weight", - "type": 8, - "typeName": "Weight" - } - ], - "index": 1, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "set_key", - "fields": [ - { - "name": "new", - "type": 103, - "typeName": "AccountIdLookupOf" - } - ], - "index": 2, - "docs": [ - "Authenticates current sudo key, sets the given AccountId (`new`) as the new sudo" - ] - }, - { - "name": "sudo_as", - "fields": [ - { - "name": "who", - "type": 103, - "typeName": "AccountIdLookupOf" - }, - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 3, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Signed` origin from a given account" - ] - } - ] - } - } - } -} +Verify the compilation by inspecting the bytecode: +```bash +forge inspect MyNFT bytecode ``` -For each field, you can access type information and metadata for the following: - -- **Storage metadata**: Provides the information required to enable applications to get information for specific storage items. -- **Call metadata**: Includes information about the runtime calls defined by the `#[pallet]` macro including call names, arguments and documentation. -- **Event metadata**: Provides the metadata generated by the `#[pallet::event]` macro, including the name, arguments, and documentation for each pallet event. -- **Constants metadata**: Provides metadata generated by the `#[pallet::constant]` macro, including the name, type, and hex-encoded value of the constant. -- **Error metadata**: Provides metadata generated by the `#[pallet::error]` macro, including the name and documentation for each pallet error. +## Deploy -!!!tip - Type identifiers change from time to time, so you should avoid relying on specific type identifiers in your applications. +Deploy to Polkadot Hub TestNet: -### Extrinsic +```bash +forge create MyNFT \ + --rpc-url polkadot_hub_testnet \ + --private-key YOUR_PRIVATE_KEY \ + --constructor-args YOUR_OWNER_ADDRESS \ + --broadcast +``` -The runtime generates extrinsic metadata and provides useful information about transaction format. When decoded, the metadata contains the transaction version and the list of signed extensions. +Replace `YOUR_PRIVATE_KEY` with your private key and `YOUR_OWNER_ADDRESS` with the address that will own the NFT contract. -For example: +## Where to Go Next -```json -{ - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [ - { - "identifier": "CheckNonZeroSender", - "ty": 132, - "additional_signed": 41 - }, - { - "identifier": "CheckSpecVersion", - "ty": 133, - "additional_signed": 4 - }, - { - "identifier": "CheckTxVersion", - "ty": 134, - "additional_signed": 4 - }, - { - "identifier": "CheckGenesis", - "ty": 135, - "additional_signed": 11 - }, - { - "identifier": "CheckMortality", - "ty": 136, - "additional_signed": 11 - }, - { - "identifier": "CheckNonce", - "ty": 138, - "additional_signed": 41 - }, - { - "identifier": "CheckWeight", - "ty": 139, - "additional_signed": 41 - }, - { - "identifier": "ChargeTransactionPayment", - "ty": 140, - "additional_signed": 41 - } - ] - }, - "ty": 141 -} +
    -``` +- Guide __Verify Your Contract__ -The type system is [composite](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank}, meaning each type identifier contains a reference to a specific type or to another type identifier that provides information about the associated primitive types. + --- -For example, you can encode the `BitVec` type, but to decode it properly, you must know the types used for the `Order` and `Store` types. To find type information for `Order` and `Store`, you can use the path in the decoded JSON to locate their type identifiers. + Now that you've deployed an NFT contract, learn how to verify it with Foundry. -## Included RPC APIs + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/foundry/verify-a-contract/) -A standard node comes with the following APIs to interact with a node: +- Guide __Deploy an ERC-20__ -- **[`AuthorApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/author/trait.AuthorApiServer.html){target=\_blank}**: Make calls into a full node, including authoring extrinsics and verifying session keys. -- **[`ChainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/chain/trait.ChainApiServer.html){target=\_blank}**: Retrieve block header and finality information. -- **[`OffchainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/offchain/trait.OffchainApiServer.html){target=\_blank}**: Make RPC calls for off-chain workers. -- **[`StateApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/state/trait.StateApiServer.html){target=\_blank}**: Query information about on-chain state such as runtime version, storage items, and proofs. -- **[`SystemApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/system/trait.SystemApiServer.html){target=\_blank}**: Retrieve information about network state, such as connected peers and node roles. + --- -## Additional Resources + Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Foundry. -The following tools can help you locate and decode metadata: + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/foundry/) -- [Subxt Explorer](https://paritytech.github.io/subxt-explorer/#/){target=\_blank} -- [Metadata Portal 🌗](https://github.com/paritytech/metadata-portal){target=\_blank} -- [De[code] Sub[strate]](https://github.com/paritytech/desub){target=\_blank} +
    --- -Page Title: Collectives Chain - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-collectives-and-daos.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/collectives-and-daos/ -- Summary: Learn how the Collectives chain provides infrastructure for governance organizations, enabling decentralized network stewardship and decision-making. - -## Introduction +Page Title: Deploy an NFT to Polkadot Hub with Hardhat -Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/ +- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub with Hardhat, a comprehenive development environment with built-in deployment capabilities. -The architecture enables entire networks to function as unified entities, allowing them to present cohesive positions and participate in cross-network governance through [Bridge Hub](/polkadot-protocol/architecture/system-chains/bridge-hub){target=\_blank}. This capability represents a fundamental advancement in Web3 principles, eliminating dependencies on traditional third-party intermediaries such as legal systems or jurisdictional authorities. +# Deploy an NFT with Hardhat -## Key Collectives +## Introduction -The Collectives chain hosts several important governance bodies: +Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. -- [**Polkadot Technical Fellowship**](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank}: A self-governing assembly of protocol experts and developers who oversee technical aspects of the Polkadot and Kusama networks. The Fellowship operates both on-chain through the collectives system and off-chain via GitHub repositories, public discussion forums, and monthly development calls that are publicly accessible. +This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Hardhat](https://hardhat.org/docs/getting-started){target=\_blank}, a comprehensive development environment with built-in testing, debugging, and deployment capabilities. Hardhat uses standard Solidity compilation to generate EVM bytecode, making it fully compatible with Polkadot Hub's EVM environment. -- [**Polkadot Alliance**](https://wiki.polkadot.com/general/glossary/#polkadot-alliance){target=\_blank}: A consortium founded by seven leading parachain projects (Acala, Astar, Interlay, Kilt, Moonbeam, Phala, and Subscan) to establish development standards and ethical guidelines within the ecosystem. This ranked collective, comprised of "Fellows" and "Allies," focuses on promoting best practices and identifying potential bad actors. Membership is primarily designed for organizations, projects, and other networks rather than individuals. +## Prerequisites -These collectives serve as pillars of Polkadot's decentralized governance model, enabling community-driven decision-making and establishing technical standards that shape the network's evolution. Through structured on-chain representation, they provide transparent mechanisms for ecosystem development while maintaining the core Web3 principles of trustlessness and decentralization. +- Basic understanding of Solidity programming and NFT standards. +- Node.js v22.13.1 or later. +- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. +- A wallet with a private key for signing transactions. +## Set Up Your Project ---- +Take the following steps to get started: -Page Title: Contract Deployment +1. Initialize your Hardhat project: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-contract-deployment.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/contract-deployment/ -- Summary: Compare deployment flows for REVM and PVM-based smart contracts on the Polkadot Hub. Includes single-step REVM flows and PVM’s two-step deployment model. + ```bash + mkdir hardhat-nft-deployment + cd hardhat-nft-deployment + npx hardhat --init + ``` -# Contract Deployment +2. Install OpenZeppelin contracts: -## Introduction + ```bash + npm install @openzeppelin/contracts + ``` -Polkadot's smart contract platform supports two distinct virtual machine backends: Rust Ethereum Virtual Machine (REVM) and PolkaVM. Each backend has its own deployment characteristics and optimization strategies. REVM provides full Ethereum compatibility with familiar single-step deployment, while the RISC-V-based PolkaVM uses a more structured two-step approach optimized for its architecture. Understanding these differences ensures smooth deployment regardless of which backend you choose for your smart contracts. +## Configure Hardhat -## REVM Deployment +Edit `hardhat.config.ts`: -The REVM backend enables seamless deployment of Ethereum contracts without modification. Contracts deploy exactly as they would on Ethereum, using familiar tools and workflows. +```typescript title="hardhat.config.ts" +import type { HardhatUserConfig } from 'hardhat/config'; -With REVM, deployment mirrors the Ethereum flow exactly including: +import hardhatToolboxViemPlugin from '@nomicfoundation/hardhat-toolbox-viem'; +import { configVariable } from 'hardhat/config'; -- Contracts are bundled and deployed in a single transaction. -- Factory contracts can create new contracts at runtime. -- Runtime code generation, including inline assembly, is supported. -- Existing familiar tools like Hardhat, Foundry, and Remix work out of the box. - -## PolkaVM Deployment - -PolkaVM implements a fundamentally different deployment model optimized for its RISC-V architecture. While simple contract deployments work seamlessly, advanced patterns like factory contracts require understanding the two-step deployment process. +const config: HardhatUserConfig = { + plugins: [hardhatToolboxViemPlugin], + solidity: { + profiles: { + default: { + version: '0.8.28', + }, + production: { + version: '0.8.28', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + }, + }, + networks: { + hardhatMainnet: { + type: 'edr-simulated', + chainType: 'l1', + }, + hardhatOp: { + type: 'edr-simulated', + chainType: 'op', + }, + sepolia: { + type: 'http', + chainType: 'l1', + url: configVariable('SEPOLIA_RPC_URL'), + accounts: [configVariable('SEPOLIA_PRIVATE_KEY')], + }, + polkadotHubTestnet: { + type: 'http', + url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + accounts: [configVariable('PRIVATE_KEY')], + }, + }, +}; -### Standard Contract Deployment +export default config; +``` -For most use cases, such as deploying ERC-20 tokens, NFT collections, or standalone contracts, deployment is transparent and requires no special steps. The [Revive compiler](https://github.com/paritytech/revive){target=\_blank} handles the deployment process automatically when using standard Solidity patterns. +!!! tip + Learn how to use Hardhat's [Config Variables](https://hardhat.org/docs/learn-more/configuration-variables){target=\_blank} to handle your private keys in a secure way. -### Two-Step Deployment Model +## Create Your Contract -PolkaVM separates contract deployment into distinct phases: +Create `contracts/MyNFT.sol`: -1. **Code upload**: Contract bytecode must be uploaded to the chain before instantiation. -2. **Contract instantiation**: Contracts are created by referencing previously uploaded code via its hash. +```solidity title="contracts/MyNFT.sol" +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; -This architecture differs from the EVM's bundled approach and has important implications for specific deployment patterns. +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; -### Factory Pattern Considerations +contract MyNFT is ERC721, Ownable { + uint256 private _nextTokenId; -The common EVM pattern, where contracts dynamically create other contracts, requires adaptation for PolkaVM as follows: + constructor(address initialOwner) + ERC721("MyToken", "MTK") + Ownable(initialOwner) + {} -**EVM Factory Pattern:** -```solidity -// This works on REVM but requires modification for PolkaVM -contract Factory { - function createToken() public returns (address) { - // EVM bundles bytecode in the factory - return address(new Token()); + function safeMint(address to) public onlyOwner { + uint256 tokenId = _nextTokenId++; + _safeMint(to, tokenId); } } ``` -**PolkaVM Requirements:** - -- **Pre-upload dependent contracts**: All contracts that will be instantiated at runtime must be uploaded to the chain before the factory attempts to create them. -- **Code hash references**: Factory contracts work with pre-uploaded code hashes rather than embedding bytecode. -- **No runtime code generation**: Dynamic bytecode generation is not supported due to PolkaVM's RISC-V format. - -### Migration Strategy for Factory Contracts - -When migrating factory contracts from Ethereum to PolkaVM: - -1. **Identify all contracts**: Determine which contracts will be instantiated at runtime. -2. **Upload dependencies first**: Deploy all dependent contracts to the chain before deploying the factory. -3. **Use on-chain constructors**: Leverage PolkaVM's on-chain constructor feature for flexible instantiation. -4. **Avoid assembly creation**: Don't use `create` or `create2` opcodes in assembly blocks for manual deployment. - -### Architecture-Specific Limitations +## Compile -PolkaVM's deployment model creates several specific constraints: +```bash +npx hardhat compile +``` -- **`EXTCODECOPY` limitations**: Contracts using `EXTCODECOPY` to manipulate code at runtime will encounter issues. -- **Runtime code modification**: Patterns that construct and mutate contract code on-the-fly are not supported. -- **Assembly-based factories**: Factory contracts written in YUL assembly that generate code at runtime will fail with `CodeNotFound` errors. +## Set Up Deployment -These patterns are rare in practice and typically require dropping down to assembly, making them non-issues for standard Solidity development. +Create a deployment module in `ignition/modules/MyNFT.ts`: -### On-Chain Constructors +```typescript title="ignition/modules/MyNFT.ts" +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -PolkaVM provides on-chain constructors as an elegant alternative to runtime code modification: +export default buildModule('MyNFTModule', (m) => { + const initialOwner = m.getParameter('initialOwner', 'INSERT_OWNER_ADDRESS'); + const myNFT = m.contract('MyNFT', [initialOwner]); + return { myNFT }; +}); +``` -- Enable contract instantiation without runtime code generation. -- Support flexible initialization patterns. -- Maintain separation between code upload and contract creation. -- Provide predictable deployment costs. +Replace `INSERT_OWNER_ADDRESS` with your desired owner address. -## Gas Estimation vs Actual Consumption +## Deploy -Both REVM and PolkaVM deployments may show significant differences between gas estimation and actual consumption. You might see estimates that are several times higher than the actual gas consumed (often around 30% of the estimate). This is normal behavior because pre-dispatch estimation cannot distinguish between computation weight and storage deposits, leading to conservative overestimation. Contract deployments are particularly affected as they consume significant storage deposits for code storage. +Deploy to Polkadot Hub TestNet: -## Deployment Comparison +```bash +npx hardhat ignition deploy ignition/modules/MyNFT.ts --network polkadotHubTestnet +``` -| Feature | REVM Backend | PolkaVM Backend | -|:-------:|:-------------:|:----------------:| -| **Deployment Model** | Single-step bundled | Two-step upload and instantiate | -| **Factory Patterns** | Direct runtime creation | Requires pre-uploaded code | -| **Code Bundling** | Bytecode in transaction | Code hash references | -| **Runtime Codegen** | Fully supported | Not supported | -| **Simple Contracts** | No modifications needed | No modifications needed | -| **Assembly Creation** | Supported | Discouraged, limited support | +## Where to Go Next -## Conclusion +
    -Both backends support contract deployment effectively, with REVM offering drop-in Ethereum compatibility and PolkaVM providing a more structured two-step approach. For the majority of use cases—deploying standard contracts like tokens or applications—both backends work seamlessly. Advanced patterns like factory contracts may require adjustment for PolkaVM, but these adaptations are straightforward with proper planning. +- Guide __Verify Your Contract__ + --- ---- + Now that you've deployed an NFT contract, learn how to verify it with Hardhat. -Page Title: Cryptography + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/verify-a-contract/) -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/cryptography/ -- Summary: A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. -# Cryptography +- Guide __Deploy an ERC-20__ -## Introduction + --- -Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem. + Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Hardhat. -## Hash Functions + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/hardhat/) -Hash functions are fundamental to blockchain technology, creating a unique digital fingerprint for any piece of data, including simple text, images, or any other form of file. They map input data of any size to a fixed-size output (typically 32 bytes) using complex mathematical operations. Hashing is used to verify data integrity, create digital signatures, and provide a secure way to store passwords. This form of mapping is known as the ["pigeonhole principle,"](https://en.wikipedia.org/wiki/Pigeonhole_principle){target=\_blank} it is primarily implemented to efficiently and verifiably identify data from large sets. +
    -### Key Properties of Hash Functions -- **Deterministic**: The same input always produces the same output. -- **Quick computation**: It's easy to calculate the hash value for any given input. -- **Pre-image resistance**: It's infeasible to generate the input data from its hash. -- **Small changes in input yield large changes in output**: Known as the ["avalanche effect"](https://en.wikipedia.org/wiki/Avalanche_effect){target=\_blank}. -- **Collision resistance**: The probabilities are extremely low to find two different inputs with the same hash. +--- -### Blake2 +Page Title: Deploy an NFT to Polkadot Hub with Remix -The Polkadot SDK utilizes Blake2, a state-of-the-art hashing method that offers: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/ +- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Remix, a browser-based IDE for quick prototyping and learning. -- Equal or greater security compared to [SHA-2](https://en.wikipedia.org/wiki/SHA-2){target=\_blank}. -- Significantly faster performance than other algorithms. +# Deploy an NFT with Remix -These properties make Blake2 ideal for blockchain systems, reducing sync times for new nodes and lowering the resources required for validation. For detailed technical specifications about Blake2, see the [official Blake2 paper](https://www.blake2.net/blake2.pdf){target=\_blank}. +## Introduction -## Types of Cryptography +Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. -There are two different ways that cryptographic algorithms are implemented: symmetric cryptography and asymmetric cryptography. +This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Remix](https://remix.ethereum.org/){target=\_blank}, a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development. -### Symmetric Cryptography +## Prerequisites -Symmetric encryption is a branch of cryptography that isn't based on one-way functions, unlike asymmetric cryptography. It uses the same cryptographic key to encrypt plain text and decrypt the resulting ciphertext. +- Basic understanding of Solidity programming and NFT standards. +- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank} +- A wallet with a private key for signing transactions. -Symmetric cryptography is a type of encryption that has been used throughout history, such as the Enigma Cipher and the Caesar Cipher. It is still widely used today and can be found in Web2 and Web3 applications alike. There is only one single key, and a recipient must also have access to it to access the contained information. +## Access Remix -#### Advantages {: #symmetric-advantages } +Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. -- Fast and efficient for large amounts of data. -- Requires less computational power. +The interface will load with a default workspace containing sample contracts. In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. -#### Disadvantages {: #symmetric-disadvantages } +## Create Your Contract -- Key distribution can be challenging. -- Scalability issues in systems with many users. +1. Create a new file `contracts/MyNFT.sol`. +2. Paste the following code: -### Asymmetric Cryptography + ```solidity title="contracts/MyNFT.sol" + // SPDX-License-Identifier: MIT + pragma solidity ^0.8.20; -Asymmetric encryption is a type of cryptography that uses two different keys, known as a keypair: a public key, used to encrypt plain text, and a private counterpart, used to decrypt the ciphertext. + import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + import "@openzeppelin/contracts/access/Ownable.sol"; -The public key encrypts a fixed-length message that can only be decrypted with the recipient's private key and, sometimes, a set password. The public key can be used to cryptographically verify that the corresponding private key was used to create a piece of data without compromising the private key, such as with digital signatures. This has obvious implications for identity, ownership, and properties and is used in many different protocols across Web2 and Web3. + contract MyNFT is ERC721, Ownable { + uint256 private _nextTokenId; -#### Advantages {: #asymmetric-advantages } + constructor(address initialOwner) + ERC721("MyToken", "MTK") + Ownable(initialOwner) + {} -- Solves the key distribution problem. -- Enables digital signatures and secure key exchange. + function safeMint(address to) public onlyOwner { + uint256 tokenId = _nextTokenId++; + _safeMint(to, tokenId); + } + } + ``` -#### Disadvantages {: #asymmetric-disadvantages } +![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-01.webp) -- Slower than symmetric encryption. -- Requires more computational resources. +## Compile -### Trade-offs and Compromises +1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). +2. Click **Compile MyNFT.sol** or press `Ctrl+S`. -Symmetric cryptography is faster and requires fewer bits in the key to achieve the same level of security that asymmetric cryptography provides. However, it requires a shared secret before communication can occur, which poses issues to its integrity and a potential compromise point. On the other hand, asymmetric cryptography doesn't require the secret to be shared ahead of time, allowing for far better end-user security. +![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-02.webp) -Hybrid symmetric and asymmetric cryptography is often used to overcome the engineering issues of asymmetric cryptography, as it is slower and requires more bits in the key to achieve the same level of security. It encrypts a key and then uses the comparatively lightweight symmetric cipher to do the "heavy lifting" with the message. +Compilation errors and warnings appear in the terminal panel at the bottom of the screen. -## Digital Signatures +## Deploy -Digital signatures are a way of verifying the authenticity of a document or message using asymmetric keypairs. They are used to ensure that a sender or signer's document or message hasn't been tampered with in transit, and for recipients to verify that the data is accurate and from the expected sender. +1. Navigate to the **Deploy & Run Transactions** tab. +2. Click the **Environment** dropdown, select **Browser Extension**, and click on **Injected Provider - MetaMask**. -Signing digital signatures only requires a low-level understanding of mathematics and cryptography. For a conceptual example -- when signing a check, it is expected that it cannot be cashed multiple times. This isn't a feature of the signature system but rather the check serialization system. The bank will check that the serial number on the check hasn't already been used. Digital signatures essentially combine these two concepts, allowing the signature to provide the serialization via a unique cryptographic fingerprint that cannot be reproduced. + ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-03.webp) -Unlike pen-and-paper signatures, knowledge of a digital signature cannot be used to create other signatures. Digital signatures are often used in bureaucratic processes, as they are more secure than simply scanning in a signature and pasting it onto a document. +3. In the deploy section, enter the initial owner address in the constructor parameter field. +4. Click **Deploy**. -Polkadot SDK provides multiple different cryptographic schemes and is generic so that it can support anything that implements the [`Pair` trait](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Pair.html){target=\_blank}. + ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-04.webp) -### Example of Creating a Digital Signature +5. Approve the transaction in your MetaMask wallet. -The process of creating and verifying a digital signature involves several steps: +Your deployed contract will appear in the **Deployed Contracts** section, ready for interaction. -1. The sender creates a hash of the message. -2. The hash is encrypted using the sender's private key, creating the signature. -3. The message and signature are sent to the recipient. -4. The recipient decrypts the signature using the sender's public key. -5. The recipient hashes the received message and compares it to the decrypted hash. +## Where to Go Next -If the hashes match, the signature is valid, confirming the message's integrity and the sender's identity. +
    -## Elliptic Curve +- Guide __Verify Your Contract__ -Blockchain technology requires the ability to have multiple keys creating a signature for block proposal and validation. To this end, Elliptic Curve Digital Signature Algorithm (ECDSA) and Schnorr signatures are two of the most commonly used methods. While ECDSA is a far simpler implementation, Schnorr signatures are more efficient when it comes to multi-signatures. + --- -Schnorr signatures bring some noticeable features over the ECDSA/EdDSA schemes: + Now that you've deployed an NFT contract, learn how to verify it with Remix. -- It is better for hierarchical deterministic key derivations. -- It allows for native multi-signature through [signature aggregation](https://bitcoincore.org/en/2017/03/23/schnorr-signature-aggregation/){target=\_blank}. -- It is generally more resistant to misuse. + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/verify-a-contract/) -One sacrifice that is made when using Schnorr signatures over ECDSA is that both require 64 bytes, but only ECDSA signatures communicate their public key. +- Guide __Deploy an ERC-20__ -### Various Implementations + --- -- **[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm){target=\_blank}**: Polkadot SDK provides an ECDSA signature scheme using the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1){target=\_blank} curve. This is the same cryptographic algorithm used to secure [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin){target=\_blank} and [Ethereum](https://en.wikipedia.org/wiki/Ethereum){target=\_blank}. + Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Remix. -- **[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519){target=\_blank}**: An EdDSA signature scheme using [Curve25519](https://en.wikipedia.org/wiki/Curve25519){target=\_blank}. It is carefully engineered at several levels of design and implementation to achieve very high speeds without compromising security. + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) -- **[SR25519](https://research.web3.foundation/Polkadot/security/keys/accounts-more){target=\_blank}**: Based on the same underlying curve as Ed25519. However, it uses Schnorr signatures instead of the EdDSA scheme. +
    --- -Page Title: Data Encoding +Page Title: Dual Virtual Machine Stack -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/data-encoding/ -- Summary: SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/ +- Summary: Compare Polkadot’s dual smart contract VMs—REVM for EVM compatibility and PolkaVM for RISC-V performance, flexibility, and efficiency. -# Data Encoding +# Dual Virtual Machine Stack +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data. - -The SCALE codec enables communication between the runtime and the outer node. This mechanism is designed for high-performance, copy-free data encoding and decoding in resource-constrained environments like the Polkadot SDK [Wasm runtime](/develop/parachains/deployment/build-deterministic-runtime/#introduction){target=\_blank}. - -It is not self-describing, meaning the decoding context must fully know the encoded data types. - -Parity's libraries utilize the [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} crate (a Rust implementation of the SCALE codec) to handle encoding and decoding for interactions between RPCs and the runtime. - -The `codec` mechanism is ideal for Polkadot SDK-based chains because: - -- It is lightweight compared to generic serialization frameworks like [`serde`](https://serde.rs/){target=\_blank}, which add unnecessary bulk to binaries. -- It doesn’t rely on Rust’s `libstd`, making it compatible with `no_std` environments like Wasm runtime. -- It integrates seamlessly with Rust, allowing easy derivation of encoding and decoding logic for new types using `#[derive(Encode, Decode)]`. - -Defining a custom encoding scheme in the Polkadot SDK-based chains, rather than using an existing Rust codec library, is crucial for enabling cross-platform and multi-language support. - -## SCALE Codec - -The codec is implemented using the following traits: - -- [`Encode`](#encode) -- [`Decode`](#decode) -- [`CompactAs`](#compactas) -- [`HasCompact`](#hascompact) -- [`EncodeLike`](#encodelike) - -### Encode +Polkadot's smart contract platform supports two distinct virtual machine (VM) architectures, providing developers with flexibility in selecting the optimal execution backend for their specific needs. This approach strikes a balance between immediate Ethereum compatibility and long-term innovation, enabling developers to deploy either unmodified (Ethereum Virtual Machine) EVM contracts using Rust Ethereum Virtual Machine (REVM) or optimize for higher performance using PolkaVM (PVM). -The [`Encode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Encode.html){target=\_blank} trait handles data encoding into SCALE format and includes the following key functions: +Both VM options share common infrastructure, including RPC interfaces, tooling support, and precompiles. The following sections compare architectures and guide you in selecting the best VM for your project's needs. -- **`size_hint(&self) -> usize`**: Estimates the number of bytes required for encoding to prevent multiple memory allocations. This should be inexpensive and avoid complex operations. Optional if the size isn’t known. -- **`encode_to(&self, dest: &mut T)`**: Encodes the data, appending it to a destination buffer. -- **`encode(&self) -> Vec`**: Encodes the data and returns it as a byte vector. -- **`using_encoded R>(&self, f: F) -> R`**: Encodes the data and passes it to a closure, returning the result. -- **`encoded_size(&self) -> usize`**: Calculates the encoded size. Should be used when the encoded data isn’t required. +## Migrate from EVM -!!!tip - For best performance, value types should override `using_encoded`, and allocating types should override `encode_to`. It's recommended to implement `size_hint` for all types where possible. +The [REVM backend](https://github.com/bluealloy/revm){target=\_blank} integrates a complete Rust implementation of the EVM, enabling Solidity contracts to run unchanged on Polkadot's smart contract platform. -### Decode +REVM allows developers to use their existing Ethereum tooling and infrastructure to build on Polkadot. Choose REVM to: -The [`Decode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Decode.html){target=\_blank} trait handles decoding SCALE-encoded data back into the appropriate types: +- Migrate existing Ethereum contracts without modifications. +- Retain exact EVM behavior for audit tools. +- Use developer tools that rely upon inspecting EVM bytecode. +- Prioritize rapid deployment over optimization. +- Work with established Ethereum infrastructure and tooling to build on Polkadot. -- **`fn decode(value: &mut I) -> Result`**: Decodes data from the SCALE format, returning an error if decoding fails. +REVM enables Ethereum developers to seamlessly migrate to Polkadot, achieving performance and fee improvements without modifying their existing contracts or developer tooling stack. -### CompactAs +## Upgrade to PolkaVM -The [`CompactAs`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.CompactAs.html){target=\_blank} trait wraps custom types for compact encoding: +[**PolkaVM**](https://github.com/paritytech/polkavm){target=\_blank} is a custom virtual machine optimized for performance with [RISC-V-based](https://en.wikipedia.org/wiki/RISC-V){target=\_blank} architecture, supporting Solidity and additional high-performance languages. It serves as the core execution environment, integrated directly within the runtime. Choose the PolkaVM for: -- **`encode_as(&self) -> &Self::As`**: Encodes the type as a compact type. -- **`decode_from(_: Self::As) -> Result`**: decodes from a compact encoded type. +- An efficient interpreter for immediate code execution. +- A planned [Just In Time (JIT)](https://en.wikipedia.org/wiki/Just-in-time_compilation){target=\_blank} compiler for optimized performance. +- Dual-mode execution capability, allowing selection of the most appropriate backend for specific workloads. +- Optimized performance for short-running contract calls through the interpreter. -### HasCompact +The interpreter remains particularly beneficial for contracts with minimal code execution, as it enables immediate code execution through lazy interpretation. -The [`HasCompact`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.HasCompact.html){target=\_blank} trait indicates a type supports compact encoding. +## Architecture -### EncodeLike +The following key components of PolkaVM work together to enable Ethereum compatibility on Polkadot-based chains. -The [`EncodeLike`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.EncodeLike.html){target=\_blank} trait is used to ensure multiple types that encode similarly are accepted by the same function. When using `derive`, it is automatically implemented. +### Revive Pallet -### Data Types +[**`pallet_revive`**](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/index.html){target=\_blank} is a runtime module that executes smart contracts by adding extrinsics, runtime APIs, and logic to convert Ethereum-style transactions into formats compatible with Polkadot SDK-based blockchains. It processes Ethereum-style transactions through the following workflow: -The table below outlines how the Rust implementation of the Parity SCALE codec encodes different data types. - -| Type | Description | Example SCALE Decoded Value | SCALE Encoded Value | -|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| -| Boolean | Boolean values are encoded using the least significant bit of a single byte. | `false` / `true` | `0x00` / `0x01` | -| Compact/general integers | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2^536) and is more efficient at encoding most values than the fixed-width version. | `unsigned integer 0` / `unsigned integer 1` / `unsigned integer 42` / `unsigned integer 69` / `unsigned integer 65535` / `BigInt(100000000000000)` | `0x00` / `0x04` / `0xa8` / `0x1501` / `0xfeff0300` / `0x0b00407a10f35a` | -| Enumerations (tagged-unions) | A fixed number of variants, each mutually exclusive and potentially implying a further value or series of values. Encoded as the first byte identifying the index of the variant that the value is. Any further bytes are used to encode any data that the variant implies. Thus, no more than 256 variants are supported. | `Int(42)` and `Bool(true)` where `enum IntOrBool { Int(u8), Bool(bool) }` | `0x002a` and `0x0101` | -| Fixed-width integers | Basic integers are encoded using a fixed-width little-endian (LE) format. | `signed 8-bit integer 69` / `unsigned 16-bit integer 42` / `unsigned 32-bit integer 16777215` | `0x45` / `0x2a00` / `0xffffff00` | -| Options | One or zero values of a particular type. | `Some` / `None` | `0x01` followed by the encoded value / `0x00` | -| Results | Results are commonly used enumerations which indicate whether certain operations were successful or unsuccessful. | `Ok(42)` / `Err(false)` | `0x002a` / `0x0100` | -| Strings | Strings are Vectors of bytes (Vec) containing a valid UTF8 sequence. | | | -| Structs | For structures, the values are named, but that is irrelevant for the encoding (names are ignored - only order matters). | `SortedVecAsc::from([3, 5, 2, 8])` | `[3, 2, 5, 8] ` | -| Tuples | A fixed-size series of values, each with a possibly different but predetermined and fixed type. This is simply the concatenation of each encoded value. | Tuple of compact unsigned integer and boolean: `(3, false)` | `0x0c00` | -| Vectors (lists, series, sets) | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. | Vector of unsigned `16`-bit integers: `[4, 8, 15, 16, 23, 42]` | `0x18040008000f00100017002a00` | - -## Encode and Decode Rust Trait Implementations - -Here's how the `Encode` and `Decode` traits are implemented: - - -```rust -use parity_scale_codec::{Encode, Decode}; - -[derive(Debug, PartialEq, Encode, Decode)] -enum EnumType { - #[codec(index = 15)] - A, - B(u32, u64), - C { - a: u32, - b: u64, - }, -} - -let a = EnumType::A; -let b = EnumType::B(1, 2); -let c = EnumType::C { a: 1, b: 2 }; - -a.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x0f"); -}); - -b.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -c.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -let mut da: &[u8] = b"\x0f"; -assert_eq!(EnumType::decode(&mut da).ok(), Some(a)); - -let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut db).ok(), Some(b)); - -let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut dc).ok(), Some(c)); - -let mut dz: &[u8] = &[0]; -assert_eq!(EnumType::decode(&mut dz).ok(), None); -``` - -## SCALE Codec Libraries - -Several SCALE codec implementations are available in various languages. Here's a list of them: - -- **AssemblyScript**: [`LimeChain/as-scale-codec`](https://github.com/LimeChain/as-scale-codec){target=\_blank} -- **C**: [`MatthewDarnell/cScale`](https://github.com/MatthewDarnell/cScale){target=\_blank} -- **C++**: [`qdrvm/scale-codec-cpp`](https://github.com/qdrvm/scale-codec-cpp){target=\_blank} -- **JavaScript**: [`polkadot-js/api`](https://github.com/polkadot-js/api){target=\_blank} -- **Dart**: [`leonardocustodio/polkadart`](https://github.com/leonardocustodio/polkadart){target=\_blank} -- **Haskell**: [`airalab/hs-web3`](https://github.com/airalab/hs-web3/tree/master/packages/scale){target=\_blank} -- **Golang**: [`itering/scale.go`](https://github.com/itering/scale.go){target=\_blank} -- **Java**: [`splix/polkaj`](https://github.com/splix/polkaj){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **Ruby**: [` wuminzhe/scale_rb`](https://github.com/wuminzhe/scale_rb){target=\_blank} -- **TypeScript**: [`parity-scale-codec-ts`](https://github.com/tjjfvi/subshape){target=\_blank}, [`scale-ts`](https://github.com/unstoppablejs/unstoppablejs/tree/main/packages/scale-ts#scale-ts){target=\_blank}, [`soramitsu/scale-codec-js-library`](https://github.com/soramitsu/scale-codec-js-library){target=\_blank}, [`subsquid/scale-codec`](https://github.com/subsquid/squid-sdk/tree/master/substrate/scale-codec){target=\_blank} - - ---- - -Page Title: Deploy an ERC-20 to Polkadot Hub - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/ -- Summary: Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Hardhat. - -# Deploy an ERC-20 to Polkadot Hub - -## Introduction - -[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. - -This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Hardhat](https://hardhat.org/){target=\_blank}, an Ethereum development environment. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. - -## Prerequisites - -Before starting, make sure you have: - -- Basic understanding of Solidity programming and fungible tokens. -- Node.js v22.13.1 or later. -- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. - -## Set Up Your Project - -This tutorial uses a [Hardhat ERC-20 template](https://github.com/polkadot-developers/revm-hardhat-examples/tree/master/erc20-hardhat){target=\_blank} that contains all the necessary files. To get started, take the following steps: - -1. Clone the GitHub repository locally: - - ```bash - git clone https://github.com/polkadot-developers/revm-hardhat-examples/ - cd revm-hardhat-examples/erc20-hardhat - ``` - -2. Install the dependencies: - - ```bash - npm i - ``` - -This will fetch all the necessary packages to help you deploy an ERC-20 with Hardhat to Polkadot. - -## Configure Hardhat - -Once you've [setup your project](#set-up-your-project), you can configure the `hardhat.config.ts` to your needs. This tutorial has the file prepared to deploy to the Polkadot TestNet. - -To store and use private keys or network URLs, you can use Hardhat's configuration variables. This can be set via tasks in the **vars** scope. For example, to store the private key to deploy to the Polkadot TestNet, run the following command: - -```bash -npx hardhat vars set TESTNET_PRIVATE_KEY -``` - -The command will initiate a wizard in which you'll have to enter the value to be stored: - -
    - npx hardhat vars set TESTNET_PRIVATE_KEY - ✔ Enter value: · ••••••••• - The configuration variable has been stored in /Users/albertoviera/Library/Preferences/hardhat-nodejs/vars.json -
    - -??? warning "Key Encryption" - This solution just prevents variables to be included in the code repository. You should find a solution that encrypts private keys and access them securely. - -You can now use the account related to this private key by importing it into the Hardhat configuration file: - -```ts title="hardhat.config.ts" hl_lines="1 17" - -const config: HardhatUserConfig = { - solidity: { - version: "0.8.28", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - networks: { - polkadotTestnet: { - url: vars.get("TESTNET_URL", "http://127.0.0.1:8545"), - accounts: vars.has("TESTNET_PRIVATE_KEY") ? [vars.get("TESTNET_PRIVATE_KEY")] : [], - }, - }, - mocha: { - timeout: 40000, - }, -}; - -export default config; -``` - -## Compile your Contract - -Once you've configured Hardhat, you can compile the contract. - -In this tutorial, a simple ERC-20 is provided. Therefore, to compile the contract you can run the following command: - -```bash -npx hardhat compile -``` - -If everything compiles successfully, you should see the following output: - -
    - npx hardhat compile - Generating typings for: 23 artifacts in dir: typechain-types for target: ethers-v6 - Successfully generated 62 typings! - Compiled 21 Solidity files successfully (evm target: paris). -
    - -## Test your Contract - -Hardhat has a native feature to test contracts. You can run tests against the local Hardhat development node, but it could have some technical differences to Polkadot. Therefore, in this tutorial, you'll be testing against the Polkadot TestNet - -This example has a predefined test file located in [`test/Token.test.js`](https://github.com/polkadot-developers/revm-hardhat-examples/blob/master/erc20-hardhat/test/MyToken.test.ts){target=\_blank}, that runs the following tests: - -1. The token was deployed by verifying its **name** and **symbol**. -2. The token has the right owner configured. -3. The token has an initial supply of zero. -4. The owner can mint tokens. -5. The total supply is increased after a mint. -6. Perform multiple mints to different addresses and checks the balance of each address and the new total supply. - -To run the test, you can execute the following command: - -```bash -npx hardhat test --network polkadotTestnet -``` - -If tests are successful, you should see the following logs: - -
    - npx hardhat test --network polkadotTestnet - -   MyToken -     Deployment -       ✔ Should have correct name and symbol -       ✔ Should set the right owner -       ✔ Should have zero initial supply -     Minting -       ✔ Should allow owner to mint tokens -       ✔ Should increase total supply on mint -     Multiple mints -       ✔ Should correctly track balance after multiple mints - -   6 passing (369ms) -
    - -## Deploy your Contract - -With the Hardhat configuration file ready, the private key stored as a variable under **vars**, and the contract compiled, you can proceed to deploy the contract to a given network. In this tutorial, you are deploying it to the Polkadot TestNet. - -To deploy the contract, run the following command: - -```bash -npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet -``` - -You'll need to confirm the target network (by chain ID): - -
    - npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet - ✔ Confirm deploy to network polkadotTestnet (420420420)? … yes -   - Hardhat Ignition 🚀 -   - Deploying [ TokenModule ] -   - Batch #1 - Executed TokenModule#MyToken -   - Batch #2 - Executed TokenModule#MyToken.mint -   - [ TokenModule ] successfully deployed 🚀 -   - Deployed Addresses -   - TokenModule#MyToken - 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3 -
    - -And that is it! You've successfully deployed an ERC-20 token contract to the Polkadot TestNet using Hardhat. - -## Where to Go Next - -
    - -- Guide __Deploy an NFT with Remix__ - - --- - - Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) - -
    - - ---- - -Page Title: Deploy an ERC-20 to Polkadot Hub - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/ -- Summary: Deploy an ERC-20 token contract on Polkadot Hub. This guide covers contract creation, compilation, deployment, and interaction via the Remix IDE. - -# Deploy an ERC-20 to Polkadot Hub - -## Introduction - -[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. - -This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Remix IDE](https://remix.ethereum.org/){target=\_blank}, a web-based development tool. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. - -## Prerequisites - -Before starting, make sure you have: - -- Basic understanding of Solidity programming and fungible tokens. -- An EVM-compatible wallet [connected to Polkadot Hub](/smart-contracts/integrations/wallets){target=\_blank}. This example utilizes [MetaMask](https://metamask.io/){target=\_blank}. -- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. - -## Create Your Contract - -To create the ERC-20 contract, you can follow the steps below: - -1. Navigate to the [Polkadot Remix IDE](https://remix.polkadot.io){target=\_blank}. -2. Click in the **Create new file** button under the **contracts** folder, and name your contract as `MyToken.sol`. - - ![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-1.webp) - -3. Now, paste the following ERC-20 contract code into the editor: - - ```solidity title="MyToken.sol" - // SPDX-License-Identifier: MIT - // Compatible with OpenZeppelin Contracts ^5.4.0 - pragma solidity ^0.8.27; - - import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; - import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; - - contract MyToken is ERC20, Ownable, ERC20Permit { - constructor(address initialOwner) - ERC20("MyToken", "MTK") - Ownable(initialOwner) - ERC20Permit("MyToken") - {} - - function mint(address to, uint256 amount) public onlyOwner { - _mint(to, amount); - } - } - ``` - - The key components of the code above are: - - - Contract imports: - - - **[`ERC20.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/ERC20.sol){target=\_blank}**: The base contract for fungible tokens, implementing core functionality like transfers, approvals, and balance tracking. - - **[`ERC20Permit.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/extensions/ERC20Permit.sol){target=\_blank}**: [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612){target=\_blank} extension for ERC-20 that adds the [permit function](https://docs.openzeppelin.com/contracts/5.x/api/token/erc20#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-){target=\_blank}, allowing approvals via off-chain signatures (no on-chain tx from the holder). Manages nonces and EIP-712 domain separator and updates allowances when a valid signature is presented. - - **[`Ownable.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/access/Ownable.sol){target=\_blank}**: Provides basic authorization control, ensuring only the contract owner can mint new tokens. - - - Constructor parameters: - - - **`initialOwner`**: Sets the address that will have administrative rights over the contract. - - **`"MyToken"`**: The full name of your token. - - **`"MTK"`**: The symbol representing your token in wallets and exchanges. - - - Key functions: - - - **`mint(address to, uint256 amount)`**: Allows the contract owner to create new tokens for any address. The amount should include 18 decimals (e.g., 1 token = 1000000000000000000). - - Inherited [Standard ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/){target=\_blank} functions: - - **`transfer(address recipient, uint256 amount)`**: Sends a specified amount of tokens to another address. - - **`approve(address spender, uint256 amount)`**: Grants permission for another address to spend a specific number of tokens on behalf of the token owner. - - **`transferFrom(address sender, address recipient, uint256 amount)`**: Transfers tokens from one address to another, if previously approved. - - **`balanceOf(address account)`**: Returns the token balance of a specific address. - - **`allowance(address owner, address spender)`**: Checks how many tokens an address is allowed to spend on behalf of another address. - - !!! tip - Use the [OpenZeppelin Contracts Wizard](https://wizard.openzeppelin.com/){target=\_blank} to generate customized smart contracts quickly. Simply configure your contract, copy the generated code, and paste it into the Remix IDE for deployment. Below is an example of an ERC-20 token contract created with it: - - ![Screenshot of the OpenZeppelin Contracts Wizard showing an ERC-20 contract configuration.](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-2.webp) - - -## Compile - -The compilation transforms your Solidity source code into bytecode that can be deployed on the blockchain. During this process, the compiler checks your contract for syntax errors, ensures type safety, and generates the machine-readable instructions needed for blockchain execution. - -To compile your contract, ensure you have it opened in the Remix IDE Editor, and follow the instructions below: - -1. Select the **Solidity Compiler** plugin from the left panel. -2. Click the **Compile MyToken.sol** button. -3. If the compilation succeeded, you'll see a green checkmark indicating success in the **Solidity Compiler** icon. - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-3.gif) - -## Deploy - -Deployment is the process of publishing your compiled smart contract to the blockchain, making it permanently available for interaction. During deployment, you'll create a new instance of your contract on the blockchain, which involves: - -1. Select the **Deploy & Run Transactions** plugin from the left panel. -2. Configure the deployment settings: - 1. From the **ENVIRONMENT** dropdown, select **Injected Provider - MetaMask** (check the [Deploying Contracts](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} section of the Remix IDE guide for more details). - 2. (Optional) From the **ACCOUNT** dropdown, select the acccount you want to use for the deploy. - -3. Configure the contract parameters: - 1. Enter the address that will own the deployed token contract. - 2. Click the **Deploy** button to initiate the deployment. - -4. **MetaMask will pop up**: Review the transaction details. Click **Confirm** to deploy your contract. -5. If the deployment process succeeded, you will see the transaction details in the terminal, including the contract address and deployment transaction hash. - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-4.gif) - -## Interact with Your Contract - -Once deployed, you can interact with your contract through Remix. Find your contract under **Deployed/Unpinned Contracts**, and click it to expand the available methods. In this example, you'll mint some tokens to a given address: - -1. Expand the **mint** function: - 1. Enter the recipient address and the amount (remember to add 18 zeros for 1 whole token). - 2. Click **transact**. - -2. Click **Approve** to confirm the transaction in the MetaMask popup. - -3. If the transaction succeeds, you will see a green check mark in the terminal. - -4. You can also call the **balanceOf** function by passing the address of the **mint** call to confirm the new balance. - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-5.gif) - - -Other standard functions you can use: - -- **`transfer(address to, uint256 amount)`**: Send tokens to another address. -- **`approve(address spender, uint256 amount)`**: Allow another address to spend your tokens. - -Feel free to explore and interact with the contract's other functions using the same approach: select the method, provide any required parameters, and confirm the transaction in MetaMask when needed. - -## Where to Go Next - -
    - -- Guide __Deploy an NFT with Remix__ - - --- - - Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) - -
    - - ---- - -Page Title: Deploy an NFT to Polkadot Hub with Foundry - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/.foundry/ -- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Foundry, a Rust toolkit with high-performance compilation. - -# Deploy an NFT with Foundry - -## Introduction - -Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. - -This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. It showcases a secure approach using [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and the [Foundry](https://getfoundry.sh/){target=\_blank} toolchain. Foundry, a fast, Rust-written toolkit, ensures high-performance compilation and is fully compatible with the Hub’s EVM environment via standard Solidity compilation. - -## Prerequisites - -- Basic understanding of Solidity programming and NFT standards. -- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank}. -- A wallet with a private key for signing transactions. - -## Set Up Your Project - -To get started, take the following steps: - -1. Install Foundry: - - ```bash - curl -L https://foundry.paradigm.xyz | bash - foundryup - ``` - -2. Initialize your project: - - ```bash - forge init foundry-nft-deployment - cd foundry-nft-deployment - ``` - -3. Install OpenZeppelin contracts: - - ```bash - forge install OpenZeppelin/openzeppelin-contracts - ``` - -## Configure Foundry - -Edit `foundry.toml`: - -```toml title="foundry.toml" -[profile.default] -src = "src" -out = "out" -libs = ["lib"] -remappings = ['@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/'] - -[rpc_endpoints] -polkadot_hub_testnet = "https://testnet-passet-hub-eth-rpc.polkadot.io" -``` - -## Create Your Contract - -Create `src/MyNFT.sol`: - -```solidity title="src/MyNFT.sol" -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract MyNFT is ERC721, Ownable { - uint256 private _nextTokenId; - - constructor(address initialOwner) - ERC721("MyToken", "MTK") - Ownable(initialOwner) - {} - - function safeMint(address to) public onlyOwner { - uint256 tokenId = _nextTokenId++; - _safeMint(to, tokenId); - } -} -``` - -## Compile - -```bash -forge build -``` - -Verify the compilation by inspecting the bytecode: - -```bash -forge inspect MyNFT bytecode -``` - -## Deploy - -Deploy to Polkadot Hub TestNet: - -```bash -forge create MyNFT \ - --rpc-url polkadot_hub_testnet \ - --private-key YOUR_PRIVATE_KEY \ - --constructor-args YOUR_OWNER_ADDRESS \ - --broadcast -``` - -Replace `YOUR_PRIVATE_KEY` with your private key and `YOUR_OWNER_ADDRESS` with the address that will own the NFT contract. - -## Where to Go Next - -
    - -- Guide __Verify Your Contract__ - - --- - - Now that you've deployed an NFT contract, learn how to verify it with Foundry. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/foundry/verify-a-contract/) - -- Guide __Deploy an ERC-20__ - - --- - - Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Foundry. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/foundry/) - -
    - - ---- - -Page Title: Deploy an NFT to Polkadot Hub with Hardhat - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/ -- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub with Hardhat, a comprehenive development environment with built-in deployment capabilities. - -# Deploy an NFT with Hardhat - -## Introduction - -Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. - -This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Hardhat](https://hardhat.org/docs/getting-started){target=\_blank}, a comprehensive development environment with built-in testing, debugging, and deployment capabilities. Hardhat uses standard Solidity compilation to generate EVM bytecode, making it fully compatible with Polkadot Hub's EVM environment. - -## Prerequisites - -- Basic understanding of Solidity programming and NFT standards. -- Node.js v22.13.1 or later. -- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -- A wallet with a private key for signing transactions. - -## Set Up Your Project - -Take the following steps to get started: - -1. Initialize your Hardhat project: - - ```bash - mkdir hardhat-nft-deployment - cd hardhat-nft-deployment - npx hardhat --init - ``` - -2. Install OpenZeppelin contracts: - - ```bash - npm install @openzeppelin/contracts - ``` - -## Configure Hardhat - -Edit `hardhat.config.ts`: - -```typescript title="hardhat.config.ts" -import type { HardhatUserConfig } from 'hardhat/config'; - -import hardhatToolboxViemPlugin from '@nomicfoundation/hardhat-toolbox-viem'; -import { configVariable } from 'hardhat/config'; - -const config: HardhatUserConfig = { - plugins: [hardhatToolboxViemPlugin], - solidity: { - profiles: { - default: { - version: '0.8.28', - }, - production: { - version: '0.8.28', - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - }, - }, - networks: { - hardhatMainnet: { - type: 'edr-simulated', - chainType: 'l1', - }, - hardhatOp: { - type: 'edr-simulated', - chainType: 'op', - }, - sepolia: { - type: 'http', - chainType: 'l1', - url: configVariable('SEPOLIA_RPC_URL'), - accounts: [configVariable('SEPOLIA_PRIVATE_KEY')], - }, - polkadotHubTestnet: { - type: 'http', - url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - accounts: [configVariable('PRIVATE_KEY')], - }, - }, -}; - -export default config; -``` - -!!! tip - Learn how to use Hardhat's [Config Variables](https://hardhat.org/docs/learn-more/configuration-variables){target=\_blank} to handle your private keys in a secure way. - -## Create Your Contract - -Create `contracts/MyNFT.sol`: - -```solidity title="contracts/MyNFT.sol" -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract MyNFT is ERC721, Ownable { - uint256 private _nextTokenId; - - constructor(address initialOwner) - ERC721("MyToken", "MTK") - Ownable(initialOwner) - {} - - function safeMint(address to) public onlyOwner { - uint256 tokenId = _nextTokenId++; - _safeMint(to, tokenId); - } -} -``` - -## Compile - -```bash -npx hardhat compile -``` - -## Set Up Deployment - -Create a deployment module in `ignition/modules/MyNFT.ts`: - -```typescript title="ignition/modules/MyNFT.ts" -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; - -export default buildModule('MyNFTModule', (m) => { - const initialOwner = m.getParameter('initialOwner', 'INSERT_OWNER_ADDRESS'); - const myNFT = m.contract('MyNFT', [initialOwner]); - return { myNFT }; -}); -``` - -Replace `INSERT_OWNER_ADDRESS` with your desired owner address. - -## Deploy - -Deploy to Polkadot Hub TestNet: - -```bash -npx hardhat ignition deploy ignition/modules/MyNFT.ts --network polkadotHubTestnet -``` - -## Where to Go Next - -
    - -- Guide __Verify Your Contract__ - - --- - - Now that you've deployed an NFT contract, learn how to verify it with Hardhat. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/verify-a-contract/) - - -- Guide __Deploy an ERC-20__ - - --- - - Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Hardhat. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/hardhat/) - -
    - - ---- - -Page Title: Deploy an NFT to Polkadot Hub with Remix - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/ -- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Remix, a browser-based IDE for quick prototyping and learning. - -# Deploy an NFT with Remix - -## Introduction - -Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. - -This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Remix](https://remix.ethereum.org/){target=\_blank}, a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development. - -## Prerequisites - -- Basic understanding of Solidity programming and NFT standards. -- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank} -- A wallet with a private key for signing transactions. - -## Access Remix - -Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. - -The interface will load with a default workspace containing sample contracts. In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. - -## Create Your Contract - -1. Create a new file `contracts/MyNFT.sol`. -2. Paste the following code: - - ```solidity title="contracts/MyNFT.sol" - // SPDX-License-Identifier: MIT - pragma solidity ^0.8.20; - - import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; - import "@openzeppelin/contracts/access/Ownable.sol"; - - contract MyNFT is ERC721, Ownable { - uint256 private _nextTokenId; - - constructor(address initialOwner) - ERC721("MyToken", "MTK") - Ownable(initialOwner) - {} - - function safeMint(address to) public onlyOwner { - uint256 tokenId = _nextTokenId++; - _safeMint(to, tokenId); - } - } - ``` - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-01.webp) - -## Compile - -1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). -2. Click **Compile MyNFT.sol** or press `Ctrl+S`. - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-02.webp) - -Compilation errors and warnings appear in the terminal panel at the bottom of the screen. - -## Deploy - -1. Navigate to the **Deploy & Run Transactions** tab. -2. Click the **Environment** dropdown, select **Browser Extension**, and click on **Injected Provider - MetaMask**. - - ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-03.webp) - -3. In the deploy section, enter the initial owner address in the constructor parameter field. -4. Click **Deploy**. - - ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-04.webp) - -5. Approve the transaction in your MetaMask wallet. - -Your deployed contract will appear in the **Deployed Contracts** section, ready for interaction. - -## Where to Go Next - -
    - -- Guide __Verify Your Contract__ - - --- - - Now that you've deployed an NFT contract, learn how to verify it with Remix. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/verify-a-contract/) - -- Guide __Deploy an ERC-20__ - - --- - - Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Remix. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) - -
    - - ---- - -Page Title: Dual Virtual Machine Stack - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/ -- Summary: Compare Polkadot’s dual smart contract VMs—REVM for EVM compatibility and PolkaVM for RISC-V performance, flexibility, and efficiency. - -# Dual Virtual Machine Stack - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot's smart contract platform supports two distinct virtual machine (VM) architectures, providing developers with flexibility in selecting the optimal execution backend for their specific needs. This approach strikes a balance between immediate Ethereum compatibility and long-term innovation, enabling developers to deploy either unmodified (Ethereum Virtual Machine) EVM contracts using Rust Ethereum Virtual Machine (REVM) or optimize for higher performance using PolkaVM (PVM). - -Both VM options share common infrastructure, including RPC interfaces, tooling support, and precompiles. The following sections compare architectures and guide you in selecting the best VM for your project's needs. - -## Migrate from EVM - -The [REVM backend](https://github.com/bluealloy/revm){target=\_blank} integrates a complete Rust implementation of the EVM, enabling Solidity contracts to run unchanged on Polkadot's smart contract platform. - -REVM allows developers to use their existing Ethereum tooling and infrastructure to build on Polkadot. Choose REVM to: - -- Migrate existing Ethereum contracts without modifications. -- Retain exact EVM behavior for audit tools. -- Use developer tools that rely upon inspecting EVM bytecode. -- Prioritize rapid deployment over optimization. -- Work with established Ethereum infrastructure and tooling to build on Polkadot. - -REVM enables Ethereum developers to seamlessly migrate to Polkadot, achieving performance and fee improvements without modifying their existing contracts or developer tooling stack. - -## Upgrade to PolkaVM - -[**PolkaVM**](https://github.com/paritytech/polkavm){target=\_blank} is a custom virtual machine optimized for performance with [RISC-V-based](https://en.wikipedia.org/wiki/RISC-V){target=\_blank} architecture, supporting Solidity and additional high-performance languages. It serves as the core execution environment, integrated directly within the runtime. Choose the PolkaVM for: - -- An efficient interpreter for immediate code execution. -- A planned [Just In Time (JIT)](https://en.wikipedia.org/wiki/Just-in-time_compilation){target=\_blank} compiler for optimized performance. -- Dual-mode execution capability, allowing selection of the most appropriate backend for specific workloads. -- Optimized performance for short-running contract calls through the interpreter. - -The interpreter remains particularly beneficial for contracts with minimal code execution, as it enables immediate code execution through lazy interpretation. - -## Architecture - -The following key components of PolkaVM work together to enable Ethereum compatibility on Polkadot-based chains. - -### Revive Pallet - -[**`pallet_revive`**](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/index.html){target=\_blank} is a runtime module that executes smart contracts by adding extrinsics, runtime APIs, and logic to convert Ethereum-style transactions into formats compatible with Polkadot SDK-based blockchains. It processes Ethereum-style transactions through the following workflow: - -```mermaid -sequenceDiagram - participant User as User/dApp - participant Proxy as Ethereum JSON RPC Proxy - participant Chain as Blockchain Node - participant Pallet as pallet_revive - - User->>Proxy: Submit Ethereum Transaction - Proxy->>Chain: Repackage as Polkadot Compatible Transaction - Chain->>Pallet: Process Transaction - Pallet->>Pallet: Decode Ethereum Transaction - Pallet->>Pallet: Execute Contract via PolkaVM - Pallet->>Chain: Return Results - Chain->>Proxy: Forward Results - Proxy->>User: Return Ethereum-compatible Response -``` - -This proxy-based approach eliminates the need for node binary modifications, maintaining compatibility across different client implementations. Preserving the original Ethereum transaction payload simplifies the adaptation of existing tools, which can continue processing familiar transaction formats. - -### PolkaVM Design Fundamentals - -PolkaVM differs from the EVM in two key ways that make it faster, more hardware-efficient, and easier to extend: - -- **Register-based design**: Instead of a stack machine, PolkaVM uses a RISC-V–style register model. This design: - - - Uses a fixed set of registers to pass arguments, not an infinite stack. - - Maps cleanly to real hardware like x86-64. - - Simplifies compilation and boosts runtime efficiency. - - Enables tighter control over register allocation and performance tuning. - -- **64-bit word size**: PolkaVM runs on a native 64-bit word size, aligning directly with modern CPUs. This design: - - - Executes arithmetic operations with direct hardware support. - - Maintains compatibility with Solidity’s 256-bit types via YUL translation. - - Accelerates computation-heavy workloads through native word alignment. - - Integrates easily with low-level, performance-focused components. - -## Where To Go Next - -
    - -- Learn __Contract Deployment__ - - --- - - Learn how REVM and PVM compare for compiling and deploying smart contracts. - - [:octicons-arrow-right-24: Reference](/smart-contracts/for-eth-devs/contract-deployment/) - -
    - - ---- - -Page Title: Elastic Scaling - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-elastic-scaling.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/consensus/elastic-scaling/ -- Summary: Learn how elastic scaling in Polkadot boosts parachain throughput, reduces latency, and supports dynamic, cost-efficient resource allocation. - -# Elastic Scaling - -## Introduction - -Polkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains. - -Elastic scaling enhances this architecture by allowing parachains to utilize multiple computational cores simultaneously, breaking the previous 1:1 relationship between parachain and relay chain blocks. - -This technical advancement enables parachains to process multiple blocks within a single relay chain block, significantly increasing throughput capabilities. By leveraging [Agile Coretime](/polkadot-protocol/architecture/polkadot-chain/agile-coretime){target=\_blank}, parachains can dynamically adjust their processing capacity based on demand, creating an efficient and responsive infrastructure for high-throughput applications. - -## How Elastic Scaling Works - -Elastic scaling enables parachains to process multiple blocks in parallel by utilizing additional cores on the relay chain. This section provides a technical analysis of the performance advantages and details of the implementation. - -Consider a parachain that needs to process four consecutive parablocks. With traditional single-core allocation, the validation process follows a strictly sequential pattern. Each parablock undergoes a two-phase process on the relay chain: - -1. **Backing phase**: Validators create and distribute validity statements. -2. **Inclusion phase**: The parablock is included in the relay chain after availability verification. - -Throughout the following diagrams, specific notation is used to represent different components of the system: - -- **R1, R2, ...**: Relay chain blocks (produced at ~6-second intervals). -- **P1, P2, ...**: Parachain blocks that need validation and inclusion. -- **C1, C2, ...**: Cores on the relay chain. - -In the single-core scenario (assuming a 6-second relay chain block time), processing four parablocks requires approximately 30 seconds: - -```mermaid -sequenceDiagram - participant R1 as R1 - participant R2 as R2 - participant R3 as R3 - participant R4 as R4 - participant R5 as R5 - - Note over R1,R5: Single Core Scenario - - rect rgb(200, 220, 240) - Note right of R1: Core C1 - R1->>R1: Back P1 - R2->>R2: Include P1 - R2->>R2: Back P2 - R3->>R3: Include P2 - R3->>R3: Back P3 - R4->>R4: Include P3 - R4->>R4: Back P4 - R5->>R5: Include P4 - end -``` - -With elastic scaling utilizing two cores simultaneously, the same four parablocks can be processed in approximately 18 seconds: - -```mermaid -sequenceDiagram - participant R1 as R1 - participant R2 as R2 - participant R3 as R3 - participant R4 as R4 - participant R5 as R5 - - Note over R1,R3: Multi-Core Scenario - - rect rgb(200, 220, 240) - Note right of R1: Core C1 - R1->>R1: Back P1 - R2->>R2: Include P1 - R2->>R2: Back P2 - R3->>R3: Include P2 - end - - rect rgb(220, 200, 240) - Note right of R1: Core C2 - R1->>R1: Back P3 - R2->>R2: Include P3 - R2->>R2: Back P4 - R3->>R3: Include P4 - end -``` - -To help interpret the sequence diagrams above, note the following key elements: - -- The horizontal axis represents time progression through relay chain blocks (R1-R5). -- Each colored rectangle shows processing on a specific core (C1 or C2). -- In the single-core scenario, all blocks must be processed sequentially on one core. -- In the multi-core scenario, blocks are processed in parallel across multiple cores, reducing total time. - -The relay chain processes these multiple parablocks as independent validation units during the backing, availability, and approval phases. However, during inclusion, it verifies that their state roots align properly to maintain chain consistency. - -From an implementation perspective: - -- **Parachain side**: Collators must increase their block production rate to utilize multiple cores fully. -- **Validation process**: Each core operates independently, but with coordinated state verification. -- **Resource management**: Cores are dynamically allocated based on parachain requirements. -- **State consistency**: While backed and processed in parallel, the parablocks maintain sequential state transitions. - -## Benefits of Elastic Scaling - -- **Increased throughput**: Multiple concurrent cores enable parachains to process transactions at multiples of their previous capacity. By allowing multiple parachain blocks to be validated within each relay chain block cycle, applications can achieve significantly higher transaction volumes. - -- **Lower latency**: Transaction finality improves substantially with multi-core processing. Parachains currently achieve 2-second latency with three cores, with projected improvements to 500ms using 12 cores, enabling near-real-time application responsiveness. - -- **Resource efficiency**: Applications acquire computational resources precisely matched to their needs, eliminating wasteful over-provisioning. Coretime can be purchased at granular intervals (blocks, hours, days), creating cost-effective operations, particularly for applications with variable transaction patterns. - -- **Scalable growth**: New applications can launch with minimal initial resource commitment and scale dynamically as adoption increases. This eliminates the traditional paradox of either over-allocating resources (increasing costs) or under-allocating (degrading performance) during growth phases. - -- **Workload distribution**: Parachains intelligently distribute workloads across cores during peak demand periods and release resources when traffic subsides. Paired with secondary coretime markets, this ensures maximum resource utilization across the entire network ecosystem. - -- **Reliable performance**: End-users experience reliable application performance regardless of network congestion levels. Applications maintain responsiveness even during traffic spikes, eliminating performance degradation that commonly impacts blockchain applications during high-demand periods. - -## Use Cases - -Elastic scaling enables applications to dynamically adjust their resource consumption based on real-time demand. This is especially valuable for decentralized applications where usage patterns can be highly variable. The following examples illustrate common scenarios where elastic scaling delivers significant performance and cost-efficiency benefits. - -### Handling Sudden Traffic Spikes - -Many decentralized applications experience unpredictable, high-volume traffic bursts, especially in gaming, DeFi protocols, NFT auctions, messaging platforms, and social media. Elastic scaling allows these systems to acquire additional coretime during peak usage and release it during quieter periods, ensuring responsiveness without incurring constant high infrastructure costs. - -### Supporting Early-Stage Growth - -Startups and new projects often begin with uncertain or volatile demand. With elastic scaling, teams can launch with minimal compute resources (e.g., a single core) and gradually scale as adoption increases. This prevents overprovisioning and enables cost-efficient growth until the application is ready for more permanent or horizontal scaling. - -### Scaling Massive IoT Networks - -Internet of Things (IoT) applications often involve processing data from millions of devices in real time. Elastic scaling supports this need by enabling high-throughput transaction processing as demand fluctuates. Combined with Polkadot’s shared security model, it provides a reliable and privacy-preserving foundation for large-scale IoT deployments. - -### Powering Real-Time, Low-Latency Systems - -Applications like payment processors, trading platforms, gaming engines, or real-time data feeds require fast, consistent performance. Elastic scaling can reduce execution latency during demand spikes, helping ensure low-latency, reliable service even under heavy load. - - ---- - -Page Title: Get Started with Parachain Development - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/get-started/ -- Summary: Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. - -# Get Started - -The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. - -## Quick Start Guides - -Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. - -| Tutorial | Tools | Description | -| :--------------------------------------------------------------------------------------------: | :----------------------------: | :---------------------------------------------------------------------: | -| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | Learn how to set up and run the Polkadot SDK Parachain Template locally | -| [Launch a Local Parachain](/parachains/testing/run-a-parachain-network/) | Zombienet, Chopsticks | Set up a local development environment for testing | -| [Connect to Polkadot](/chain-interactions/query-on-chain-data/query-sdks/) | Polkadot.js, Substrate Connect | Connect your application to Polkadot networks | -| [Fork an Existing Parachain](/parachains/testing/fork-a-parachain/) | Chopsticks | Create a local fork of a live parachain for testing | - -## Launch a Simple Parachain - -Learn the fundamentals of launching and deploying a parachain to the Polkadot network. - -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------: | -| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | -| [Deploy to Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/) | Step-by-step tutorial to deploying your parachain to Polkadot | -| [Obtain Coretime](/parachains/launch-a-parachain/obtain-coretime/) | Learn how to acquire blockspace using Polkadot's coretime model (RegionX) | - -## Customize Your Runtime - -Build custom functionality for your parachain by composing and creating pallets. - -| Tutorial | Description | -| :-------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------: | -| [Add Existing Pallets to the Runtime](/parachains/customize-runtime/add-existing-pallets/) | Integrate pre-built pallets from the FRAME ecosystem | -| [Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/) | Configure and use multiple instances of the same pallet | -| [Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/) | Enable smart contract capabilities using Contracts or EVM pallets | - -### Pallet Development - -Deep dive into creating and managing custom pallets for your parachain. - -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------: | -| [Create a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/) | Build a pallet from scratch with custom logic | -| [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/) | Set up a mock runtime environment for testing | -| [Pallet Unit Testing](/parachains/customize-runtime/pallet-development/pallet-testing/) | Write comprehensive tests for your pallet logic | -| [Add Your Custom Pallet to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/) | Integrate your custom pallet into your parachain runtime | -| [Benchmark the Custom Pallet](/parachains/customize-runtime/pallet-development/benchmark-pallet/) | Measure and optimize pallet performance with benchmarking | - -## Testing - -Test your parachain in various environments before production deployment. - -| Tutorial | Description | -| :---------------------------------------------------------------------: | :-----------------------------------------------------: | -| [Fork a Parachain](/parachains/testing/fork-a-parachain/) | Use Chopsticks to create a local fork for testing | -| [Run a Parachain Network](/parachains/testing/run-a-parachain-network/) | Launch a complete parachain test network with Zombienet | - -## Runtime Upgrades and Maintenance - -Manage your parachain's lifecycle with forkless upgrades and maintenance operations. - -| Tutorial | Description | -| :-----------------------------------------------------------------------: | :--------------------------------------------------: | -| [Runtime Upgrades](/parachains/runtime-maintenance/runtime-upgrades/) | Perform forkless runtime upgrades via governance | -| [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/) | Safely migrate storage when updating runtime logic | -| [Unlock Parachains](/parachains/runtime-maintenance/unlock-parachains/) | Understand parachain lifecycle and unlock mechanisms | - -## Interoperability - -Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). - -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: | -| [Open HRMP Channels Between Parachains](/parachains/interoperability/channels-between-parachains/) | Establish communication channels with other parachains | -| [Open HRMP Channels with System Parachains](/parachains/interoperability/channels-with-system-parachains/) | Connect with Asset Hub and other system parachains | - -## Integrations - -Integrate your parachain with essential ecosystem tools and services. - -| Tutorial | Description | -| :--------------------------------------------: | :----------------------------------------------------: | -| [Wallets](/parachains/integrations/wallets/) | Integrate wallet support for user interactions | -| [Indexers](/parachains/integrations/indexers/) | Set up indexing solutions for querying blockchain data | -| [Oracles](/parachains/integrations/oracles/) | Connect your parachain to off-chain data sources | - -## Additional Resources - -- [Polkadot SDK Documentation](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/index.html) -- [Polkadot Wiki - Parachains](https://wiki.polkadot.network/docs/learn-parachains/) - - ---- - -Page Title: Get Started with Smart Contracts - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/get-started/ -- Summary: Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. - -# Get Started - -This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need. - -## Quick Starts - -Kick off development fast with curated links for connecting, funding, exploring, and deploying your first contract. - -| Quick Start | Tools | Description | -|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:| -| [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer | -| [Get Test Tokens](/smart-contracts/faucets/){target=\_blank} | - | Request test funds to deploy and interact with contracts | -| [Explore Transactions](/smart-contracts/explorers/){target=\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state | -| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} | Remix | One‑click browser deployment to Polkadot Hub | -| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\_blank} | Foundry | Scripted deployments and testing from the CLI | -| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} | Hardhat | Project scaffolding, testing, and deployments | - -## Build and Test Locally - -Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. - -| Build and Test Locally | Tools | Description | -|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:| -| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\_blank} | Polkadot SDK node | Spin up a local node for iterative development | -| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts | -| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\_blank} | Remix | Publish verified source on explorers | -| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\_blank} | Foundry | Install toolchain and configure networks | -| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\_blank} | Foundry | Write and run Solidity tests locally | -| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\_blank} | Foundry | Verify deployed bytecode and metadata | -| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} | Hardhat | Initialize a project and configure networks | -| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} | Hardhat | Unit test contracts and run scripts | -| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\_blank} | Hardhat | Verify deployments on explorers | - -## Ethereum Developer Resources - -Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. - -| Ethereum Developer Guides | Description | -|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:| -| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts | -| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\_blank} | Transaction types, fees, and multi‑dimensional metering | -| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} | Gas vs. weight, proof size, and storage deposits | -| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\_blank} | Deployment patterns and best practices on Polkadot Hub | -| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank} | Supported Ethereum JSON‑RPC methods and examples | -| [Migration](/smart-contracts/for-eth-devs/migration/){target=\_blank} | Port existing apps and tooling to Polkadot Hub | -| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} | Overview of EVM and native execution on the Hub | - -## Cookbook: Hands‑on Tutorials - -Follow step‑by‑step guides that walk through common tasks and complete dApp examples. - -| Tutorial | Tools | Description | -|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:| -| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} | Remix | Minimal deployment walkthrough | -| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token | -| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection | -| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\_blank} | Hardhat | Full dApp project: compile, test, deploy | -| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\_blank} | Multiple | End‑to‑end dApp patterns and practices | - -## Libraries - -Choose the client libraries that fit your stack for connecting wallets and calling contracts. - -| Library | Description | -|:------------------------------------------------------------------:|:-------------------------------------------------------:| -| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank} | Connect, sign, and interact with contracts using Ethers | -| [viem](/smart-contracts/libraries/viem/){target=\_blank} | Type‑safe EVM interactions and utilities | -| [Wagmi](/smart-contracts/libraries/wagmi/){target=\_blank} | React hooks for wallet connections and contract calls | -| [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank} | Web3 provider and contract APIs | -| [Web3.py](/smart-contracts/libraries/web3-py/){target=\_blank} | Python toolkit for on‑chain interactions and scripts | - -## Integrations - -Integrate essential services like wallets, indexers, and oracles to round out your dApp. - -| Integration | Description | -|:-------------------------------------------------------------------:|:-----------------------------------------:| -| [Wallets](/smart-contracts/integrations/wallets/){target=\_blank} | Supported wallets and configuration notes | -| [Indexers](/smart-contracts/integrations/indexers/){target=\_blank} | Index and query blockchain data | -| [Oracles](/smart-contracts/integrations/oracles/){target=\_blank} | Bring external data on‑chain | - -## Precompiles - -Discover precompiled system contracts available on the Hub and how to use them. - -| Topic | Description | -|:------------------------------------------------------------------------:|:---------------------------------------------------:| -| [Overview of Precompiles](/smart-contracts/precompiles/){target=\_blank} | What precompiles are available on the Hub | -| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\_blank} | EVM precompiles and interfaces | -| [Staking](/smart-contracts/precompiles/staking/){target=\_blank} | Interact with staking functionality via precompiles | -| [XCM](/smart-contracts/precompiles/xcm/){target=\_blank} | Cross‑chain messaging helpers for contracts | - -From here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\_blank} or reach out in the community channels. - - ---- - -Page Title: Glossary - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md -- Canonical (HTML): https://docs.polkadot.com/reference/glossary/ -- Summary: Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. - -# Glossary - -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. - -Additional glossaries from around the ecosystem you might find helpful: - -- [Polkadot Wiki Glossary](https://wiki.polkadot.com/general/glossary){target=\_blank} -- [Polkadot SDK Glossary](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/glossary/index.html){target=\_blank} - -## Authority - -The role in a blockchain that can participate in consensus mechanisms. - -- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final. -- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author). - -Authority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol. - -## Authority Round (Aura) - -A deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol. - -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. - -## Blind Assignment of Blockchain Extension (BABE) - -A [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block. - -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. - -## Block Author - -The node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_. - -## Byzantine Fault Tolerance (BFT) - -The ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack. - -### Byzantine Failure - -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. - -### Practical Byzantine Fault Tolerance (pBFT) - -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. - -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. - -### Preimage - -A preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\_blank}, the output, the hash, cannot be used to reveal the input, the preimage. - -## Call - -In the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object. - -## Chain Specification - -A chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains. - -## Collator - -An [author](#block-author) of a [parachain](#parachain) network. -They aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus). - -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. - -## Collective - -Most often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network. - -## Consensus - -Consensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship. - -See also [hybrid consensus](#hybrid-consensus). - -## Consensus Algorithm - -Ensures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft). - -Consensus algorithms are generally concerned with ensuring two properties: - -- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. -- **Liveness**: Indicating the ability of the chain to keep progressing. - -## Consensus Engine - -The node subsystem responsible for consensus tasks. - -For detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} blog series. - -See also [hybrid consensus](#hybrid-consensus). - -## Coretime - -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. - -On-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety. - -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank}. - -## Development Phrase - -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. - -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: - -``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk -``` - -Many tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`. - -## Digest - -An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: - -- [Light clients](#light-client) for chain synchronization. -- Consensus engines for block verification. -- The runtime itself, in the case of pre-runtime digests. - -## Dispatchable - -Function objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations. - -## Events - -A means of recording that some particular [state](#state) transition happened. - -In the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization. - -## Executor - -A means of executing a function call in a given [runtime](#runtime) with a set of dependencies. -There are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_. - -- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes. - -- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain. - -## Existential Deposit - -The minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. - -If an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\_blank} to drop its references to that account. - -If the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\_blank}. - -## Extrinsic - -A general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder. - -It is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). - -For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. - -## Fork Choice Rule/Strategy - -A fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\_blank}, in which the chain with the most blocks is selected. - -## FRAME (Framework for Runtime Aggregation of Modularized Entities) - -Enables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes. - -[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank} - -## Full Node - -A node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization. - -## Genesis Configuration - -A mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file. - -## GRANDPA - -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. - -The [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\_blank}. - -## Header - -A structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization. - -## Hybrid Consensus - -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. - -Hybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa). - -## Inherent Transactions - -A special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block. - -Only the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified. - -## JSON-RPC - -A stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON. - -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. - -## Keystore - -A subsystem for managing keys for the purpose of producing new blocks. - -## Kusama - -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. - -Kusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\_blank} network and is referred to as [Polkadot's "wild cousin."](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\_blank}. - -As a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation. - -## libp2p - -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). - -Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. - -## Light Client - -A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. - -A light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\_blank} server, enabling blockchain users to interact with the network. - -## Metadata - -Data that provides information about one or more aspects of a system. -The metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system. - -## Nominated Proof of Stake (NPoS) - -A method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes. - -## Oracle - -An entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services. - -## Origin - -A [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\_blank}. - -## Pallet - -A module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime). -Pallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item). - -## Parachain - -A parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_. -You can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\_blank}. - -## Paseo - -Paseo TestNet provisions testing on Polkadot's "production" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing. - -## Polkadot - -The [Polkadot network](https://polkadot.com/){target=\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain). - -## Polkadot Cloud - -Polkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance. - -## Polkadot Hub - -Polkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3. - -## PolkaVM - -PolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution. - -## Relay Chain - -Relay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another. - -## Rococo - -A [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead. - -## Runtime - -The runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function. - -## Slot - -A fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block. - -## Sovereign Account - -The unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem. - -The sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier. - -## SS58 Address Format - -A public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain - -The [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks - -## State Transition Function (STF) - -The logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime). - -## Storage Item - -[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime). -Learn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\_blank} reference document in the Polkadot SDK. - -## Substrate - -A flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\_blank}. - -## Transaction - -An [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}. - -## Transaction Era - -A definable period expressed as a range of block numbers during which a transaction can be included in a block. -Transaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero. - -## Trie (Patricia Merkle Tree) - -A data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set. - -In Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays. - -## Validator - -A validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance. - -## WebAssembly (Wasm) - -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. - -[Wasm](https://webassembly.org/){target=\_blank} can be compiled from many languages, including -the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state. - -## Weight - -A convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block. -Polkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware. - -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: - -- Block construction -- Network propagation -- Import and verification - -By defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements. - -## Westend - -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. - - ---- - -Page Title: Install Polkadot SDK - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md -- Canonical (HTML): https://docs.polkadot.com/parachains/install-polkadot-sdk/ -- Summary: Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. - -# Install Polkadot SDK - -This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts: - -- **Installing dependencies**: Setting up Rust, required system packages, and development tools. -- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. - -Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. - -## Install Dependencies: macOS - -You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. - -### Before You Begin {: #before-you-begin-mac-os } - -Before you install Rust and set up your development environment on macOS, verify that your computer meets the following basic requirements: - -- Operating system version is 10.7 Lion or later. -- Processor speed of at least 2 GHz. Note that 3 GHz is recommended. -- Memory of at least 8 GB RAM. Note that 16 GB is recommended. -- Storage of at least 10 GB of available space. -- Broadband Internet connection. - -### Install Homebrew - -In most cases, you should use Homebrew to install and manage packages on macOS computers. If you don't already have Homebrew installed on your local computer, you should download and install it before continuing. - -To install Homebrew: - -1. Open the Terminal application. -2. Download and install Homebrew by running the following command: - - ```bash - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - ``` - -3. Verify Homebrew has been successfully installed by running the following command: - - ```bash - brew --version - ``` - - The command displays output similar to the following: - -
    - brew --version - Homebrew 4.3.15 -
    - -### Support for Apple Silicon - -Protobuf must be installed before the build process can begin. To install it, run the following command: - -```bash -brew install protobuf -``` - -### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } - -Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `openssl`. - -To install `openssl` and the Rust toolchain on macOS: - -1. Open the Terminal application. -2. Ensure you have an updated version of Homebrew by running the following command: - - ```bash - brew update - ``` - -3. Install the `openssl` package by running the following command: - - ```bash - brew install openssl - ``` - -4. Download the `rustup` installation program and use it to install Rust by running the following command: - - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -5. Follow the prompts displayed to proceed with a default installation. -6. Update your current shell to include Cargo by running the following command: - - ```bash - source ~/.cargo/env - ``` - -7. Configure the Rust toolchain to default to the latest stable version by running the following commands: - - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` - -8. Install `cmake` using the following command: - - ```bash - brew install cmake - ``` - -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - -## Install Dependencies: Linux - -Rust supports most Linux distributions. Depending on the specific distribution and version of the operating system you use, you might need to add some software dependencies to your environment. In general, your development environment should include a linker or a C-compatible compiler, such as `clang`, and an appropriate integrated development environment (IDE). - -### Before You Begin {: #before-you-begin-linux } - -Check the documentation for your operating system for information about the installed packages and how to download and install any additional packages you might need. For example, if you use Ubuntu, you can use the Ubuntu Advanced Packaging Tool (`apt`) to install the `build-essential` package: - -```bash -sudo apt install build-essential -``` - -At a minimum, you need the following packages before you install Rust: - -```text -clang curl git make -``` - -Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `libssl-dev` or `openssl-devel`. - -### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } - -To install the Rust toolchain on Linux: - -1. Open a terminal shell. -2. Check the packages installed on the local computer by running the appropriate package management command for your Linux distribution. -3. Add any package dependencies you are missing to your local development environment by running the appropriate package management command for your Linux distribution: - - === "Ubuntu" - - ```bash - sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler - ``` - - === "Debian" - - ```sh - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` - - === "Arch" - - ```sh - pacman -Syu --needed --noconfirm curl git clang make protobuf - ``` - - === "Fedora" - - ```sh - sudo dnf update - sudo dnf install clang curl git openssl-devel make protobuf-compiler - ``` - - === "OpenSUSE" - - ```sh - sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf - ``` - - Remember that different distributions might use different package managers and bundle packages in different ways. For example, depending on your installation selections, Ubuntu Desktop and Ubuntu Server might have different packages and different requirements. However, the packages listed in the command-line examples are applicable to many common Linux distributions, including Debian, Linux Mint, MX Linux, and Elementary OS. - -4. Download the `rustup` installation program and use it to install Rust by running the following command: - - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -5. Follow the prompts displayed to proceed with a default installation. -6. Update your current shell to include Cargo by running the following command: - - ```bash - source $HOME/.cargo/env - ``` - -7. Verify your installation by running the following command: - - ```bash - rustc --version - ``` - -8. Configure the Rust toolchain to default to the latest stable version by running the following commands: - - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` - -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - -## Install Dependencies: Windows (WSL) - -In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. - -However, suppose your local computer uses Microsoft Windows instead of a UNIX-based operating system. In that case, you can configure it with additional software to make it a suitable development environment for building Substrate-based blockchains. To prepare a development environment on a Microsoft Windows computer, you can use Windows Subsystem for Linux (WSL) to emulate a UNIX operating environment. - -### Before You Begin {: #before-you-begin-windows-wls } - -Before installing on Microsoft Windows, verify the following basic requirements: - -- You have a computer running a supported Microsoft Windows operating system: - - **For Windows desktop**: You must be running Microsoft Windows 10, version 2004 or later, or Microsoft Windows 11 to install WSL. - - **For Windows server**: You must be running Microsoft Windows Server 2019, or later, to install WSL on a server operating system. -- You have a good internet connection and access to a shell terminal on your local computer. - -### Set Up Windows Subsystem for Linux - -WSL enables you to emulate a Linux environment on a computer that uses the Windows operating system. The primary advantage of this approach for Substrate development is that you can use all of the code and command-line examples as described in the Substrate documentation. For example, you can run common commands—such as `ls` and `ps`—unmodified. By using WSL, you can avoid configuring a virtual machine image or a dual-boot operating system. - -To prepare a development environment using WSL: - -1. Check your Windows version and build number to see if WSL is enabled by default. - - If you have Microsoft Windows 10, version 2004 (Build 19041 and higher), or Microsoft Windows 11, WSL is available by default and you can continue to the next step. - - If you have an older version of Microsoft Windows installed, see the [WSL manual installation steps for older versions](https://learn.microsoft.com/en-us/windows/wsl/install-manual){target=\_blank}. If you are installing on an older version of Microsoft Windows, you can download and install WLS 2 if your computer has Windows 10, version 1903 or higher. - -2. Select **Windows PowerShell** or **Command Prompt** from the **Start** menu, right-click, then **Run as administrator**. - -3. In the PowerShell or Command Prompt terminal, run the following command: - - ```bash - wsl --install - ``` - - This command enables the required WSL 2 components that are part of the Windows operating system, downloads the latest Linux kernel, and installs the Ubuntu Linux distribution by default. - - If you want to review the other Linux distributions available, run the following command: - - ```bash - wsl --list --online - ``` - -4. After the distribution is downloaded, close the terminal. - -5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. - - Restarting the computer is required to start the installation of the Linux distribution. It can take a few minutes for the installation to complete after you restart. - - For more information about setting up WSL as a development environment, see the [Set up a WSL development environment](https://learn.microsoft.com/en-us/windows/wsl/setup/environment){target=\_blank} docs. - -### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } - -To install the Rust toolchain on WSL: - -1. Click the **Start** menu, then select **Ubuntu**. -2. Type a UNIX user name to create a user account. -3. Type a password for your UNIX user, then retype the password to confirm it. -4. Download the latest updates for the Ubuntu distribution using the Ubuntu Advanced Packaging Tool (`apt`) by running the following command: - - ```bash - sudo apt update - ``` - -5. Add the required packages for the Ubuntu distribution by running the following command: - - ```bash - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` - -6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: - - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -7. Follow the prompts displayed to proceed with a default installation. - -8. Update your current shell to include Cargo by running the following command: - - ```bash - source ~/.cargo/env - ``` - -9. Verify your installation by running the following command: - - ```bash - rustc --version - ``` - -10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: - - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` - -11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - -## Build the Polkadot SDK - -After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. - -### Clone the Polkadot SDK - -1. Clone the Polkadot SDK repository: - - ```bash - git clone https://github.com/paritytech/polkadot-sdk.git - ``` - -2. Navigate into the project directory: - - ```bash - cd polkadot-sdk - ``` - -### Compile the Polkadot SDK - -Compile the entire Polkadot SDK repository to ensure your environment is properly configured: - -```bash -cargo build --release --locked -``` - -!!!note - This initial compilation will take significant time, depending on your machine specifications. It compiles all components of the Polkadot SDK to verify your toolchain is correctly configured. - -### Verify the Build - -Once the build completes successfully, verify the installation by checking the compiled binaries: - -```bash -ls target/release -``` - -You should see several binaries, including: - -- `polkadot`: The Polkadot relay chain node. -- `polkadot-parachain`: The parachain collator node. -- `polkadot-omni-node`:The omni node for running parachains. -- `substrate-node`: The kitchensink node with many pre-configured pallets. - -Verify the Polkadot binary works by checking its version: - -```bash -./target/release/polkadot --version -``` - -This should display version information similar to: - -```bash -polkadot 1.16.0-1234abcd567 -``` - -If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! - -## Optional: Run the Kitchensink Node - -The Polkadot SDK includes a feature-rich node called "kitchensink" located at `substrate/bin/node`. This node comes pre-configured with many pallets and features from the Polkadot SDK, making it an excellent reference for exploring capabilities and understanding how different components work together. - -!!!note - If you've already compiled the Polkadot SDK in the previous step, the `substrate-node` binary is already built and ready to use. You can skip directly to running the node. - -### Run the Kitchensink Node in Development Mode - -From the `polkadot-sdk` root directory, start the kitchensink node in development mode: - -```bash -./target/release/substrate-node --dev -``` - -The `--dev` flag enables development mode, which: - -- Runs a single-node development chain. -- Produces and finalizes blocks automatically. -- Uses pre-configured development accounts (Alice, Bob, etc.). -- Deletes all data when stopped, ensuring a clean state on restart. - - -You should see log output indicating the node is running and producing blocks, with increasing block numbers after `finalized`. - -### Interact with the Kitchensink Node - -The kitchensink node is accessible at `ws://localhost:9944`. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your browser to explore its features and connect to the local node. - -1. Click the network icon in the top left corner. -2. Scroll to **Development** and select **Local Node**. -3. Click **Switch** to connect to your local node. - -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) - -Once connected, the interface updates its color scheme to indicate a successful connection to the local node. - -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) - -You can now explore the various pallets and features included in the kitchensink node, making it a valuable reference as you develop your own blockchain applications. - -To stop the node, press `Control-C` in the terminal. - -## Where to Go Next - -
    - -- __Get Started with Parachain Development__ - - --- - - Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. - - [:octicons-arrow-right-24: Get Started](/parachains/get-started/) - -
    - - ---- - -Page Title: Interoperability - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/interoperability/ -- Summary: Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. - -# Interoperability - -## Introduction - -Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions. - -Polkadot’s design ensures that blockchains can transcend their individual limitations by working together as part of a unified system. This cooperative architecture is what sets Polkadot apart in the blockchain landscape. - -## Why Interoperability Matters - -The blockchain ecosystem is inherently fragmented. Different blockchains excel in specialized domains such as finance, gaming, or supply chain management, but these chains function in isolation without interoperability. This lack of connectivity stifles the broader utility of blockchain technology. - -Interoperability solves this problem by enabling blockchains to: - -- **Collaborate across networks**: Chains can interact to share assets, functionality, and data, creating synergies that amplify their individual strengths. -- **Achieve greater scalability**: Specialized chains can offload tasks to others, optimizing performance and resource utilization. -- **Expand use-case potential**: Cross-chain applications can leverage features from multiple blockchains, unlocking novel user experiences and solutions. - -In the Polkadot ecosystem, interoperability transforms a collection of isolated chains into a cohesive, efficient network, pushing the boundaries of what blockchains can achieve together. - -## Key Mechanisms for Interoperability - -At the core of Polkadot's cross-chain collaboration are foundational technologies designed to break down barriers between networks. These mechanisms empower blockchains to communicate, share resources, and operate as a cohesive ecosystem. - -### Cross-Consensus Messaging (XCM): The Backbone of Communication - -Polkadot's Cross-Consensus Messaging (XCM) is the standard framework for interaction between parachains, relay chains, and, eventually, external blockchains. XCM provides a trustless, secure messaging format for exchanging assets, sharing data, and executing cross-chain operations. - -Through XCM, decentralized applications can: - -- Transfer tokens and other assets across chains. -- Coordinate complex workflows that span multiple blockchains. -- Enable seamless user experiences where underlying blockchain differences are invisible. -- XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem. - -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. - -### Bridges: Connecting External Networks - -While XCM enables interoperability within the Polkadot ecosystem, bridges extend this functionality to external blockchains such as Ethereum and Bitcoin. By connecting these networks, bridges allow Polkadot-based chains to access external liquidity, additional functionalities, and broader user bases. - -With bridges, developers and users gain the ability to: - -- Integrate external assets into Polkadot-based applications. -- Combine the strengths of Polkadot’s scalability with the liquidity of other networks. -- Facilitate accurate multi-chain applications that transcend ecosystem boundaries. - -For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. - -## The Polkadot Advantage - -Polkadot was purpose-built for interoperability. Unlike networks that add interoperability as an afterthought, Polkadot integrates it as a fundamental design principle. This approach offers several distinct advantages: - -- **Developer empowerment**: Polkadot’s interoperability tools allow developers to build applications that leverage multiple chains’ capabilities without added complexity. -- **Enhanced ecosystem collaboration**: Chains in Polkadot can focus on their unique strengths while contributing to the ecosystem’s overall growth. -- **Future-proofing blockchain**: By enabling seamless communication, Polkadot ensures its ecosystem can adapt to evolving demands and technologies. - -## Looking Ahead - -Polkadot’s vision of interoperability extends beyond technical functionality, representing a shift towards a more collaborative blockchain landscape. By enabling chains to work together, Polkadot fosters innovation, efficiency, and accessibility, paving the way for a decentralized future where blockchains are not isolated competitors but interconnected collaborators. - - ---- - -Page Title: Introduction to XCM - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ -- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. - -# Introduction to XCM - -## Introduction - -Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. - -With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. - -## Messaging Format - -XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. - -XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. - -## The Four Principles of XCM - -XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: - -- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. -- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. -- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. -- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. - -These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. - -## The XCM Tech Stack - -![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) - -The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. - -## Core Functionalities of XCM - -XCM enhances cross-consensus communication by introducing several powerful features: - -- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. -- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. -- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. - -The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. - -## XCM Example - -The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). - -```rust -let message = Xcm(vec![ - WithdrawAsset((Here, amount).into()), - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } -]); -``` - -The message consists of three instructions described as follows: - -- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. - - ```rust - WithdrawAsset((Here, amount).into()), - ``` - - - **`Here`**: The native parachain token. - - **`amount`**: The number of tokens that are transferred. - - The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. - -- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. - - ```rust - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - ``` - - - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. - - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. - -- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. - - ```rust - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } - ``` - - - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. - -This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - -## Overview - -XCM revolutionizes cross-chain communication by enabling use cases such as: - -- Token transfers between blockchains. -- Asset locking for cross-chain smart contract interactions. -- Remote execution of functions on other blockchains. - -These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - - ---- - -Page Title: JSON-RPC APIs - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ -- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. - -# JSON-RPC APIs - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. - -This guide uses the Polkadot Hub TestNet endpoint: - -```text -https://testnet-passet-hub-eth-rpc.polkadot.io -``` - -## Available Methods - -### eth_accounts - -Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_accounts" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_accounts", - "params":[], - "id":1 -}' -``` - ---- - -### eth_blockNumber - -Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_blockNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_blockNumber", - "params":[], - "id":1 -}' -``` - ---- - -### eth_call - -Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction call object. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_call" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_call", - "params":[{ - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_CALL" - }, "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_chainId - -Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_chainId" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_chainId", - "params":[], - "id":1 -}' -``` - ---- - -### eth_estimateGas - -Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction call object. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_estimateGas" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_estimateGas", - "params":[{ - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_FUNCTION_CALL" - }], - "id":1 -}' -``` - -Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. - ---- - -### eth_gasPrice - -Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_gasPrice" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_gasPrice", - "params":[], - "id":1 -}' -``` - ---- - -### eth_getBalance - -Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_getBalance" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBalance", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getBlockByHash - -Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. - -**Parameters**: - -- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. - -**Example**: - -```bash title="eth_getBlockByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockByHash", - "params":["INSERT_BLOCK_HASH", INSERT_BOOLEAN], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values. - ---- - -### eth_getBlockByNumber - -Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. - -**Parameters**: - -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. - -**Example**: - -```bash title="eth_getBlockByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockByNumber", - "params":["INSERT_BLOCK_VALUE", INSERT_BOOLEAN], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values. - ---- - -### eth_getBlockTransactionCountByNumber - -Returns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\_blank}. - -**Parameters**: - -- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_getBlockTransactionCountByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockTransactionCountByNumber", - "params":["INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getBlockTransactionCountByHash - -Returns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}. - -**Parameters**: - -- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getBlockTransactionCountByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockTransactionCountByHash", - "params":["INSERT_BLOCK_HASH"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. - ---- - -### eth_getCode - -Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - -**Example**: - -```bash title="eth_getCode" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getCode", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getLogs - -Returns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}. - -**Parameters**: - -- **`filter` ++"object"++**: The filter object. - - **`fromBlock` ++"string"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - - **`toBlock` ++"string"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - - **`address` ++"string" or "array of strings"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`topics` ++"array of strings"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string or an array of such strings (meaning OR). - - **`blockhash` ++"string"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getLogs" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getLogs", - "params":[{ - "fromBlock": "latest", - "toBlock": "latest" - }], - "id":1 -}' -``` - ---- - -### eth_getStorageAt - -Returns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`storageKey` ++"string"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - -**Example**: - -```bash title="eth_getStorageAt" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getStorageAt", - "params":["INSERT_ADDRESS", "INSERT_STORAGE_KEY", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getTransactionCount - -Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - -**Example**: - -```bash title="eth_getTransactionCount" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionCount", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getTransactionByHash - -Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. - -**Parameters**: - -- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByHash", - "params":["INSERT_TRANSACTION_HASH"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. - ---- - -### eth_getTransactionByBlockNumberAndIndex - -Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. - -**Parameters**: - -- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionByBlockNumberAndIndex" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByBlockNumberAndIndex", - "params":["INSERT_BLOCK_VALUE", "INSERT_TRANSACTION_INDEX"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. - ---- - -### eth_getTransactionByBlockHashAndIndex - -Returns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}. - -**Parameters**: - -- **`blockHash` ++"string"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionByBlockHashAndIndex" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByBlockHashAndIndex", - "params":["INSERT_BLOCK_HASH", "INSERT_TRANSACTION_INDEX"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. - ---- - -### eth_getTransactionReceipt - -Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. - -**Parameters**: - -- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionReceipt" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionReceipt", - "params":["INSERT_TRANSACTION_HASH"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. - ---- - -### eth_maxPriorityFeePerGas - -Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_maxPriorityFeePerGas" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_maxPriorityFeePerGas", - "params":[], - "id":1 -}' -``` - ---- - -### eth_sendRawTransaction - -Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. - -**Parameters**: - -- **`callData` ++"string"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_sendRawTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_sendRawTransaction", - "params":["INSERT_CALL_DATA"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_CALL_DATA` with the proper values. - ---- - -### eth_sendTransaction - -Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction object. - - **`from` ++"string"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`to` ++"string"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`data` ++"string"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`nonce` ++"string"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_sendTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_sendTransaction", - "params":[{ - "from": "INSERT_SENDER_ADDRESS", - "to": "INSERT_RECIPIENT_ADDRESS", - "gas": "INSERT_GAS_LIMIT", - "gasPrice": "INSERT_GAS_PRICE", - "value": "INSERT_VALUE", - "input": "INSERT_INPUT_DATA", - "nonce": "INSERT_NONCE" - }], - "id":1 -}' -``` - -Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values. - ---- - -### eth_syncing - -Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_syncing" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_syncing", - "params":[], - "id":1 -}' -``` - ---- - -### net_listening - -Returns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="net_listening" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_listening", - "params":[], - "id":1 -}' -``` - ---- - -### net_peerCount - -Returns the number of peers currently connected to the client. - -**Parameters**: - -None. - -**Example**: - -```bash title="net_peerCount" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_peerCount", - "params":[], - "id":1 -}' -``` - ---- - -### net_version - -Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="net_version" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_version", - "params":[], - "id":1 -}' -``` - ---- - -### system_health - -Returns information about the health of the system. - -**Parameters**: - -None. - -**Example**: - -```bash title="system_health" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"system_health", - "params":[], - "id":1 -}' -``` - ---- - -### web3_clientVersion - -Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="web3_clientVersion" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"web3_clientVersion", - "params":[], - "id":1 -}' -``` - ---- - -### debug_traceBlockByNumber - -Traces a block's execution by its number and returns a detailed execution trace for each transaction. - -**Parameters**: - -- **`blockValue` ++"string"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`options` ++"object"++**: (Optional) An object containing tracer options. - - **`tracer` ++"string"++**: The name of the tracer to use (e.g., `"callTracer"`, `"opTracer"`). - - Other tracer-specific options may be supported. - -**Example**: - -```bash title="debug_traceBlockByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceBlockByNumber", - "params":["INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], - "id":1 -}' -``` - -Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. - ---- - -### debug_traceTransaction - -Traces the execution of a single transaction by its hash and returns a detailed execution trace. - -**Parameters**: - -- **`transactionHash` ++"string"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). - -**Example**: - -```bash title="debug_traceTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceTransaction", - "params":["INSERT_TRANSACTION_HASH", {"tracer": "callTracer"}], - "id":1 -}' -``` - -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. - ---- - -### debug_traceCall - -Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction call object, similar to `eth_call` parameters. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). - -**Example**: - -```bash title="debug_traceCall" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceCall", - "params":[{ - "from": "INSERT_SENDER_ADDRESS", - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_CALL" - }, "INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], - "id":1 -}' -``` - -Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value. - ---- - -## Response Format - -All responses follow the standard JSON-RPC 2.0 format: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": ... // The return value varies by method -} -``` - -## Error Handling - -If an error occurs, the response will include an error object: - -```json -{ - "jsonrpc": "2.0", - "id": 1, - "error": { - "code": -32000, - "message": "Error message here" - } -} -``` - - ---- - -Page Title: Networks - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/networks/ -- Summary: Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. - -# Networks - -## Introduction - -The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's various networks and explain how they fit into the development workflow. - -## Network Overview - -Polkadot's development process is structured to ensure new features and upgrades are rigorously tested before being deployed on live production networks. The progression follows a well-defined path, starting from local environments and advancing through TestNets, ultimately reaching the Polkadot MainNet. The diagram below outlines the typical progression of the Polkadot development cycle: - -``` mermaid -flowchart LR - id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] - id1[Local] --> id3[Paseo] --> id5[Polkadot] +```mermaid +sequenceDiagram + participant User as User/dApp + participant Proxy as Ethereum JSON RPC Proxy + participant Chain as Blockchain Node + participant Pallet as pallet_revive + + User->>Proxy: Submit Ethereum Transaction + Proxy->>Chain: Repackage as Polkadot Compatible Transaction + Chain->>Pallet: Process Transaction + Pallet->>Pallet: Decode Ethereum Transaction + Pallet->>Pallet: Execute Contract via PolkaVM + Pallet->>Chain: Return Results + Chain->>Proxy: Forward Results + Proxy->>User: Return Ethereum-compatible Response ``` -This flow ensures developers can thoroughly test and iterate without risking real tokens or affecting production networks. Testing tools like [Chopsticks](#chopsticks) and various TestNets make it easier to experiment safely before releasing to production. - -A typical journey through the Polkadot core protocol development process might look like this: - -1. **Local development node**: Development starts in a local environment, where developers can create, test, and iterate on upgrades or new features using a local development node. This stage allows rapid experimentation in an isolated setup without any external dependencies. - -2. **Westend**: After testing locally, upgrades are deployed to [Westend](#westend), Polkadot's primary TestNet. Westend simulates real-world conditions without using real tokens, making it the ideal place for rigorous feature testing before moving on to production networks. - -3. **Kusama**: Once features have passed extensive testing on Westend, they move to Kusama, Polkadot's experimental and fast-moving "canary" network. Kusama operates as a high-fidelity testing ground with actual economic incentives, giving developers insights into how their features will perform in a real-world environment. - -4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network. - - In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. - -5. **Paseo**: For parachain and dApp developers, Paseo serves as a community-run TestNet that mirrors Polkadot's runtime. Like Westend for core protocol development, Paseo provides a testing ground for parachain development without affecting live networks. - -!!!note - The Rococo TestNet deprecation date was October 14, 2024. Teams should use Westend for Polkadot protocol and feature testing and Paseo for chain development-related testing. - -## Polkadot Development Networks - -Development and testing are crucial to building robust dApps and parachains and performing network upgrades within the Polkadot ecosystem. To achieve this, developers can leverage various networks and tools that provide a risk-free environment for experimentation and validation before deploying features to live networks. These networks help avoid the costs and risks associated with real tokens, enabling testing for functionalities like governance, cross-chain messaging, and runtime upgrades. - -## Kusama Network - -Kusama is the experimental version of Polkadot, designed for developers who want to move quickly and test their applications in a real-world environment with economic incentives. Kusama serves as a production-grade testing ground where developers can deploy features and upgrades with the pressure of game theory and economics in mind. It mirrors Polkadot but operates as a more flexible space for innovation. - -The native token for Kusama is KSM. For more information about KSM, visit the [Native Assets](https://wiki.polkadot.com/kusama/kusama-getting-started/){target=\_blank} page. - -## Test Networks - -The following test networks provide controlled environments for testing upgrades and new features. TestNet tokens are available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}. - -### Westend - -Westend is Polkadot's primary permanent TestNet. Unlike temporary test networks, Westend is not reset to the genesis block, making it an ongoing environment for testing Polkadot core features. Managed by Parity Technologies, Westend ensures that developers can test features in a real-world simulation without using actual tokens. - -The native token for Westend is WND. More details about WND can be found on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_2){target=\_blank} page. - -### Paseo - -[Paseo](https://github.com/paseo-network){target=\_blank} is a community-managed TestNet designed for parachain and dApp developers. It mirrors Polkadot's runtime and is maintained by Polkadot community members. Paseo provides a dedicated space for parachain developers to test their applications in a Polkadot-like environment without the risks associated with live networks. +This proxy-based approach eliminates the need for node binary modifications, maintaining compatibility across different client implementations. Preserving the original Ethereum transaction payload simplifies the adaptation of existing tools, which can continue processing familiar transaction formats. -The native token for Paseo is PAS. Additional information on PAS is available on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_1){target=\_blank} page. +### PolkaVM Design Fundamentals -## Local Test Networks +PolkaVM differs from the EVM in two key ways that make it faster, more hardware-efficient, and easier to extend: -Local test networks are an essential part of the development cycle for blockchain developers using the Polkadot SDK. They allow for fast, iterative testing in controlled, private environments without connecting to public TestNets. Developers can quickly spin up local instances to experiment, debug, and validate their code before deploying to larger TestNets like Westend or Paseo. Two key tools for local network testing are Zombienet and Chopsticks. +- **Register-based design**: Instead of a stack machine, PolkaVM uses a RISC-V–style register model. This design: -### Zombienet + - Uses a fixed set of registers to pass arguments, not an infinite stack. + - Maps cleanly to real hardware like x86-64. + - Simplifies compilation and boosts runtime efficiency. + - Enables tighter control over register allocation and performance tuning. -[Zombienet](https://github.com/paritytech/zombienet){target=\_blank} is a flexible testing framework for Polkadot SDK-based blockchains. It enables developers to create and manage ephemeral, short-lived networks. This feature makes Zombienet particularly useful for quick iterations, as it allows you to run multiple local networks concurrently, mimicking different runtime conditions. Whether you're developing a parachain or testing your custom blockchain logic, Zombienet gives you the tools to automate local testing. +- **64-bit word size**: PolkaVM runs on a native 64-bit word size, aligning directly with modern CPUs. This design: -Key features of Zombienet include: + - Executes arithmetic operations with direct hardware support. + - Maintains compatibility with Solidity’s 256-bit types via YUL translation. + - Accelerates computation-heavy workloads through native word alignment. + - Integrates easily with low-level, performance-focused components. -- Creating dynamic, local networks with different configurations. -- Running parachains and relay chains in a simulated environment. -- Efficient testing of network components like cross-chain messaging and governance. +## Where To Go Next -Zombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets. +
    -### Chopsticks +- Learn __Contract Deployment__ -[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\_blank} is a tool designed to create forks of Polkadot SDK-based blockchains, allowing developers to interact with network forks as part of their testing process. This capability makes Chopsticks a powerful option for testing upgrades, runtime changes, or cross-chain applications in a forked network environment. + --- -Key features of Chopsticks include: + Learn how REVM and PVM compare for compiling and deploying smart contracts. -- Forking live Polkadot SDK-based blockchains for isolated testing. -- Simulating cross-chain messages in a private, controlled setup. -- Debugging network behavior by interacting with the fork in real-time. + [:octicons-arrow-right-24: Reference](/smart-contracts/for-eth-devs/contract-deployment/) -Chopsticks provides a controlled environment for developers to safely explore the effects of runtime changes. It ensures that network behavior is tested and verified before upgrades are deployed to live networks. +
    --- -Page Title: Node and Runtime - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/node-and-runtime/ -- Summary: Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. - -# Node and Runtime - -## Introduction - -Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network. - -Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. - -If the system were a monolithic protocol, any modification would require updating the entire system. Instead, Polkadot achieves true upgradeability by defining an immutable meta-protocol (the client) and a protocol (the runtime) that can be upgraded independently. - -This separation gives the [Polkadot Relay Chain](/polkadot-protocol/architecture/polkadot-chain){target=\_blank} and all connected [parachains](/polkadot-protocol/architecture/parachains){target=\_blank} an evolutionary advantage over other blockchain platforms. - -## Architectural Principles - -The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: - -- Client (Meta-protocol): - - Handles the foundational infrastructure of the blockchain. - - Manages runtime execution, networking, consensus, and other off-chain components. - - Provides an immutable base layer that ensures network stability. - - Upgradable only through hard forks. - -- Runtime (Protocol): - - Defines the blockchain's state transition logic. - - Determines the specific rules and behaviors of the blockchain. - - Compiled to WebAssembly (Wasm) for platform-independent execution. - - Capable of being upgraded without network-wide forking. - -### Advantages of this Architecture - -- **Forkless upgrades**: Runtime can be updated without disrupting the entire network. -- **Modularity**: Clear separation allows independent development of client and runtime. -- **Flexibility**: Enables rapid iteration and evolution of blockchain logic. -- **Performance**: WebAssembly compilation provides efficient, cross-platform execution. - -## Node (Client) - -The node, also known as the client, is the core component responsible for executing the Wasm runtime and orchestrating various essential blockchain components. It ensures the correct execution of the state transition function and manages multiple critical subsystems, including: +Page Title: Get Started with Parachain Development -- **Wasm execution**: Runs the blockchain runtime, which defines the state transition rules. -- **Database management**: Stores blockchain data. -- **Networking**: Facilitates peer-to-peer communication, block propagation, and transaction gossiping. -- **Transaction pool (Mempool)**: Manages pending transactions before they are included in a block. -- **Consensus mechanism**: Ensures agreement on the blockchain state across nodes. -- **RPC services**: Provides external interfaces for applications and users to interact with the node. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/get-started/ +- Summary: Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. -## Runtime +# Get Started -The runtime is more than just a set of rules. It's the fundamental logic engine that defines a blockchain's entire behavior. In Polkadot SDK-based blockchains, the runtime represents a complete, self-contained description of the blockchain's state transition function. +The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. -### Characteristics +## Quick Start Guides -The runtime is distinguished by three key characteristics: +Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. -- **Business logic**: Defines the complete application-specific blockchain behavior. -- **WebAssembly compilation**: Ensures platform-independent, secure execution. -- **On-chain storage**: Stored within the blockchain's state, allowing dynamic updates. +| Tutorial | Tools | Description | +| :--------------------------------------------------------------------------------------------: | :----------------------------: | :---------------------------------------------------------------------: | +| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | Learn how to set up and run the Polkadot SDK Parachain Template locally | +| [Launch a Local Parachain](/parachains/testing/run-a-parachain-network/) | Zombienet, Chopsticks | Set up a local development environment for testing | +| [Connect to Polkadot](/chain-interactions/query-on-chain-data/query-sdks/) | Polkadot.js, Substrate Connect | Connect your application to Polkadot networks | +| [Fork an Existing Parachain](/parachains/testing/fork-a-parachain/) | Chopsticks | Create a local fork of a live parachain for testing | -### Key Functions +## Launch a Simple Parachain -The runtime performs several critical functions, such as: +Learn the fundamentals of launching and deploying a parachain to the Polkadot network. -- Define state transition rules. -- Implement blockchain-specific logic. -- Manage account interactions. -- Control transaction processing. -- Define governance mechanisms. -- Handle custom pallets and modules. +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------: | +| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | +| [Deploy to Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/) | Step-by-step tutorial to deploying your parachain to Polkadot | +| [Obtain Coretime](/parachains/launch-a-parachain/obtain-coretime/) | Learn how to acquire blockspace using Polkadot's coretime model (RegionX) | -## Communication Between Node and Runtime +## Customize Your Runtime -The client and runtime communicate exclusively using [SCALE-encoded](/polkadot-protocol/parachain-basics/data-encoding){target=\_blank} communication. This ensures efficient and compact data exchange between the two components. +Build custom functionality for your parachain by composing and creating pallets. -### Runtime APIs +| Tutorial | Description | +| :-------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------: | +| [Add Existing Pallets to the Runtime](/parachains/customize-runtime/add-existing-pallets/) | Integrate pre-built pallets from the FRAME ecosystem | +| [Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/) | Configure and use multiple instances of the same pallet | +| [Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/) | Enable smart contract capabilities using Contracts or EVM pallets | -The Runtime API consists of well-defined functions and constants a client assumes are implemented in the Runtime Wasm blob. These APIs enable the client to interact with the runtime to execute blockchain operations and retrieve information. The client invokes these APIs to: +### Pallet Development -- Build, execute, and finalize blocks. -- Access metadata. -- Access consensus related information. -- Handle transaction execution. +Deep dive into creating and managing custom pallets for your parachain. -### Host Functions +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------: | +| [Create a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/) | Build a pallet from scratch with custom logic | +| [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/) | Set up a mock runtime environment for testing | +| [Pallet Unit Testing](/parachains/customize-runtime/pallet-development/pallet-testing/) | Write comprehensive tests for your pallet logic | +| [Add Your Custom Pallet to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/) | Integrate your custom pallet into your parachain runtime | +| [Benchmark the Custom Pallet](/parachains/customize-runtime/pallet-development/benchmark-pallet/) | Measure and optimize pallet performance with benchmarking | -During execution, the runtime can access certain external client functionalities via host functions. The specific functions the client exposes allow the runtime to perform operations outside the WebAssembly domain. Host functions enable the runtime to: +## Testing -- Perform cryptographic operations. -- Access the current blockchain state. -- Handle storage modifications. -- Allocate memory. +Test your parachain in various environments before production deployment. +| Tutorial | Description | +| :---------------------------------------------------------------------: | :-----------------------------------------------------: | +| [Fork a Parachain](/parachains/testing/fork-a-parachain/) | Use Chopsticks to create a local fork for testing | +| [Run a Parachain Network](/parachains/testing/run-a-parachain-network/) | Launch a complete parachain test network with Zombienet | ---- +## Runtime Upgrades and Maintenance -Page Title: On-Chain Governance Overview +Manage your parachain's lifecycle with forkless upgrades and maintenance operations. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md -- Canonical (HTML): https://docs.polkadot.com/reference/governance/ -- Summary: Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. +| Tutorial | Description | +| :-----------------------------------------------------------------------: | :--------------------------------------------------: | +| [Runtime Upgrades](/parachains/runtime-maintenance/runtime-upgrades/) | Perform forkless runtime upgrades via governance | +| [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/) | Safely migrate storage when updating runtime logic | +| [Unlock Parachains](/parachains/runtime-maintenance/unlock-parachains/) | Understand parachain lifecycle and unlock mechanisms | -# On-Chain Governance +## Interoperability -## Introduction +Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). -Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model. +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: | +| [Open HRMP Channels Between Parachains](/parachains/interoperability/channels-between-parachains/) | Establish communication channels with other parachains | +| [Open HRMP Channels with System Parachains](/parachains/interoperability/channels-with-system-parachains/) | Connect with Asset Hub and other system parachains | -This guide will explain the principles and structure of OpenGov and walk you through its key components, such as Origins, Tracks, and Delegation. You will learn about improvements over earlier governance systems, including streamlined voting processes and enhanced stakeholder participation. +## Integrations -With OpenGov, Polkadot achieves a flexible, scalable, and democratic governance framework that allows multiple proposals to proceed simultaneously, ensuring the network evolves in alignment with its community's needs. +Integrate your parachain with essential ecosystem tools and services. -## Governance Evolution +| Tutorial | Description | +| :--------------------------------------------: | :----------------------------------------------------: | +| [Wallets](/parachains/integrations/wallets/) | Integrate wallet support for user interactions | +| [Indexers](/parachains/integrations/indexers/) | Set up indexing solutions for querying blockchain data | +| [Oracles](/parachains/integrations/oracles/) | Connect your parachain to off-chain data sources | -Polkadot’s governance journey began with [Governance V1](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#governance-summary){target=\_blank}, a system that proved effective in managing treasury funds and protocol upgrades. However, it faced limitations, such as: +## Additional Resources -- Slow voting cycles, causing delays in decision-making. -- Inflexibility in handling multiple referendums, restricting scalability. +- [Polkadot SDK Documentation](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/index.html) +- [Polkadot Wiki - Parachains](https://wiki.polkadot.network/docs/learn-parachains/) -To address these challenges, Polkadot introduced OpenGov, a governance model designed for greater inclusivity, efficiency, and scalability. OpenGov replaces the centralized structures of Governance V1, such as the Council and Technical Committee, with a fully decentralized and dynamic framework. -For a full comparison of the historic and current governance models, visit the [Gov1 vs. Polkadot OpenGov](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#gov1-vs-polkadot-opengov){target=\_blank} section of the Polkadot Wiki. +--- -## OpenGov Key Features +Page Title: Get Started with Smart Contracts -OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/get-started/ +- Summary: Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. -- **Decentralization**: Shifts all decision-making power to the public, ensuring a more democratic process. -- **Enhanced delegation**: Allows users to delegate their votes to trusted experts across specific governance tracks. -- **Simultaneous referendums**: Multiple proposals can progress at once, enabling faster decision-making. -- **Polkadot Technical Fellowship**: A broad, community-driven group replacing the centralized Technical Committee. +# Get Started -This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. +This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need. -## Origins and Tracks +## Quick Starts -In OpenGov, origins and tracks are central to managing proposals and votes. +Kick off development fast with curated links for connecting, funding, exploring, and deploying your first contract. -- **Origin**: Determines the authority level of a proposal (e.g., Treasury, Root) which decides the track of all referendums from that origin. -- **Track**: Define the procedural flow of a proposal, such as voting duration, approval thresholds, and enactment timelines. +| Quick Start | Tools | Description | +|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:| +| [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer | +| [Get Test Tokens](/smart-contracts/faucets/){target=\_blank} | - | Request test funds to deploy and interact with contracts | +| [Explore Transactions](/smart-contracts/explorers/){target=\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state | +| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} | Remix | One‑click browser deployment to Polkadot Hub | +| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\_blank} | Foundry | Scripted deployments and testing from the CLI | +| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} | Hardhat | Project scaffolding, testing, and deployments | -Developers must be aware that referendums from different origins and tracks will take varying amounts of time to reach approval and enactment. The [Polkadot Technical Fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} has the option to shorten this timeline by whitelisting a proposal and allowing it to be enacted through the [Whitelist Caller](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#whitelisted-caller){target=\_blank} origin. +## Build and Test Locally -Visit [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#origins-and-tracks){target=\_blank} for details on current origins and tracks, associated terminology, and parameters. +Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. -## Referendums +| Build and Test Locally | Tools | Description | +|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:| +| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\_blank} | Polkadot SDK node | Spin up a local node for iterative development | +| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts | +| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\_blank} | Remix | Publish verified source on explorers | +| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\_blank} | Foundry | Install toolchain and configure networks | +| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\_blank} | Foundry | Write and run Solidity tests locally | +| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\_blank} | Foundry | Verify deployed bytecode and metadata | +| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} | Hardhat | Initialize a project and configure networks | +| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} | Hardhat | Unit test contracts and run scripts | +| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\_blank} | Hardhat | Verify deployments on explorers | -In OpenGov, anyone can submit a referendum, fostering an open and participatory system. The timeline for a referendum depends on the privilege level of the origin with more significant changes offering more time for community voting and participation before enactment. +## Ethereum Developer Resources -The timeline for an individual referendum includes four distinct periods: +Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. -- **Lead-in**: A minimum amount of time to allow for community participation, available room in the origin, and payment of the decision deposit. Voting is open during this period. -- **Decision**: Voting continues. -- **Confirmation**: Referendum must meet [approval and support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} criteria during entire period to avoid rejection. -- **Enactment**: Changes approved by the referendum are executed. +| Ethereum Developer Guides | Description | +|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:| +| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts | +| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\_blank} | Transaction types, fees, and multi‑dimensional metering | +| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} | Gas vs. weight, proof size, and storage deposits | +| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\_blank} | Deployment patterns and best practices on Polkadot Hub | +| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank} | Supported Ethereum JSON‑RPC methods and examples | +| [Migration](/smart-contracts/for-eth-devs/migration/){target=\_blank} | Port existing apps and tooling to Polkadot Hub | +| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} | Overview of EVM and native execution on the Hub | -### Vote on Referendums +## Cookbook: Hands‑on Tutorials -Voters can vote with their tokens on each referendum. Polkadot uses a voluntary token locking mechanism, called conviction voting, as a way for voters to increase their voting power. A token holder signals they have a stronger preference for approving a proposal based upon their willingness to lock up tokens. Longer voluntary token locks are seen as a signal of continual approval and translate to increased voting weight. +Follow step‑by‑step guides that walk through common tasks and complete dApp examples. -See [Voting on a Referendum](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank} for a deeper look at conviction voting and related token locks. +| Tutorial | Tools | Description | +|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:| +| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} | Remix | Minimal deployment walkthrough | +| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token | +| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection | +| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\_blank} | Hardhat | Full dApp project: compile, test, deploy | +| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\_blank} | Multiple | End‑to‑end dApp patterns and practices | -### Delegate Voting Power +## Libraries -The OpenGov system also supports multi-role delegations, allowing token holders to assign their voting power on different tracks to entities with expertise in those areas. +Choose the client libraries that fit your stack for connecting wallets and calling contracts. -For example, if a token holder lacks the technical knowledge to evaluate proposals on the [Root track](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#root){target=\_blank}, they can delegate their voting power for that track to an expert they trust to vote in the best interest of the network. This ensures informed decision-making across tracks while maintaining flexibility for token holders. +| Library | Description | +|:------------------------------------------------------------------:|:-------------------------------------------------------:| +| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank} | Connect, sign, and interact with contracts using Ethers | +| [viem](/smart-contracts/libraries/viem/){target=\_blank} | Type‑safe EVM interactions and utilities | +| [Wagmi](/smart-contracts/libraries/wagmi/){target=\_blank} | React hooks for wallet connections and contract calls | +| [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank} | Web3 provider and contract APIs | +| [Web3.py](/smart-contracts/libraries/web3-py/){target=\_blank} | Python toolkit for on‑chain interactions and scripts | -Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. +## Integrations -### Cancel a Referendum +Integrate essential services like wallets, indexers, and oracles to round out your dApp. -Polkadot OpenGov has two origins for rejecting ongoing referendums: +| Integration | Description | +|:-------------------------------------------------------------------:|:-----------------------------------------:| +| [Wallets](/smart-contracts/integrations/wallets/){target=\_blank} | Supported wallets and configuration notes | +| [Indexers](/smart-contracts/integrations/indexers/){target=\_blank} | Index and query blockchain data | +| [Oracles](/smart-contracts/integrations/oracles/){target=\_blank} | Bring external data on‑chain | -- [**Referendum Canceller**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-canceller){target=\_blank}: Cancels an active referendum when non-malicious errors occur and refunds the deposits to the originators. -- [**Referendum Killer**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-killer){target=\_blank}: Used for urgent, malicious cases this origin instantly terminates an active referendum and slashes deposits. +## Precompiles -See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. +Discover precompiled system contracts available on the Hub and how to use them. -## Additional Resources +| Topic | Description | +|:------------------------------------------------------------------------:|:---------------------------------------------------:| +| [Overview of Precompiles](/smart-contracts/precompiles/){target=\_blank} | What precompiles are available on the Hub | +| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\_blank} | EVM precompiles and interfaces | +| [Staking](/smart-contracts/precompiles/staking/){target=\_blank} | Interact with staking functionality via precompiles | +| [XCM](/smart-contracts/precompiles/xcm/){target=\_blank} | Cross‑chain messaging helpers for contracts | -- **[Democracy pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/democracy/src){target=\_blank}**: Handles administration of general stakeholder voting. -- **[Gov2: Polkadot’s Next Generation of Decentralised Governance](https://medium.com/polkadot-network/gov2-polkadots-next-generation-of-decentralised-governance-4d9ef657d11b){target=\_blank}**: Medium article by Gavin Wood. -- **[Polkadot Direction](https://matrix.to/#/#Polkadot-Direction:parity.io){target=\_blank}**: Matrix Element client. -- **[Polkassembly](https://polkadot.polkassembly.io/){target=\_blank}**: OpenGov dashboard and UI. -- **[Polkadot.js Apps Governance](https://polkadot.js.org/apps/#/referenda){target=\_blank}**: Overview of active referendums. +From here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\_blank} or reach out in the community channels. --- -Page Title: Origins and Tracks +Page Title: Get Started with XCM -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance-origins-tracks.md -- Canonical (HTML): https://docs.polkadot.com/reference/governance/origins-tracks/ -- Summary: Explore Polkadot's OpenGov origins and tracks system, defining privilege levels, decision processes, and tailored pathways for network proposals. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ +- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. -# Origins and Tracks +# Get Started with XCM ## Introduction -Polkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency. - -This guide will help you understand the role of origins in classifying proposals by privilege and priority. You will learn how tracks guide proposals through tailored stages like voting, confirmation, and enactment and how to select the correct origin for your referendum to align with community expectations and network governance. - -Origins and tracks are vital in streamlining the governance workflow and maintaining Polkadot's resilience and adaptability. - -## Origins - -Origins are the foundation of Polkadot's OpenGov governance system. They categorize proposals by privilege and define their decision-making rules. Each origin corresponds to a specific level of importance and risk, guiding how referendums progress through the governance process. - -- High-privilege origins like Root Origin govern critical network changes, such as core software upgrades. -- Lower-privilege origins like Small Spender handle minor requests, such as community project funding under 10,000 DOT. - -Proposers select an origin based on the nature of their referendum. Origins determine parameters like approval thresholds, required deposits, and timeframes for voting and confirmation. Each origin is paired with a track, which acts as a roadmap for the proposal's lifecycle, including preparation, voting, and enactment. - -For a detailed list of origins and their associated parameters, see the [Polkadot OpenGov Origins](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/){target=\_blank} entry in the Polkadot Wiki. +Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. -## Tracks +With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. -Tracks define a referendum's journey from submission to enactment, tailoring governance parameters to the impact of proposed changes. Each track operates independently and includes several key stages: +## Messaging Format -- **Preparation**: Time for community discussion before voting begins. -- **Voting**: Period for token holders to cast their votes. -- **Decision**: Finalization of results and determination of the proposal's outcome. -- **Confirmation**: Period to verify sustained community support before enactment. -- **Enactment**: Final waiting period before the proposal takes effect. +XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. -Tracks customize these stages with parameters like decision deposit requirements, voting durations, and approval thresholds, ensuring proposals from each origin receive the required scrutiny and process. For example, a runtime upgrade in the Root Origin track will have longer timeframes and stricter thresholds than a treasury request in the Small Spender track. +XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. -## Additional Resources +## The Four Principles of XCM -- For a list of origins and tracks for Polkadot and Kusama, including associated parameters, see the [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#origins-and-tracks-info){target=\_blank} entry in the Polkadot Wiki. +XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: -- For a deeper dive into the approval and support system, see the [Approval and Support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} entry of the Polkadot Wiki. +- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. +- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. +- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. +- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. +These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. ---- +## The XCM Tech Stack -Page Title: Overview of FRAME +![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md -- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ -- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. +The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. -# Customize Your Runtime +## Core Functionalities of XCM -## Introduction +XCM enhances cross-consensus communication by introducing several powerful features: -A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. +- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. +- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. +- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. -This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. +The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. -## Understanding Your Runtime +## XCM Example -The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. +The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). -Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. +```rust +let message = Xcm(vec![ + WithdrawAsset((Here, amount).into()), + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } +]); +``` -## Runtime Architecture +The message consists of three instructions described as follows: -The following diagram shows how FRAME components work together to form your runtime: +- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. -![](/images/parachains/customize-runtime/index/frame-overview-01.webp) + ```rust + WithdrawAsset((Here, amount).into()), + ``` -The main components are: + - **`Here`**: The native parachain token. + - **`amount`**: The number of tokens that are transferred. -- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. -- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. -- **`frame_system`**: Provides core runtime primitives and storage. -- **`frame_support`**: Utilities and macros that simplify pallet development. + The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. -## Building Blocks: Pallets +- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. -[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. + ```rust + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + ``` -A pallet can implement virtually any blockchain feature you need: + - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. + - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. -- Expose new transactions that users can submit. -- Store data on-chain. -- Enforce business rules and validation logic. -- Emit events to notify users of state changes. -- Handle errors gracefully. +- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. -### Pre-Built Pallets vs. Custom Pallets + ```rust + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } + ``` -FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. + - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. + +This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. -However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. +## Overview -### Pallet Structure +XCM revolutionizes cross-chain communication by enabling use cases such as: -FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. +- Token transfers between blockchains. +- Asset locking for cross-chain smart contract interactions. +- Remote execution of functions on other blockchains. -A typical pallet looks like this: +These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. -```rust -pub use pallet::*; -#[frame_support::pallet] -pub mod pallet { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; +--- - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); +Page Title: Install Polkadot SDK - #[pallet::config] // snip - #[pallet::event] // snip - #[pallet::error] // snip - #[pallet::storage] // snip - #[pallet::call] // snip -} -``` +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md +- Canonical (HTML): https://docs.polkadot.com/parachains/install-polkadot-sdk/ +- Summary: Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. -Every pallet can implement these core macros: +# Install Polkadot SDK -- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. -- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. -- **`#[pallet::config]`**: Defines configuration and associated types. -- **`#[pallet::event]`**: Defines events emitted by your pallet. -- **`#[pallet::error]`**: Defines error types your pallet can return. -- **`#[pallet::storage]`**: Defines on-chain storage items. -- **`#[pallet::call]`**: Defines dispatchable functions (transactions). +This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts: -For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. +- **Installing dependencies**: Setting up Rust, required system packages, and development tools. +- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. -## How Runtime Customization Works +Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. -Customizing your runtime typically follows these patterns: +## Install Dependencies: macOS -**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. +You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. -**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. +### Before You Begin {: #before-you-begin-mac-os } -**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. +Before you install Rust and set up your development environment on macOS, verify that your computer meets the following basic requirements: -**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. +- Operating system version is 10.7 Lion or later. +- Processor speed of at least 2 GHz. Note that 3 GHz is recommended. +- Memory of at least 8 GB RAM. Note that 16 GB is recommended. +- Storage of at least 10 GB of available space. +- Broadband Internet connection. -The following diagram illustrates how pallets combine to form a complete runtime: +### Install Homebrew -![](/images/parachains/customize-runtime/index/frame-overview-02.webp) +In most cases, you should use Homebrew to install and manage packages on macOS computers. If you don't already have Homebrew installed on your local computer, you should download and install it before continuing. -## Starting Templates +To install Homebrew: -The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. +1. Open the Terminal application. +2. Download and install Homebrew by running the following command: -- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. + ```bash + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" + ``` -- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. +3. Verify Homebrew has been successfully installed by running the following command: -- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. + ```bash + brew --version + ``` -- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. + The command displays output similar to the following: -## Key Customization Scenarios +
    + brew --version + Homebrew 4.3.15 +
    -This section covers the most common customization patterns you'll encounter: +### Support for Apple Silicon -- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. +Protobuf must be installed before the build process can begin. To install it, run the following command: -- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. +```bash +brew install protobuf +``` -- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. +### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } -- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. +Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `openssl`. -- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. +To install `openssl` and the Rust toolchain on macOS: +1. Open the Terminal application. +2. Ensure you have an updated version of Homebrew by running the following command: ---- + ```bash + brew update + ``` -Page Title: Overview of the Polkadot Relay Chain +3. Install the `openssl` package by running the following command: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/ -- Summary: Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. + ```bash + brew install openssl + ``` -# Overview +4. Download the `rustup` installation program and use it to install Rust by running the following command: -## Introduction + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank}, and cross-chain interactions via its native [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank}. +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: -This guide covers key aspects of Polkadot’s architecture, including its high-level protocol structure, blockspace commoditization, and the role of its native token, DOT, in governance, staking, and resource allocation. + ```bash + source ~/.cargo/env + ``` -## Polkadot 1.0 +7. Configure the Rust toolchain to default to the latest stable version by running the following commands: -Polkadot 1.0 represents the state of Polkadot as of 2023, coinciding with the release of [Polkadot runtime v1.0.0](https://github.com/paritytech/polkadot/releases/tag/v1.0.0){target=\_blank}. This section will focus on Polkadot 1.0, along with philosophical insights into network resilience and blockspace. + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -As a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including: +8. Install `cmake` using the following command: -- **Application-specific Layer-1 blockchains (parachains)**: Polkadot's sharded network allows for parallel transaction processing, with shards that can have unique state transition functions, enabling custom-built L1 chains optimized for specific applications. + ```bash + brew install cmake + ``` -- **Shared security and scalability**: L1 chains connected to Polkadot benefit from its [Nominated Proof of Stake (NPoS)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#nominated-proof-of-stake){target=\_blank} system, providing security out-of-the-box without the need to bootstrap their own. +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -- **Secure interoperability**: Polkadot's native interoperability enables seamless data and value exchange between parachains. This interoperability can also be used outside of the ecosystem for bridging with external networks. +## Install Dependencies: Linux -- **Resilient infrastructure**: Decentralized and scalable, Polkadot ensures ongoing support for development and community initiatives via its on-chain [treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} and governance. +Rust supports most Linux distributions. Depending on the specific distribution and version of the operating system you use, you might need to add some software dependencies to your environment. In general, your development environment should include a linker or a C-compatible compiler, such as `clang`, and an appropriate integrated development environment (IDE). -- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. +### Before You Begin {: #before-you-begin-linux } -- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. +Check the documentation for your operating system for information about the installed packages and how to download and install any additional packages you might need. For example, if you use Ubuntu, you can use the Ubuntu Advanced Packaging Tool (`apt`) to install the `build-essential` package: - - [Polkadot Blockchain Academy](https://polkadot.com/blockchain-academy){target=\_blank} - - [EdX courses](https://www.edx.org/school/web3x){target=\_blank} - - Rust and Substrate courses (coming soon) +```bash +sudo apt install build-essential +``` -### High-Level Architecture +At a minimum, you need the following packages before you install Rust: -Polkadot features a chain that serves as the central component of the system. This chain is depicted as a ring encircled by several parachains that are connected to it. +```text +clang curl git make +``` -According to Polkadot's design, any blockchain that can compile to WebAssembly (Wasm) and adheres to the Parachains Protocol becomes a parachain on the Polkadot network. +Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `libssl-dev` or `openssl-devel`. -Here’s a high-level overview of the Polkadot protocol architecture: +### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } -![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } +To install the Rust toolchain on Linux: -Parachains propose blocks to Polkadot validators, who check for availability and validity before finalizing them. With the relay chain providing security, collators—full nodes of parachains—can focus on their tasks without needing strong incentives. +1. Open a terminal shell. +2. Check the packages installed on the local computer by running the appropriate package management command for your Linux distribution. +3. Add any package dependencies you are missing to your local development environment by running the appropriate package management command for your Linux distribution: -The [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank} allows parachains to exchange messages freely, leveraging the chain's security for trust-free communication. + === "Ubuntu" -In order to interact with chains that want to use their own finalization process (e.g., Bitcoin), Polkadot has [bridges](/reference/parachains/interoperability/#bridges-connecting-external-networks){target=\_blank} that offer two-way compatibility, meaning that transactions can be made between different parachains. + ```bash + sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler + ``` -### Polkadot's Additional Functionalities + === "Debian" -Historically, obtaining core slots on Polkadot chain relied upon crowdloans and auctions. Chain cores were leased through auctions for three-month periods, up to a maximum of two years. Crowdloans enabled users to securely lend funds to teams for lease deposits in exchange for pre-sale tokens, which is the only way to access slots on Polkadot 1.0. Auctions are now deprecated in favor of [coretime](/polkadot-protocol/architecture/system-chains/coretime/){target=\_blank}. + ```sh + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler + ``` -Additionally, the chain handles [staking](https://wiki.polkadot.com/learn/learn-staking/){target=\_blank}, [accounts](/reference/parachains/accounts/){target=\_blank}, balances, and [governance](/reference/governance/){target=\_blank}. + === "Arch" -#### Agile Coretime + ```sh + pacman -Syu --needed --noconfirm curl git clang make protobuf + ``` -The new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. + === "Fedora" -[Agile coretime](/reference/polkadot-hub/consensus-and-security/agile-coretime/){target=\_blank} improves the efficient use of Polkadot's network resources and offers economic flexibility for developers, extending Polkadot's capabilities far beyond the original vision outlined in the [whitepaper](https://polkadot.com/papers/Polkadot-whitepaper.pdf){target=\_blank}. + ```sh + sudo dnf update + sudo dnf install clang curl git openssl-devel make protobuf-compiler + ``` -It enables parachains to purchase monthly "bulk" allocations of coretime (the time allocated for utilizing a core, measured in Polkadot relay chain blocks), ensuring heavy-duty parachains that can author a block every six seconds with [Asynchronous Backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} can reliably renew their coretime each month. Although six-second block times are now the default, parachains have the option of producing blocks less frequently. + === "OpenSUSE" -Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. + ```sh + sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf + ``` -### Polkadot's Resilience + Remember that different distributions might use different package managers and bundle packages in different ways. For example, depending on your installation selections, Ubuntu Desktop and Ubuntu Server might have different packages and different requirements. However, the packages listed in the command-line examples are applicable to many common Linux distributions, including Debian, Linux Mint, MX Linux, and Elementary OS. -Decentralization is a vital component of blockchain networks, but it comes with trade-offs: +4. Download the `rustup` installation program and use it to install Rust by running the following command: -- An overly decentralized network may face challenges in reaching consensus and require significant energy to operate. -- Also, a network that achieves consensus quickly risks centralization, making it easier to manipulate or attack. + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: -Polkadot 1.0 currently achieves resilience through several strategies: + ```bash + source $HOME/.cargo/env + ``` -- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. +7. Verify your installation by running the following command: -- **Decentralized nodes**: Designed to encourage operators to join the network. This program aims to expand and diversify the validators in the ecosystem who aim to become independent of the program during their term. Feel free to explore more about the program on the official [Decentralized Nodes](https://nodes.web3.foundation/){target=\_blank} page. + ```bash + rustc --version + ``` -- **On-chain treasury and governance**: Known as [OpenGov](/reference/governance/){target=\_blank}, this system allows every decision to be made through public referenda, enabling any token holder to cast a vote. +8. Configure the Rust toolchain to default to the latest stable version by running the following commands: -### Polkadot's Blockspace + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -Polkadot 1.0’s design allows for the commoditization of blockspace. +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -Blockspace is a blockchain's capacity to finalize and commit operations, encompassing its security, computing, and storage capabilities. Its characteristics can vary across different blockchains, affecting security, flexibility, and availability. +## Install Dependencies: Windows (WSL) -- **Security**: Measures the robustness of blockspace in Proof of Stake (PoS) networks linked to the stake locked on validator nodes, the variance in stake among validators, and the total number of validators. It also considers social centralization (how many validators are owned by single operators) and physical centralization (how many validators run on the same service provider). +In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. -- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes. +However, suppose your local computer uses Microsoft Windows instead of a UNIX-based operating system. In that case, you can configure it with additional software to make it a suitable development environment for building Substrate-based blockchains. To prepare a development environment on a Microsoft Windows computer, you can use Windows Subsystem for Linux (WSL) to emulate a UNIX operating environment. -- **Availability**: Indicates how easily users can access blockspace. It should be easily accessible, allowing diverse business models to thrive, ideally regulated by a marketplace based on demand and supplemented by options for "second-hand" blockspace. +### Before You Begin {: #before-you-begin-windows-wls } -Polkadot is built on core blockspace principles, but there's room for improvement. Tasks like balance transfers, staking, and governance are managed on the relay chain. +Before installing on Microsoft Windows, verify the following basic requirements: -Delegating these responsibilities to [system chains](/polkadot-protocol/architecture/system-chains/){target=\_blank} could enhance flexibility and allow the relay chain to concentrate on providing shared security and interoperability. +- You have a computer running a supported Microsoft Windows operating system: + - **For Windows desktop**: You must be running Microsoft Windows 10, version 2004 or later, or Microsoft Windows 11 to install WSL. + - **For Windows server**: You must be running Microsoft Windows Server 2019, or later, to install WSL on a server operating system. +- You have a good internet connection and access to a shell terminal on your local computer. -For more information about blockspace, watch [Robert Habermeier’s interview](https://www.youtube.com/watch?v=e1vISppPwe4){target=\_blank} or read his [technical blog post](https://www.rob.tech/blog/polkadot-blockspace-over-blockchains/){target=\_blank}. +### Set Up Windows Subsystem for Linux -## DOT Token +WSL enables you to emulate a Linux environment on a computer that uses the Windows operating system. The primary advantage of this approach for Substrate development is that you can use all of the code and command-line examples as described in the Substrate documentation. For example, you can run common commands—such as `ls` and `ps`—unmodified. By using WSL, you can avoid configuring a virtual machine image or a dual-boot operating system. -DOT is the native token of the Polkadot network, much like BTC for Bitcoin and Ether for the Ethereum blockchain. DOT has 10 decimals, uses the Planck base unit, and has a balance type of `u128`. The same is true for Kusama's KSM token with the exception of having 12 decimals. +To prepare a development environment using WSL: -### Redenomination of DOT - -Polkadot conducted a community poll, which ended on 27 July 2020 at block 888,888, to decide whether to redenominate the DOT token. The stakeholders chose to redenominate the token, changing the value of 1 DOT from 1e12 plancks to 1e10 plancks. +1. Check your Windows version and build number to see if WSL is enabled by default. -Importantly, this did not affect the network's total number of base units (plancks); it only affects how a single DOT is represented. The redenomination became effective 72 hours after transfers were enabled, occurring at block 1,248,328 on 21 August 2020 around 16:50 UTC. + If you have Microsoft Windows 10, version 2004 (Build 19041 and higher), or Microsoft Windows 11, WSL is available by default and you can continue to the next step. -### The Planck Unit + If you have an older version of Microsoft Windows installed, see the [WSL manual installation steps for older versions](https://learn.microsoft.com/en-us/windows/wsl/install-manual){target=\_blank}. If you are installing on an older version of Microsoft Windows, you can download and install WLS 2 if your computer has Windows 10, version 1903 or higher. -The smallest unit of account balance on Polkadot SDK-based blockchains (such as Polkadot and Kusama) is called _Planck_, named after the Planck length, the smallest measurable distance in the physical universe. +2. Select **Windows PowerShell** or **Command Prompt** from the **Start** menu, right-click, then **Run as administrator**. -Similar to how BTC's smallest unit is the Satoshi and ETH's is the Wei, Polkadot's native token DOT equals 1e10 Planck, while Kusama's native token KSM equals 1e12 Planck. +3. In the PowerShell or Command Prompt terminal, run the following command: -### Uses for DOT + ```bash + wsl --install + ``` -DOT serves three primary functions within the Polkadot network: + This command enables the required WSL 2 components that are part of the Windows operating system, downloads the latest Linux kernel, and installs the Ubuntu Linux distribution by default. -- **Governance**: It is used to participate in the governance of the network. -- **Staking**: DOT is staked to support the network's operation and security. -- **Buying coretime**: Used to purchase coretime in-bulk or on-demand and access the chain to benefit from Polkadot's security and interoperability. + If you want to review the other Linux distributions available, run the following command: -Additionally, DOT can serve as a transferable token. For example, DOT, held in the treasury, can be allocated to teams developing projects that benefit the Polkadot ecosystem. + ```bash + wsl --list --online + ``` -## JAM and the Road Ahead +4. After the distribution is downloaded, close the terminal. -The Join-Accumulate Machine (JAM) represents a transformative redesign of Polkadot's core architecture, envisioned as the successor to the current relay chain. Unlike traditional blockchain architectures, JAM introduces a unique computational model that processes work through two primary functions: +5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. -- **Join**: Handles data integration. -- **Accumulate**: Folds computations into the chain's state. + Restarting the computer is required to start the installation of the Linux distribution. It can take a few minutes for the installation to complete after you restart. -JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: + For more information about setting up WSL as a development environment, see the [Set up a WSL development environment](https://learn.microsoft.com/en-us/windows/wsl/setup/environment){target=\_blank} docs. -- **Permissionless code execution**: JAM is designed to be more generic and flexible, allowing for permissionless code execution through services that can be deployed without governance approval. -- **More effective block time utilization**: JAM's efficient pipeline processing model places the prior state root in block headers instead of the posterior state root, enabling more effective utilization of block time for computations. +### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } -This architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes. +To install the Rust toolchain on WSL: +1. Click the **Start** menu, then select **Ubuntu**. +2. Type a UNIX user name to create a user account. +3. Type a password for your UNIX user, then retype the password to confirm it. +4. Download the latest updates for the Ubuntu distribution using the Ubuntu Advanced Packaging Tool (`apt`) by running the following command: ---- + ```bash + sudo apt update + ``` -Page Title: Parachains Overview +5. Add the required packages for the Ubuntu distribution by running the following command: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/ -- Summary: Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. + ```bash + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler + ``` -# Parachains Overview +6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: -## Introduction + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network. +7. Follow the prompts displayed to proceed with a default installation. -Unlike standalone blockchains that must bootstrap their own validator sets and security, parachains leverage Polkadot's pooled security model. This allows parachain developers to focus on their application-specific functionality rather than consensus and security infrastructure. Parachains can communicate with each other through Cross-Consensus Messaging (XCM), enabling seamless interoperability across the Polkadot ecosystem. +8. Update your current shell to include Cargo by running the following command: -Key capabilities that parachains provide include: + ```bash + source ~/.cargo/env + ``` -- **Shared security**: Inherit security from Polkadot's validator set without maintaining your own. -- **Interoperability**: Communicate trustlessly with other parachains via XCM. -- **Scalability**: Process transactions in parallel with other parachains. -- **Customization**: Build application-specific logic tailored to your use case. -- **Upgradeability**: Upgrade runtime logic without hard forks. +9. Verify your installation by running the following command: -## Polkadot SDK: Parachain Architecture + ```bash + rustc --version + ``` -Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: +10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: -![](/images/reference/parachains/index/overview-01.webp) + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -- **[Substrate](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html){target=\_blank}**: The foundation providing core blockchain primitives and libraries. -- **[FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank}**: A modular framework for building your parachain's runtime logic. -- **[Cumulus](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html){target=\_blank}**: Essential libraries and pallets that enable parachain functionality. -- **[XCM (Cross Consensus Messaging)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/xcm/index.html){target=\_blank}**: The messaging format for communicating with other parachains and the relay chain. -- **[Polkadot](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/polkadot/index.html){target=\_blank}**: The relay chain that provides security and coordination. +11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -### Substrate: The Foundation +## Build the Polkadot SDK -Substrate provides the core infrastructure that every parachain is built upon. It handles the low-level blockchain functionality, allowing you to focus on your application's unique features. Substrate includes implementations for networking, database management, consensus participation, and the execution environment for your runtime. +After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. -Every Polkadot SDK node consists of two main components: +### Clone the Polkadot SDK -- **Client (Host)**: Handles infrastructure services. +1. Clone the Polkadot SDK repository: - - Native binary that runs on validator and collator nodes. - - Executes the Wasm-compiled runtime. - - Manages networking, database, mempool, and block production. - - Interfaces with the relay chain for validation. + ```bash + git clone https://github.com/paritytech/polkadot-sdk.git + ``` -- **Runtime (State Transition Function)**: Contains your business logic. +2. Navigate into the project directory: - - Defines how your Polkadot SDK node processes transactions. - - Compiled to [Wasm](https://webassembly.org/){target=\_blank} for deterministic execution. - - Stored on-chain and upgradeable via governance. + ```bash + cd polkadot-sdk + ``` -```mermaid -%%{init: {'flowchart': {'padding': 5, 'nodeSpacing': 50, 'rankSpacing': 10}}}%% -graph TB - classDef title font-size:20px,font-weight:bold,stroke-width:0px - classDef clientStyle font-size:16px,font-weight:bold - classDef clientSubNodeStyle margin-top:10px - classDef runtimeCallExecutorStyle padding-top:10px +### Compile the Polkadot SDK - subgraph sg1[Parachain
    Node] - direction TB +Compile the entire Polkadot SDK repository to ensure your environment is properly configured: - I[RuntimeCall Executor] - B[Wasm Runtime - STF] +```bash +cargo build --release --locked +``` - subgraph sg2[Client] - direction TB - C[Network and Blockchain
    Infrastructure Services
    + Relay Chain Interface] - end +!!!note + This initial compilation will take significant time, depending on your machine specifications. It compiles all components of the Polkadot SDK to verify your toolchain is correctly configured. - I --> B - end +### Verify the Build - class sg1 title - class sg2 clientStyle - class C clientSubNodeStyle - class I runtimeCallExecutorStyle +Once the build completes successfully, verify the installation by checking the compiled binaries: +```bash +ls target/release ``` -### FRAME: Building Blocks for Your Runtime +You should see several binaries, including: + +- `polkadot`: The Polkadot relay chain node. +- `polkadot-parachain`: The parachain collator node. +- `polkadot-omni-node`:The omni node for running parachains. +- `substrate-node`: The kitchensink node with many pre-configured pallets. -FRAME provides modular components called [pallets](/reference/glossary#pallet){target=\_blank} that you can compose to build your parachain's runtime. Each pallet provides specific functionality that you can customize and configure for your needs. This modular approach allows you to quickly assemble complex functionality without writing everything from scratch. +Verify the Polkadot binary works by checking its version: -```mermaid -graph LR - subgraph SP["Parachain Runtime"] - direction LR - Timestamp ~~~ Aura ~~~ ParachainSystem - Balances ~~~ TransactionPayment ~~~ Sudo - subgraph Timestamp["Timestamp"] - SS1[Custom Config] - end - subgraph Aura["Aura"] - SS2[Custom Config] - end - subgraph ParachainSystem["Parachain System"] - SS3[Custom Config] - end - subgraph Balances["Balances"] - SS4[Custom Config] - end - subgraph TransactionPayment["Transaction Payment"] - SS5[Custom Config] - end - subgraph Sudo["Sudo"] - SS6[Custom Config] - end - style Timestamp stroke:#FF69B4 - style Aura stroke:#FF69B4 - style ParachainSystem stroke:#FF69B4 - style Balances stroke:#FF69B4 - style TransactionPayment stroke:#FF69B4 - style Sudo stroke:#FF69B4 - style SS1 stroke-dasharray: 5 - style SS2 stroke-dasharray: 5 - style SS3 stroke-dasharray: 5 - style SS4 stroke-dasharray: 5 - style SS5 stroke-dasharray: 5 - style SS6 stroke-dasharray: 5 - - end - subgraph AP["Available FRAME Pallets"] - direction LR - A1[Aura]~~~A2[Parachain
    System]~~~A3[Transaction
    Payment]~~~A4[Sudo] - B1[Identity]~~~B2[Balances]~~~B3[Assets]~~~B4[EVM] - C1[Timestamp]~~~C2[Staking]~~~C3[Contracts]~~~C4[and more...] - end - AP --> SP +```bash +./target/release/polkadot --version +``` + +This should display version information similar to: + +```bash +polkadot 1.16.0-1234abcd567 ``` -### Cumulus: Parachain-Specific Functionality +If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! -Cumulus is what transforms a Polkadot SDK-based runtime into a parachain-capable runtime. It provides the essential components for communicating with the relay chain, participating in Polkadot's consensus, and handling parachain-specific operations like block validation and collation. +## Optional: Run the Kitchensink Node -Key Cumulus components include: +The Polkadot SDK includes a feature-rich node called "kitchensink" located at `substrate/bin/node`. This node comes pre-configured with many pallets and features from the Polkadot SDK, making it an excellent reference for exploring capabilities and understanding how different components work together. -- **Parachain system pallet**: Core parachain functionality and relay chain communication. -- **Collator consensus**: Block production logic for parachain collators. -- **Relay chain interface**: APIs for interacting with the Polkadot relay chain. -- **Validation data**: Handling proof-of-validity data required by relay chain validators. +!!!note + If you've already compiled the Polkadot SDK in the previous step, the `substrate-node` binary is already built and ready to use. You can skip directly to running the node. -## Where to Go Next +### Run the Kitchensink Node in Development Mode -Building a parachain requires understanding the relationship between your chain and the Polkadot relay chain. The Polkadot SDK provides all the tools needed to design custom runtime logic, enable cross-chain communication, and deploy your parachain to production. +From the `polkadot-sdk` root directory, start the kitchensink node in development mode: -The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. +```bash +./target/release/substrate-node --dev +``` -
    +The `--dev` flag enables development mode, which: -- Guide __Launch a Simple Parachain__ +- Runs a single-node development chain. +- Produces and finalizes blocks automatically. +- Uses pre-configured development accounts (Alice, Bob, etc.). +- Deletes all data when stopped, ensuring a clean state on restart. - --- - Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. +You should see log output indicating the node is running and producing blocks, with increasing block numbers after `finalized`. - [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) +### Interact with the Kitchensink Node +The kitchensink node is accessible at `ws://localhost:9944`. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your browser to explore its features and connect to the local node. -- Guide __Customize Your Runtime__ +1. Click the network icon in the top left corner. +2. Scroll to **Development** and select **Local Node**. +3. Click **Switch** to connect to your local node. - --- +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) - Design your parachain's runtime logic and choose appropriate pallets for your use case. +Once connected, the interface updates its color scheme to indicate a successful connection to the local node. - [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) -- Guide __Interoperability__ +You can now explore the various pallets and features included in the kitchensink node, making it a valuable reference as you develop your own blockchain applications. - --- +To stop the node, press `Control-C` in the terminal. - Implement XCM for trustless cross-chain communication with other parachains. +## Where to Go Next - [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/) +
    -- Guide __Runtime Upgrades__ +- __Get Started with Parachain Development__ --- - Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. - - [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) + Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. + [:octicons-arrow-right-24: Get Started](/parachains/get-started/) +
    --- -Page Title: People Chain +Page Title: JSON-RPC APIs -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-people-and-identity.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/people-and-identity/ -- Summary: Learn how People chain secures decentralized identity management, empowering users to control and verify digital identities without central authorities. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ +- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. -# People Chain +# JSON-RPC APIs +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -People chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management. - -This solution empowers users to create, control, and verify their digital identities without reliance on centralized authorities. By prioritizing user sovereignty and data privacy, People chain establishes a foundation for trusted interactions throughout the Polkadot ecosystem while returning control of personal information to individuals. - -## Identity Management System - -People chain provides a comprehensive identity framework allowing users to: - -- Establish verifiable on-chain identities. -- Control disclosure of personal information. -- Receive verification from trusted registrars. -- Link multiple accounts under a unified identity. - -Users must reserve funds in a bond to store their information on chain. These funds are locked, not spent, and returned when the identity is cleared. - -### Sub-Identities - -The platform supports hierarchical identity structures through sub-accounts: - -- Primary accounts can establish up to 100 linked sub-accounts. -- Each sub-account maintains its own distinct identity. -- All sub-accounts require a separate bond deposit. +Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. -## Verification Process +This guide uses the Polkadot Hub TestNet endpoint: -### Judgment Requests +```text +https://testnet-passet-hub-eth-rpc.polkadot.io +``` -After establishing an on-chain identity, users can request verification from [registrars](#registrars): +## Available Methods -1. Users specify the maximum fee they're willing to pay for judgment. -2. Only registrars whose fees fall below this threshold can provide verification. -3. Registrars assess the provided information and issue a judgment. +### eth_accounts -### Judgment Classifications +Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. -Registrars can assign the following confidence levels to identity information: +**Parameters**: -- **Unknown**: Default status; no judgment rendered yet. -- **Reasonable**: Data appears valid but without formal verification (standard for most verified identities). -- **Known good**: Information certified correct through formal verification (requires documentation; limited to registrars). -- **Out of date**: Previously verified information that requires updating. -- **Low quality**: Imprecise information requiring correction. -- **Erroneous**: Incorrect information, potentially indicating fraudulent intent. +None. -A temporary "Fee Paid" status indicates judgment in progress. Both "Fee Paid" and "Erroneous" statuses lock identity information from modification until resolved. +**Example**: -### Registrars +```bash title="eth_accounts" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_accounts", + "params":[], + "id":1 +}' +``` -Registrars serve as trusted verification authorities within the People chain ecosystem. These entities validate user identities and provide attestations that build trust in the network. +--- -- Registrars set specific fees for their verification services. -- They can specialize in verifying particular identity fields. -- Verification costs vary based on complexity and thoroughness. +### eth_blockNumber -When requesting verification, users specify their maximum acceptable fee. Only registrars whose fees fall below this threshold can provide judgment. Upon completing the verification process, the user pays the registrar's fee, and the registrar issues an appropriate confidence level classification based on their assessment. +Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. -Multiple registrars operate across the Polkadot and People chain ecosystems, each with unique specializations and fee structures. To request verification: +**Parameters**: -1. Research available registrars and their verification requirements. -2. Contact your chosen registrar directly through their specified channels. -3. Submit required documentation according to their verification process. -4. Pay the associated verification fee. +None. -You must contact specific registrars individually to request judgment. Each registrar maintains its own verification procedures and communication channels. +**Example**: -## Where to Go Next +```bash title="eth_blockNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_blockNumber", + "params":[], + "id":1 +}' +``` -
    +--- -- External __Polkadot.js Guides about Identity__ +### eth_call - --- +Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. - Step-by-step instructions for managing identities through the Polkadot.js interface, with practical examples and visual guides. +**Parameters**: - [:octicons-arrow-right-24: Reference](https://wiki.polkadot.com/learn/learn-guides-identity/) +- **`transaction` ++"object"++**: The transaction call object. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- External __How to Set and Clear an Identity__ +**Example**: - --- +```bash title="eth_call" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_call", + "params":[{ + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_CALL" + }, "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` - Practical walkthrough covering identity setup and removal process on People chain. +Ensure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values. - [:octicons-arrow-right-24: Reference](https://support.polkadot.network/support/solutions/articles/65000181981-how-to-set-and-clear-an-identity) +--- -- External __People Chain Runtime Implementation__ +### eth_chainId - --- +Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}. - Source code for the People chain runtime, detailing the technical architecture of decentralized identity management. +**Parameters**: - [:octicons-arrow-right-24: Reference](https://github.com/polkadot-fellows/runtimes/tree/main/system-parachains/people) +None. -
    +**Example**: +```bash title="eth_chainId" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_chainId", + "params":[], + "id":1 +}' +``` --- -Page Title: Polkadot SDK Accounts - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/accounts/ -- Summary: Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. - -# Accounts - -## Introduction - -Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains. - -This page will guide you through the essential aspects of accounts, including their data structure, balance types, reference counters, and address formats. You’ll learn how accounts are managed within the runtime, how balances are categorized, and how addresses are encoded and validated. - -## Account Data Structure +### eth_estimateGas -Accounts are foundational to any blockchain, and the Polkadot SDK provides a flexible management system. This section explains how the Polkadot SDK defines accounts and manages their lifecycle through data structures within the runtime. +Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}. -### Account +**Parameters**: -The [`Account` data type](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/type.Account.html){target=\_blank} is a storage map within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank} that links an account ID to its corresponding data. This structure is fundamental for mapping account-related information within the chain. +- **`transaction` ++"object"++**: The transaction call object. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -The code snippet below shows how accounts are defined: +**Example**: -```rs - /// The full account information for a particular account ID. - #[pallet::storage] - #[pallet::getter(fn account)] - pub type Account = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - AccountInfo, - ValueQuery, - >; +```bash title="eth_estimateGas" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_estimateGas", + "params":[{ + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_FUNCTION_CALL" + }], + "id":1 +}' ``` -The preceding code block defines a storage map named `Account`. The `StorageMap` is a type of on-chain storage that maps keys to values. In the `Account` map, the key is an account ID, and the value is the account's information. Here, `T` represents the generic parameter for the runtime configuration, which is defined by the pallet's configuration trait (`Config`). - -The `StorageMap` consists of the following parameters: - -- **`_`**: Used in macro expansion and acts as a placeholder for the storage prefix type. Tells the macro to insert the default prefix during expansion. -- **`Blake2_128Concat`**: The hashing function applied to keys in the storage map. -- **`T: :AccountId`**: Represents the key type, which corresponds to the account’s unique ID. -- **`AccountInfo`**: The value type stored in the map. For each account ID, the map stores an `AccountInfo` struct containing: - - - **`T::Nonce`**: A nonce for the account, which is incremented with each transaction to ensure transaction uniqueness. - - **`T: :AccountData`**: Custom account data defined by the runtime configuration, which could include balances, locked funds, or other relevant information. - -- **`ValueQuery`**: Defines how queries to the storage map behave when no value is found; returns a default value instead of `None`. - -For a detailed explanation of storage maps, see the [`StorageMap`](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/struct.StorageMap.html){target=\_blank} entry in the Rust docs. - -### Account Info - -The `AccountInfo` structure is another key element within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank}, providing more granular details about each account's state. This structure tracks vital data, such as the number of transactions and the account’s relationships with other modules. - -```rs -/// Information of an account. -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct AccountInfo { - /// The number of transactions this account has sent. - pub nonce: Nonce, - /// The number of other modules that currently depend on this account's existence. The account - /// cannot be reaped until this is zero. - pub consumers: RefCount, - /// The number of other modules that allow this account to exist. The account may not be reaped - /// until this and `sufficients` are both zero. - pub providers: RefCount, - /// The number of modules that allow this account to exist for their own purposes only. The - /// account may not be reaped until this and `providers` are both zero. - pub sufficients: RefCount, - /// The additional data that belongs to this account. Used to store the balance(s) in a lot of - /// chains. - pub data: AccountData, -} -``` +Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. -The `AccountInfo` structure includes the following components: +--- -- **`nonce`**: Tracks the number of transactions initiated by the account, which ensures transaction uniqueness and prevents replay attacks. -- **`consumers`**: Counts how many other modules or pallets rely on this account’s existence. The account cannot be removed from the chain (reaped) until this count reaches zero. -- **`providers`**: Tracks how many modules permit this account’s existence. An account can only be reaped once both `providers` and `sufficients` are zero. -- **`sufficients`**: Represents the number of modules that allow the account to exist for internal purposes, independent of any other modules. -- **`AccountData`**: A flexible data structure that can be customized in the runtime configuration, usually containing balances or other user-specific data. +### eth_gasPrice -This structure helps manage an account's state and prevents its premature removal while it is still referenced by other on-chain data or modules. The [`AccountInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.AccountInfo.html){target=\_blank} structure can vary as long as it satisfies the trait bounds defined by the `AccountData` associated type in the [`frame-system::pallet::Config`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/trait.Config.html){target=\_blank} trait. +Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. -### Account Reference Counters +**Parameters**: -Polkadot SDK uses reference counters to track an account’s dependencies across different runtime modules. These counters ensure that accounts remain active while data is associated with them. +None. -The reference counters include: +**Example**: -- **`consumers`**: Prevents account removal while other pallets still rely on the account. -- **`providers`**: Ensures an account is active before other pallets store data related to it. -- **`sufficients`**: Indicates the account’s independence, ensuring it can exist even without a native token balance, such as when holding sufficient alternative assets. +```bash title="eth_gasPrice" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_gasPrice", + "params":[], + "id":1 +}' +``` -#### Providers Reference Counters +--- -The `providers` counter ensures that an account is ready to be depended upon by other runtime modules. For example, it is incremented when an account has a balance above the existential deposit, which marks the account as active. +### eth_getBalance -The system requires this reference counter to be greater than zero for the `consumers` counter to be incremented, ensuring the account is stable before any dependencies are added. +Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. -#### Consumers Reference Counters +**Parameters**: -The `consumers` counter ensures that the account cannot be reaped until all references to it across the runtime have been removed. This check prevents the accidental deletion of accounts that still have active on-chain data. +- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -It is the user’s responsibility to clear out any data from other runtime modules if they wish to remove their account and reclaim their existential deposit. +**Example**: -#### Sufficients Reference Counter +```bash title="eth_getBalance" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBalance", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -The `sufficients` counter tracks accounts that can exist independently without relying on a native account balance. This is useful for accounts holding other types of assets, like tokens, without needing a minimum balance in the native token. +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -For instance, the [Assets pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank}, may increment this counter for an account holding sufficient tokens. +--- -#### Account Deactivation +### eth_getBlockByHash -In Polkadot SDK-based chains, an account is deactivated when its reference counters (such as `providers`, `consumers`, and `sufficient`) reach zero. These counters ensure the account remains active as long as other runtime modules or pallets reference it. +Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. -When all dependencies are cleared and the counters drop to zero, the account becomes deactivated and may be removed from the chain (reaped). This is particularly important in Polkadot SDK-based blockchains, where accounts with balances below the existential deposit threshold are pruned from storage to conserve state resources. +**Parameters**: -Each pallet that references an account has cleanup functions that decrement these counters when the pallet no longer depends on the account. Once these counters reach zero, the account is marked for deactivation. +- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. -#### Updating Counters +**Example**: -The Polkadot SDK provides runtime developers with various methods to manage account lifecycle events, such as deactivation or incrementing reference counters. These methods ensure that accounts cannot be reaped while still in use. +```bash title="eth_getBlockByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockByHash", + "params":["INSERT_BLOCK_HASH", INSERT_BOOLEAN], + "id":1 +}' +``` -The following helper functions manage these counters: +Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values. -- **`inc_consumers()`**: Increments the `consumer` reference counter for an account, signaling that another pallet depends on it. -- **`dec_consumers()`**: Decrements the `consumer` reference counter, signaling that a pallet no longer relies on the account. -- **`inc_providers()`**: Increments the `provider` reference counter, ensuring the account remains active. -- **`dec_providers()`**: Decrements the `provider` reference counter, allowing for account deactivation when no longer in use. -- **`inc_sufficients()`**: Increments the `sufficient` reference counter for accounts that hold sufficient assets. -- **`dec_sufficients()`**: Decrements the `sufficient` reference counter. +--- -To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. +### eth_getBlockByNumber -The `System` pallet offers three query functions to assist developers in tracking account states: +Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. -- **[`can_inc_consumer()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_inc_consumer){target=\_blank}**: Checks if the account can safely increment the consumer reference. -- **[`can_dec_provider()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_dec_provider){target=\_blank}**: Ensures that no consumers exist before allowing the decrement of the provider counter. -- **[`is_provider_required()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.is_provider_required){target=\_blank}**: Verifies whether the account still has any active consumer references. +**Parameters**: -This modular and flexible system of reference counters tightly controls the lifecycle of accounts in Polkadot SDK-based blockchains, preventing the accidental removal or retention of unneeded accounts. You can refer to the [System pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html){target=\_blank} for more details. - +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. -## Account Balance Types +**Example**: -In the Polkadot ecosystem, account balances are categorized into different types based on how the funds are utilized and their availability. These balance types determine the actions that can be performed, such as transferring tokens, paying transaction fees, or participating in governance activities. Understanding these balance types helps developers manage user accounts and implement balance-dependent logic. +```bash title="eth_getBlockByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockByNumber", + "params":["INSERT_BLOCK_VALUE", INSERT_BOOLEAN], + "id":1 +}' +``` -!!! note "A more efficient distribution of account balance types is in development" - Soon, pallets in the Polkadot SDK will implement the [`Fungible` trait](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} (see the [tracking issue](https://github.com/paritytech/polkadot-sdk/issues/226){target=\_blank} for more details). For example, the [`transaction-storage`](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_storage/index.html){target=\_blank} pallet changed the implementation of the [`Currency`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/currency/index.html){target=\_blank} trait (see the [Refactor transaction storage pallet to use fungible traits](https://github.com/paritytech/polkadot-sdk/pull/1800){target=\_blank} PR for further details): +Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values. - ```rust - type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - ``` - - To the [`Fungible`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} trait: +--- - ```rust - type BalanceOf = <::Currency as FnInspect<::AccountId>>::Balance; - ``` - - This update will enable more efficient use of account balances, allowing the free balance to be utilized for on-chain activities such as setting proxies and managing identities. +### eth_getBlockTransactionCountByNumber -### Balance Types +Returns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\_blank}. -The five main balance types are: +**Parameters**: -- **Free balance**: Represents the total tokens available to the account for any on-chain activity, including staking, governance, and voting. However, it may not be fully spendable or transferrable if portions of it are locked or reserved. -- **Locked balance**: Portions of the free balance that cannot be spent or transferred because they are tied up in specific activities like [staking](https://wiki.polkadot.com/learn/learn-staking/#nominating-validators){target=\_blank}, [vesting](https://wiki.polkadot.com/learn/learn-guides-transfers/#vested-transfers-with-the-polkadot-js-ui){target=\_blank}, or participating in [governance](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank}. While the tokens remain part of the free balance, they are non-transferable for the duration of the lock. -- **Reserved balance**: Funds locked by specific system actions, such as setting up an [identity](https://wiki.polkadot.com/learn/learn-identity/){target=\_blank}, creating [proxies](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}, or submitting [deposits for governance proposals](https://wiki.polkadot.com/learn/learn-guides-polkadot-opengov/#claiming-opengov-deposits){target=\_blank}. These tokens are not part of the free balance and cannot be spent unless they are unreserved. -- **Spendable balance**: The portion of the free balance that is available for immediate spending or transfers. It is calculated by subtracting the maximum of locked or reserved amounts from the free balance, ensuring that existential deposit limits are met. -- **Untouchable balance**: Funds that cannot be directly spent or transferred but may still be utilized for on-chain activities, such as governance participation or staking. These tokens are typically tied to certain actions or locked for a specific period. +- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -The spendable balance is calculated as follows: +**Example**: -```text -spendable = free - max(locked - reserved, ED) +```bash title="eth_getBlockTransactionCountByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockTransactionCountByNumber", + "params":["INSERT_BLOCK_VALUE"], + "id":1 +}' ``` -Here, `free`, `locked`, and `reserved` are defined above. The `ED` represents the [existential deposit](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank}, the minimum balance required to keep an account active and prevent it from being reaped. You may find you can't see all balance types when looking at your account via a wallet. Wallet providers often display only spendable, locked, and reserved balances. +Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. + +--- -### Locks +### eth_getBlockTransactionCountByHash -Locks are applied to an account's free balance, preventing that portion from being spent or transferred. Locks are automatically placed when an account participates in specific on-chain activities, such as staking or governance. Although multiple locks may be applied simultaneously, they do not stack. Instead, the largest lock determines the total amount of locked tokens. +Returns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}. -Locks follow these basic rules: +**Parameters**: -- If different locks apply to varying amounts, the largest lock amount takes precedence. -- If multiple locks apply to the same amount, the lock with the longest duration governs when the balance can be unlocked. +- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -#### Locks Example +**Example**: -Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: +```bash title="eth_getBlockTransactionCountByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockTransactionCountByHash", + "params":["INSERT_BLOCK_HASH"], + "id":1 +}' +``` -- 80 DOT is staked with a 28-day lock period. -- 24 DOT is locked for governance with a 1x conviction and a 7-day lock period. -- 4 DOT is locked for governance with a 6x conviction and a 224-day lock period. +Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. -In this case, the total locked amount is 80 DOT because only the largest lock (80 DOT from staking) governs the locked balance. These 80 DOT will be released at different times based on the lock durations. In this example, the 24 DOT locked for governance will be released first since the shortest lock period is seven days. The 80 DOT stake with a 28-day lock period is released next. Now, all that remains locked is the 4 DOT for governance. After 224 days, all 80 DOT (minus the existential deposit) will be free and transferable. +--- -![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) +### eth_getCode -#### Edge Cases for Locks +Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. -In scenarios where multiple convictions and lock periods are active, the lock duration and amount are determined by the longest period and largest amount. For example, if you delegate with different convictions and attempt to undelegate during an active lock period, the lock may be extended for the full amount of tokens. For a detailed discussion on edge case lock behavior, see this [Stack Exchange post](https://substrate.stackexchange.com/questions/5067/delegating-and-undelegating-during-the-lock-period-extends-it-for-the-initial-am){target=\_blank}. +**Parameters**: -### Balance Types on Polkadot.js +- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). -Polkadot.js provides a user-friendly interface for managing and visualizing various account balances on Polkadot and Kusama networks. When interacting with Polkadot.js, you will encounter multiple balance types that are critical for understanding how your funds are distributed and restricted. This section explains how different balances are displayed in the Polkadot.js UI and what each type represents. +**Example**: -![](/images/reference/parachains/accounts/accounts-02.webp) +```bash title="eth_getCode" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getCode", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -The most common balance types displayed on Polkadot.js are: +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -- **Total balance**: The total number of tokens available in the account. This includes all tokens, whether they are transferable, locked, reserved, or vested. However, the total balance does not always reflect what can be spent immediately. In this example, the total balance is 0.6274 KSM. +--- -- **Transferable balance**: Shows how many tokens are immediately available for transfer. It is calculated by subtracting the locked and reserved balances from the total balance. For example, if an account has a total balance of 0.6274 KSM and a transferable balance of 0.0106 KSM, only the latter amount can be sent or spent freely. +### eth_getLogs -- **Vested balance**: Tokens that allocated to the account but released according to a specific schedule. Vested tokens remain locked and cannot be transferred until fully vested. For example, an account with a vested balance of 0.2500 KSM means that this amount is owned but not yet transferable. +Returns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}. -- **Locked balance**: Tokens that are temporarily restricted from being transferred or spent. These locks typically result from participating in staking, governance, or vested transfers. In Polkadot.js, locked balances do not stack—only the largest lock is applied. For instance, if an account has 0.5500 KSM locked for governance and staking, the locked balance would display 0.5500 KSM, not the sum of all locked amounts. +**Parameters**: -- **Reserved balance**: Refers to tokens locked for specific on-chain actions, such as setting an identity, creating a proxy, or making governance deposits. Reserved tokens are not part of the free balance, but can be freed by performing certain actions. For example, removing an identity would unreserve those funds. +- **`filter` ++"object"++**: The filter object. + - **`fromBlock` ++"string"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + - **`toBlock` ++"string"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + - **`address` ++"string" or "array of strings"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`topics` ++"array of strings"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string or an array of such strings (meaning OR). + - **`blockhash` ++"string"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period. +**Example**: -- **Redeemable balance**: The number of tokens that have completed the unbonding period and are ready to be unlocked and transferred again. For example, if an account has a redeemable balance of 0.1000 KSM, those tokens are now available for spending. +```bash title="eth_getLogs" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getLogs", + "params":[{ + "fromBlock": "latest", + "toBlock": "latest" + }], + "id":1 +}' +``` -- **Democracy balance**: Reflects the number of tokens locked for governance activities, such as voting on referenda. These tokens are locked for the duration of the governance action and are only released after the lock period ends. +--- -By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. +### eth_getStorageAt -## Address Formats +Returns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}. -The SS58 address format is a core component of the Polkadot SDK that enables accounts to be uniquely identified across Polkadot-based networks. This format is a modified version of Bitcoin's Base58Check encoding, specifically designed to accommodate the multi-chain nature of the Polkadot ecosystem. SS58 encoding allows each chain to define its own set of addresses while maintaining compatibility and checksum validation for security. +**Parameters**: -### Basic Format +- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`storageKey` ++"string"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). -SS58 addresses consist of three main components: +**Example**: -```text -base58encode(concat(,
    , )) +```bash title="eth_getStorageAt" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getStorageAt", + "params":["INSERT_ADDRESS", "INSERT_STORAGE_KEY", "INSERT_BLOCK_VALUE"], + "id":1 +}' ``` -- **Address type**: A byte or set of bytes that define the network (or chain) for which the address is intended. This ensures that addresses are unique across different Polkadot SDK-based chains. -- **Address**: The public key of the account encoded as bytes. -- **Checksum**: A hash-based checksum which ensures that addresses are valid and unaltered. The checksum is derived from the concatenated address type and address components, ensuring integrity. +Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. -The encoding process transforms the concatenated components into a Base58 string, providing a compact and human-readable format that avoids easily confused characters (e.g., zero '0', capital 'O', lowercase 'l'). This encoding function ([`encode`](https://docs.rs/bs58/latest/bs58/fn.encode.html){target=\_blank}) is implemented exactly as defined in Bitcoin and IPFS specifications, using the same alphabet as both implementations. +--- -For more details about the SS58 address format implementation, see the [`Ss58Codec`](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Ss58Codec.html){target=\_blank} trait in the Rust Docs. +### eth_getTransactionCount -### Address Type +Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}. -The address type defines how an address is interpreted and to which network it belongs. Polkadot SDK uses different prefixes to distinguish between various chains and address formats: +**Parameters**: -- **Address types `0-63`**: Simple addresses, commonly used for network identifiers. -- **Address types `64-127`**: Full addresses that support a wider range of network identifiers. -- **Address types `128-255`**: Reserved for future address format extensions. +- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). -For example, Polkadot’s main network uses an address type of 0, while Kusama uses 2. This ensures that addresses can be used without confusion between networks. +**Example**: -The address type is always encoded as part of the SS58 address, making it easy to quickly identify the network. Refer to the [SS58 registry](https://github.com/paritytech/ss58-registry){target=\_blank} for the canonical listing of all address type identifiers and how they map to Polkadot SDK-based networks. +```bash title="eth_getTransactionCount" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionCount", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -### Address Length +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -SS58 addresses can have different lengths depending on the specific format. Address lengths range from as short as 3 to 35 bytes, depending on the complexity of the address and network requirements. This flexibility allows SS58 addresses to adapt to different chains while providing a secure encoding mechanism. +--- -| Total | Type | Raw account | Checksum | -|-------|------|-------------|----------| -| 3 | 1 | 1 | 1 | -| 4 | 1 | 2 | 1 | -| 5 | 1 | 2 | 2 | -| 6 | 1 | 4 | 1 | -| 7 | 1 | 4 | 2 | -| 8 | 1 | 4 | 3 | -| 9 | 1 | 4 | 4 | -| 10 | 1 | 8 | 1 | -| 11 | 1 | 8 | 2 | -| 12 | 1 | 8 | 3 | -| 13 | 1 | 8 | 4 | -| 14 | 1 | 8 | 5 | -| 15 | 1 | 8 | 6 | -| 16 | 1 | 8 | 7 | -| 17 | 1 | 8 | 8 | -| 35 | 1 | 32 | 2 | +### eth_getTransactionByHash -SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. +Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. -### Checksum Types +**Parameters**: -A checksum is applied to validate SS58 addresses. Polkadot SDK uses a Blake2b-512 hash function to calculate the checksum, which is appended to the address before encoding. The checksum length can vary depending on the address format (e.g., 1-byte, 2-byte, or longer), providing varying levels of validation strength. +- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. +**Example**: -### Validating Addresses +```bash title="eth_getTransactionByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByHash", + "params":["INSERT_TRANSACTION_HASH"], + "id":1 +}' +``` -SS58 addresses can be validated using the subkey command-line interface or the Polkadot.js API. These tools help ensure an address is correctly formatted and valid for the intended network. The following sections will provide an overview of how validation works with these tools. +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. -#### Using Subkey +--- -[Subkey](https://paritytech.github.io/polkadot-sdk/master/subkey/index.html){target=\_blank} is a CLI tool provided by Polkadot SDK for generating and managing keys. It can inspect and validate SS58 addresses. +### eth_getTransactionByBlockNumberAndIndex -The `inspect` command gets a public key and an SS58 address from the provided secret URI. The basic syntax for the `subkey inspect` command is: +Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. -```bash -subkey inspect [flags] [options] uri -``` +**Parameters**: -For the `uri` command-line argument, you can specify the secret seed phrase, a hex-encoded private key, or an SS58 address. If the input is a valid address, the `subkey` program displays the corresponding hex-encoded public key, account identifier, and SS58 addresses. +- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: +**Example**: -```bash -subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" +```bash title="eth_getTransactionByBlockNumberAndIndex" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByBlockNumberAndIndex", + "params":["INSERT_BLOCK_VALUE", "INSERT_TRANSACTION_INDEX"], + "id":1 +}' ``` -The command displays output similar to the following: +Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. -
    - subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" - Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account: - Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849 - Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR - Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - SS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR -
    +--- -The `subkey` program assumes an address is based on a public/private key pair. If you inspect an address, the command returns the 32-byte account identifier. +### eth_getTransactionByBlockHashAndIndex -However, not all addresses in Polkadot SDK-based networks are based on keys. +Returns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}. -Depending on the command-line options you specify and the input you provided, the command output might also display the network for which the address has been encoded. For example: +**Parameters**: -```bash -subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" -``` +- **`blockHash` ++"string"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -The command displays output similar to the following: +**Example**: -
    - subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" - Public Key URI `12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU` is account: - Network ID/Version: polkadot - Public key (hex): 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Account ID: 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Public key (SS58): 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU - SS58 Address: 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU -
    +```bash title="eth_getTransactionByBlockHashAndIndex" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByBlockHashAndIndex", + "params":["INSERT_BLOCK_HASH", "INSERT_TRANSACTION_INDEX"], + "id":1 +}' +``` -#### Using Polkadot.js API +Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. -To verify an address in JavaScript or TypeScript projects, you can use the functions built into the [Polkadot.js API](https://polkadot.js.org/docs/){target=\_blank}. For example: +--- -```js -// Import Polkadot.js API dependencies -const { decodeAddress, encodeAddress } = require('@polkadot/keyring'); -const { hexToU8a, isHex } = require('@polkadot/util'); +### eth_getTransactionReceipt -// Specify an address to test. -const address = 'INSERT_ADDRESS_TO_TEST'; +Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. -// Check address -const isValidSubstrateAddress = () => { - try { - encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); +**Parameters**: - return true; - } catch (error) { - return false; - } -}; +- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -// Query result -const isValid = isValidSubstrateAddress(); -console.log(isValid); +**Example**: +```bash title="eth_getTransactionReceipt" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionReceipt", + "params":["INSERT_TRANSACTION_HASH"], + "id":1 +}' ``` -If the function returns `true`, the specified address is a valid address. +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. + +--- + +### eth_maxPriorityFeePerGas + +Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. -#### Other SS58 Implementations +**Parameters**: -Support for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries. +None. -- **Crystal**: [`wyhaines/base58.cr`](https://github.com/wyhaines/base58.cr){target=\_blank} -- **Go**: [`itering/subscan-plugin`](https://github.com/itering/subscan-plugin){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **TypeScript**: [`subsquid/squid-sdk`](https://github.com/subsquid/squid-sdk){target=\_blank} +**Example**: +```bash title="eth_maxPriorityFeePerGas" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_maxPriorityFeePerGas", + "params":[], + "id":1 +}' +``` --- -Page Title: Proof of Stake Consensus +### eth_sendRawTransaction + +Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/pos-consensus/ -- Summary: Explore Polkadot's consensus protocols for secure, scalable, and decentralized network operation, including NPoS, BABE, GRANDPA, and BEEFY. +**Parameters**: -# Proof of Stake Consensus +- **`callData` ++"string"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -## Introduction +**Example**: -Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank} model and a combination of advanced consensus mechanisms to ensure efficient block production and strong finality guarantees. This combination enables the Polkadot network to scale while maintaining security and decentralization. +```bash title="eth_sendRawTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_sendRawTransaction", + "params":["INSERT_CALL_DATA"], + "id":1 +}' +``` -## Nominated Proof of Stake +Ensure to replace the `INSERT_CALL_DATA` with the proper values. -Polkadot uses Nominated Proof of Stake (NPoS) to select the validator set and secure the network. This model is designed to maximize decentralization and security by balancing the roles of [validators](https://wiki.polkadot.com/learn/learn-validator/){target=\_blank} and [nominators](https://wiki.polkadot.com/learn/learn-nominator/){target=\_blank}. +--- -- **Validators**: Play a key role in maintaining the network's integrity. They produce new blocks, validate parachain blocks, and ensure the finality of transactions across the relay chain. -- **Nominators**: Support the network by selecting validators to back with their stake. This mechanism allows users who don't want to run a validator node to still participate in securing the network and earn rewards based on the validators they support. +### eth_sendTransaction -In Polkadot's NPoS system, nominators can delegate their tokens to trusted validators, giving them voting power in selecting validators while spreading security responsibilities across the network. +Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. -## Hybrid Consensus +**Parameters**: -Polkadot employs a hybrid consensus model that combines two key protocols: a finality gadget called [GRANDPA](#finality-gadget-grandpa) and a block production mechanism known as [BABE](#block-production-babe). This hybrid approach enables the network to benefit from both rapid block production and provable finality, ensuring security and performance. +- **`transaction` ++"object"++**: The transaction object. + - **`from` ++"string"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`to` ++"string"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`data` ++"string"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`nonce` ++"string"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -The hybrid consensus model has some key advantages: +**Example**: -- **Probabilistic finality**: With BABE constantly producing new blocks, Polkadot ensures that the network continues to make progress, even when a final decision has not yet been reached on which chain is the true canonical chain. +```bash title="eth_sendTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_sendTransaction", + "params":[{ + "from": "INSERT_SENDER_ADDRESS", + "to": "INSERT_RECIPIENT_ADDRESS", + "gas": "INSERT_GAS_LIMIT", + "gasPrice": "INSERT_GAS_PRICE", + "value": "INSERT_VALUE", + "input": "INSERT_INPUT_DATA", + "nonce": "INSERT_NONCE" + }], + "id":1 +}' +``` -- **Provable finality**: GRANDPA guarantees that once a block is finalized, it can never be reverted, ensuring that all network participants agree on the finalized chain. +Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values. -By using separate protocols for block production and finality, Polkadot can achieve rapid block creation and strong guarantees of finality while avoiding the typical trade-offs seen in traditional consensus mechanisms. +--- -## Block Production - BABE +### eth_syncing -Blind Assignment for Blockchain Extension (BABE) is Polkadot's block production mechanism, working with GRANDPA to ensure blocks are produced consistently across the network. As validators participate in BABE, they are assigned block production slots through a randomness-based lottery system. This helps determine which validator is responsible for producing a block at a given time. BABE shares similarities with [Ouroboros Praos](https://eprint.iacr.org/2017/573.pdf){target=\_blank} but differs in key aspects like chain selection rules and slot timing. +Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. -Key features of BABE include: +**Parameters**: -- **Epochs and slots**: BABE operates in phases called epochs, each of which is divided into slots (around 6 seconds per slot). Validators are assigned slots at the beginning of each epoch based on stake and randomness. +None. -- **Randomized block production**: Validators enter a lottery to determine which will produce a block in a specific slot. This randomness is sourced from the relay chain's [randomness cycle](/reference/parachains/randomness/){target=\_blank}. +**Example**: -- **Multiple block producers per slot**: In some cases, more than one validator might win the lottery for the same slot, resulting in multiple blocks being produced. These blocks are broadcasted, and the network's fork choice rule helps decide which chain to follow. +```bash title="eth_syncing" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_syncing", + "params":[], + "id":1 +}' +``` -- **Handling empty slots**: If no validators win the lottery for a slot, a secondary selection algorithm ensures that a block is still produced. Validators selected through this method always produce a block, ensuring no slots are skipped. +--- -BABE's combination of randomness and slot allocation creates a secure, decentralized system for consistent block production while also allowing for fork resolution when multiple validators produce blocks for the same slot. +### net_listening -### Validator Participation +Returns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\_blank}. -In BABE, validators participate in a lottery for every slot to determine whether they are responsible for producing a block during that slot. This process's randomness ensures a decentralized and unpredictable block production mechanism. +**Parameters**: -There are two lottery outcomes for any given slot that initiate additional processes: +None. -- **Multiple validators in a slot**: Due to the randomness, multiple validators can be selected to produce a block for the same slot. When this happens, each validator produces a block and broadcasts it to the network resulting in a race condition. The network's topology and latency then determine which block reaches the majority of nodes first. BABE allows both chains to continue building until the finalization process resolves which one becomes canonical. The [Fork Choice](#fork-choice) rule is then used to decide which chain the network should follow. +**Example**: -- **No validators in a slot**: On occasions when no validator is selected by the lottery, a [secondary validator selection algorithm](https://spec.polkadot.network/sect-block-production#defn-babe-secondary-slots){target=\_blank} steps in. This backup ensures that a block is still produced, preventing skipped slots. However, if the primary block produced by a verifiable random function [(VRF)-selected](/reference/parachains/randomness/#vrf){target=\_blank} validator exists for that slot, the secondary block will be ignored. As a result, every slot will have either a primary or a secondary block. +```bash title="net_listening" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_listening", + "params":[], + "id":1 +}' +``` -This design ensures continuous block production, even in cases of multiple competing validators or an absence of selected validators. +--- -### Additional Resources +### net_peerCount -For further technical insights about BABE, including cryptographic details and formal proofs, see the [BABE paper](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank} from Web3 Foundation. +Returns the number of peers currently connected to the client. -For BABE technical definitions, constants, and formulas, see the [Block Production Lottery](https://spec.polkadot.network/sect-block-production#sect-block-production-lottery){target=\_blank} section of the Polkadot Protocol Specification. +**Parameters**: -## Finality Gadget - GRANDPA +None. -GRANDPA (GHOST-based Recursive ANcestor Deriving Prefix Agreement) serves as the finality gadget for Polkadot's relay chain. Operating alongside the BABE block production mechanism, it ensures provable finality, giving participants confidence that blocks finalized by GRANDPA cannot be reverted. +**Example**: -Key features of GRANDPA include: +```bash title="net_peerCount" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_peerCount", + "params":[], + "id":1 +}' +``` -- **Independent finality service**: GRANDPA runs separately from the block production process, operating in parallel to ensure seamless finalization. -- **Chain-based finalization**: Instead of finalizing one block at a time, GRANDPA finalizes entire chains, speeding up the process significantly. -- **Batch finalization**: Can finalize multiple blocks in a single round, enhancing efficiency and minimizing delays in the network. -- **Partial synchrony tolerance**: GRANDPA works effectively in a partially synchronous network environment, managing both asynchronous and synchronous conditions. -- **Byzantine fault tolerance**: Can handle up to 1/5 Byzantine (malicious) nodes, ensuring the system remains secure even when faced with adversarial behavior. +--- -??? note "What is GHOST?" - [GHOST (Greedy Heaviest-Observed Subtree)](https://eprint.iacr.org/2018/104.pdf){target=\blank} is a consensus protocol used in blockchain networks to select the heaviest branch in a block tree. Unlike traditional longest-chain rules, GHOST can more efficiently handle high block production rates by considering the weight of subtrees rather than just the chain length. +### net_version -### Probabilistic vs. Provable Finality +Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. -In traditional Proof of Work (PoW) blockchains, finality is probabilistic. As blocks are added to the chain, the probability that a block is final increases, but it can never be guaranteed. Eventual consensus means that all nodes will agree on a single version of the blockchain over time, but this process can be unpredictable and slow. +**Parameters**: -Conversely, GRANDPA provides provable finality, which means that once a block is finalized, it is irreversible. By using Byzantine fault-tolerant agreements, GRANDPA finalizes blocks more efficiently and securely than probabilistic mechanisms like Nakamoto consensus. Like Ethereum's Casper the Friendly Finality Gadget (FFG), GRANDPA ensures that finalized blocks cannot be reverted, offering stronger consensus guarantees. +None. -### Additional Resources +**Example**: -For technical insights, including formal proofs and detailed algorithms, see the [GRANDPA paper](https://github.com/w3f/consensus/blob/master/pdf/grandpa.pdf){target=\_blank} from Web3 Foundation. +```bash title="net_version" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_version", + "params":[], + "id":1 +}' +``` -For a deeper look at the code behind GRANDPA, see the following GitHub repositories: +--- -- [GRANDPA Rust implementation](https://github.com/paritytech/finality-grandpa){target=\_blank} -- [GRANDPA Pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/grandpa/src/lib.rs){target=\_blank} +### system_health -## Fork Choice +Returns information about the health of the system. -The fork choice of the relay chain combines BABE and GRANDPA: +**Parameters**: -1. BABE must always build on the chain that GRANDPA has finalized. -2. When there are forks after the finalized head, BABE builds on the chain with the most primary blocks to provide probabilistic finality. +None. -![Fork choice diagram](/images/reference/polkadot-hub/consensus-and-security/pos-consensus/consensus-protocols-01.webp) +**Example**: -In the preceding diagram, finalized blocks are black, and non-finalized blocks are yellow. Primary blocks are labeled '1', and secondary blocks are labeled '2.' The topmost chain is the longest chain originating from the last finalized block, but it is not selected because it only has one primary block at the time of evaluation. In comparison, the one below it originates from the last finalized block and has three primary blocks. +```bash title="system_health" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"system_health", + "params":[], + "id":1 +}' +``` -### Additional Resources +--- -To learn more about how BABE and GRANDPA work together to produce and finalize blocks on Kusama, see this [Block Production and Finalization in Polkadot](https://youtu.be/FiEAnVECa8c){target=\_blank} talk from Web3 Foundation's Bill Laboon. +### web3_clientVersion -For an in-depth academic discussion about Polkadot's hybrid consensus model, see this [Block Production and Finalization in Polkadot: Understanding the BABE and GRANDPA Protocols](https://www.youtube.com/watch?v=1CuTSluL7v4&t=4s){target=\_blank} MIT Cryptoeconomic Systems 2020 talk by Web3 Foundation's Bill Laboon. +Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. -## Bridging - BEEFY +**Parameters**: -Bridge Efficiency Enabling Finality Yielder (BEEFY) is a specialized protocol that extends the finality guarantees provided by GRANDPA. It is specifically designed to facilitate efficient bridging between Polkadot relay chains (such as Polkadot and Kusama) and external blockchains like Ethereum. While GRANDPA is well-suited for finalizing blocks within Polkadot, it has limitations when bridging external chains that weren't built with Polkadot's interoperability features in mind. BEEFY addresses these limitations by ensuring other networks can efficiently verify finality proofs. +None. -Key features of BEEFY include: +**Example**: -- **Efficient finality proof verification**: BEEFY enables external networks to easily verify Polkadot finality proofs, ensuring seamless communication between chains. -- **Merkle Mountain Ranges (MMR)**: This data structure is used to efficiently store and transmit proofs between chains, optimizing data storage and reducing transmission overhead. -- **ECDSA signature schemes**: BEEFY uses ECDSA signatures, which are widely supported on Ethereum and other EVM-based chains, making integration with these ecosystems smoother. -- **Light client optimization**: BEEFY reduces the computational burden on light clients by allowing them to check for a super-majority of validator votes rather than needing to process all validator signatures, improving performance. +```bash title="web3_clientVersion" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"web3_clientVersion", + "params":[], + "id":1 +}' +``` -### Additional Resources +--- -For BEEFY technical definitions, constants, and formulas, see the [Bridge design (BEEFY)](https://spec.polkadot.network/sect-finality#sect-grandpa-beefy){target=\_blank} section of the Polkadot Protocol Specification. +### debug_traceBlockByNumber +Traces a block's execution by its number and returns a detailed execution trace for each transaction. ---- +**Parameters**: -Page Title: Randomness +- **`blockValue` ++"string"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`options` ++"object"++**: (Optional) An object containing tracer options. + - **`tracer` ++"string"++**: The name of the tracer to use (e.g., `"callTracer"`, `"opTracer"`). + - Other tracer-specific options may be supported. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/randomness/ -- Summary: Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. +**Example**: -# Randomness +```bash title="debug_traceBlockByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceBlockByNumber", + "params":["INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "id":1 +}' +``` -## Introduction +Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. -Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as "random" numbers on a computer are actually pseudo-random. These numbers rely on an initial "seed," which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\_blank}, [heart rates](https://mdpi.altmetric.com/details/47574324){target=\_blank}, or even [lava lamps](https://en.wikipedia.org/wiki/Lavarand){target=\_blank}. While this may seem random, given the same "seed," the same sequence of numbers will always be generated. +--- -In a global blockchain network, relying on real-world entropy for randomness isn’t feasible because these inputs vary by time and location. If nodes use different inputs, blockchains can fork. Hence, real-world randomness isn't suitable for use as a seed in blockchain systems. +### debug_traceTransaction -Currently, two primary methods for generating randomness in blockchains are used: [`RANDAO`](#randao) and [`VRF`](#vrf) (Verifiable Random Function). Polkadot adopts the `VRF` approach for its randomness. +Traces the execution of a single transaction by its hash and returns a detailed execution trace. -## VRF +**Parameters**: -A Verifiable Random Function (VRF) is a cryptographic function that generates a random number and proof that ensures the submitter produced the number. This proof allows anyone to verify the validity of the random number. +- **`transactionHash` ++"string"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). -Polkadot's VRF is similar to the one used in [**Ouroboros Praos**](https://eprint.iacr.org/2017/573.pdf){target=\_blank}, which secures randomness for block production in systems like [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe){target=\_blank} (Polkadot’s block production mechanism). +**Example**: -The key difference is that Polkadot's VRF doesn’t rely on a central clock—avoiding the issue of whose clock to trust. Instead, it uses its own past results and slot numbers to simulate time and determine future outcomes. +```bash title="debug_traceTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceTransaction", + "params":["INSERT_TRANSACTION_HASH", {"tracer": "callTracer"}], + "id":1 +}' +``` -### How VRF Works +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. -Slots on Polkadot are discrete units of time, each lasting six seconds, and can potentially hold a block. Multiple slots form an epoch, with 2400 slots making up one four-hour epoch. +--- -In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: +### debug_traceCall -1. A "secret key," unique to each validator, is used for the die roll. -2. An epoch randomness value, derived from the hash of VRF outputs from blocks two epochs ago (N-2), so past randomness influences the current epoch (N). -3. The current slot number. +Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. -This process helps maintain fair randomness across the network. +**Parameters**: -Here is a graphical representation: +- **`transaction` ++"object"++**: The transaction call object, similar to `eth_call` parameters. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). -![](/images/reference/parachains/randomness/randomness-01.webp) +**Example**: -The VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). +```bash title="debug_traceCall" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceCall", + "params":[{ + "from": "INSERT_SENDER_ADDRESS", + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_CALL" + }, "INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "id":1 +}' +``` -The result is checked by the validator against a protocol threshold. If it's below the threshold, the validator becomes a candidate for block production in that slot. +Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value. -The validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`. +--- -So, VRF can be expressed like: +## Response Format -`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)` +All responses follow the standard JSON-RPC 2.0 format: -Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": ... // The return value varies by method +} +``` -After executing the VRF, the `RESULT` is compared to a protocol-defined `THRESHOLD`. If the `RESULT` is below the `THRESHOLD`, the validator becomes a valid candidate to propose a block for that slot. Otherwise, the validator skips the slot. +## Error Handling -As a result, there may be multiple validators eligible to propose a block for a slot. In this case, the block accepted by other nodes will prevail, provided it is on the chain with the latest finalized block as determined by the GRANDPA finality gadget. It's also possible for no block producers to be available for a slot, in which case the AURA consensus takes over. AURA is a fallback mechanism that randomly selects a validator to produce a block, running in parallel with BABE and only stepping in when no block producers exist for a slot. Otherwise, it remains inactive. +If an error occurs, the response will include an error object: -Because validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32000, + "message": "Error message here" + } +} +``` -To verify resolution of this issue and that Polkadot block times remain near constant-time, see the [PoS Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} page of this documentation. -## RANDAO +--- -An alternative on-chain randomness method is Ethereum's RANDAO, where validators perform thousands of hashes on a seed and publish the final hash during a round. The collective input from all validators forms the random number, and as long as one honest validator participates, the randomness is secure. +Page Title: Overview of FRAME -To enhance security, RANDAO can optionally be combined with a Verifiable Delay Function (VDF), ensuring that randomness can't be predicted or manipulated during computation. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md +- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ +- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. -For more information about RANDAO, see the [Randomness - RANDAO](https://eth2book.info/capella/part2/building_blocks/randomness/){target=\_blank} section of the Upgrading Ethereum documentation. +# Customize Your Runtime -## VDFs +## Introduction -Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. +A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. -They produce a unique result that can be quickly verified publicly. When combined with RANDAO, feeding RANDAO's output into a VDF introduces a delay that nullifies an attacker's chance to influence the randomness. +This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. -However, VDF likely requires specialized ASIC devices to run separately from standard nodes. +## Understanding Your Runtime -!!!warning - While only one is needed to secure the system, and they will be open-source and inexpensive, running VDF devices involves significant costs without direct incentives, adding friction for blockchain users. +The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. -## Additional Resources +Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. -For more information about the reasoning for choices made along with proofs, see Polkadot's research on blockchain randomness and sortition in the [Block production](https://research.web3.foundation/Polkadot/protocols/block-production){target=\_blank} entry of the Polkadot Wiki. +## Runtime Architecture -For a discussion with Web3 Foundation researchers about when and under what conditions Polkadot's randomness can be utilized, see the [Discussion on Randomness used in Polkadot](https://github.com/use-ink/ink/issues/57){target=\_blank} issue on GitHub. +The following diagram shows how FRAME components work together to form your runtime: +![](/images/parachains/customize-runtime/index/frame-overview-01.webp) ---- +The main components are: -Page Title: Register a Local Asset +- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. +- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. +- **`frame_system`**: Provides core runtime primitives and storage. +- **`frame_support`**: Utilities and macros that simplify pallet development. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md -- Canonical (HTML): https://docs.polkadot.com/chain-interactions/token-operations/register-local-asset/ -- Summary: Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. +## Building Blocks: Pallets -# Register a Local Asset on Asset Hub +[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. -## Introduction +A pallet can implement virtually any blockchain feature you need: -As detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation. +- Expose new transactions that users can submit. +- Store data on-chain. +- Enforce business rules and validation logic. +- Emit events to notify users of state changes. +- Handle errors gracefully. -This guide will take you through the steps of registering a local asset on the Asset Hub parachain. +### Pre-Built Pallets vs. Custom Pallets -## Prerequisites +FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. -Before you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and a funded wallet with DOT or KSM. +However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. -- For Polkadot Asset Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata. -- For Kusama Asset Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata. +### Pallet Structure -You need to ensure that your Asset Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees. +FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. -## Steps to Register a Local Asset +A typical pallet looks like this: -To register a local asset on the Asset Hub parachain, follow these steps: +```rust +pub use pallet::*; -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; - - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`. - - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider. + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); -2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. + #[pallet::config] // snip + #[pallet::event] // snip + #[pallet::error] // snip + #[pallet::storage] // snip + #[pallet::call] // snip +} +``` - ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) +Every pallet can implement these core macros: -3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column. +- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. +- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. +- **`#[pallet::config]`**: Defines configuration and associated types. +- **`#[pallet::event]`**: Defines events emitted by your pallet. +- **`#[pallet::error]`**: Defines error types your pallet can return. +- **`#[pallet::storage]`**: Defines on-chain storage items. +- **`#[pallet::call]`**: Defines dispatchable functions (transactions). - ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) +For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. -4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. +## How Runtime Customization Works - ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) +Customizing your runtime typically follows these patterns: -5. Fill in the required fields in the **Create Asset** form: +**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. - 1. **creator account**: The account to be used for creating this asset and setting up the initial metadata. - 2. **asset name**: The descriptive name of the asset you are registering. - 3. **asset symbol**: The symbol that will be used to represent the asset. - 4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface. - 5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested. - 6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id. - 7. Click on the **Next** button. - - ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp) +**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. -6. Choose the accounts for the roles listed below: +**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. - 1. **admin account**: The account designated for continuous administration of the token. - 2. **issuer account**: The account that will be used for issuing this token. - 3. **freezer account**: The account that will be used for performing token freezing operations. - 4. Click on the **Create** button. +**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. - ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp) +The following diagram illustrates how pallets combine to form a complete runtime: -7. Click on the **Sign and Submit** button to complete the asset registration process. +![](/images/parachains/customize-runtime/index/frame-overview-02.webp) - ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) +## Starting Templates -## Verify Asset Registration +The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. -After completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets){target=\_blank} section of the Polkadot.js Apps interface. +- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. -![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp) +- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. -!!! tip - Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field. +- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. -In this way, you have successfully registered a local asset on the Asset Hub parachain. +- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. -For an in-depth explanation about Asset Hub and its features, see the [Asset Hub](/chain-interactions/token-operations/convert-assets/){target=\_blank} entry in the Polkadot Wiki. +## Key Customization Scenarios -## Test Setup Environment +This section covers the most common customization patterns you'll encounter: -You can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank} documentation. +- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. -To set up a test environment, execute the following command: +- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` +- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. -The above command will spawn a lazy fork of Polkadot Asset Hub with the latest block data from the network. If you need to test Kusama Asset Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. +- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. -An Asset Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet. +- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. --- @@ -6611,507 +3476,115 @@ This page contains a list of all relevant tutorials and guides to help you get s | Title | Difficulty | Tools | Description | |---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| | [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. | -| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | - -## Port Ethereum DApps - -| Title | Difficulty | Tools | Description | -|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| -| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | - - ---- - -Page Title: Smart Contracts Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ -- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. - -# Smart Contracts on Polkadot - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. - -Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. - -These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. - -## Native Smart Contracts - -### Introduction - -Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. - -### Smart Contract Development - -The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. - -Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. - -### Technical Architecture - -PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: - -- Enhanced performance for smart contract execution. -- Improved gas efficiency for complex operations. -- Native compatibility with Polkadot's runtime environment. -- Optimized storage and state management. - -### Development Tools and Resources - -Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: - -- Contract development in Solidity or Rust. -- Support for standard Ethereum development libraries. -- Integration with widely used development environments. -- Access to blockchain explorers and indexing solutions. -- Compatibility with contract monitoring and management tools. - -### Cross-Chain Capabilities - -Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. - -### Use Cases - -Polkadot Hub's smart contract platform is suitable for a wide range of applications: - -- DeFi protocols leveraging _cross-chain capabilities_. -- NFT platforms utilizing Polkadot's native token standards. -- Governance systems integrated with Polkadot's democracy mechanisms. -- Cross-chain bridges and asset management solutions. - -## Other Smart Contract Environments - -Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: - -- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). - -- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. - - -Each environment provides unique advantages based on developer preferences and application requirements. - -## Where to Go Next - -Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. - -Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. - -
    - -- Guide __Libraries__ - - --- - - Explore essential libraries to optimize smart contract development and interaction. - - [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) - -- Guide __Dev Environments__ - - --- - - Set up your development environment for seamless contract deployment and testing. - - [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) - -
    - - ---- - -Page Title: Technical Reference Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md -- Canonical (HTML): https://docs.polkadot.com/reference/ -- Summary: Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. - -## Introduction - -The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need. - -Polkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\_blank} to the [governance](/reference/glossary#governance){target=\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants. - -This guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem. - -## Polkadot Hub - -[Polkadot Hub](/reference/polkadot-hub/){target=\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain. - -The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: - -- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications. -- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem. -- **Staking**: Participate in network security and earn rewards by staking DOT. -- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov. -- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities. -- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem. -- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations. - -## Parachains - -[Parachains](/reference/parachains/){target=\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers: - -- **Accounts**: Deep dive into account types, storage, and management on parachains. -- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms. -- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus. -- **Chain data**: Explore data structures, storage layouts, and state management. -- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains. -- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility. -- **Networks**: Learn about networking protocols and peer-to-peer communication. -- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\_blank}, the standard for cross-chain communication. -- **Randomness**: Understand how randomness is generated and used in Polkadot chains. -- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. - -## On-Chain Governance - -[On-Chain governance](/reference/governance/){target=\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details: - -- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums. -- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity. -- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance. -- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system. - -## Glossary - -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: - -- Blockchain concepts (blocks, transactions, state) -- Consensus mechanisms (validators, collators, finality) -- Polkadot-specific terms (relay chain, parachain, XCM, FRAME) -- Network components (nodes, runtimes, storage) -- Governance terminology (origins, tracks, referendums) - -## Tools - -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: - -- **Light clients**: Lightweight solutions for interacting with the network without running full nodes. -- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\_blank} and [PAPI](/reference/tools/papi/){target=\_blank} for building applications. -- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\_blank} and other Rust-based libraries for SDK development. -- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\_blank} for Python developers. -- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\_blank}, and [Omninode](/reference/tools/omninode/){target=\_blank} for smart contract and parachain testing. -- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\_blank} for substrate interaction. -- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\_blank} for XCM integration and asset transfers. - -## Where to Go Next - -For detailed exploration of specific areas, proceed to any of the main sections: - -
    - -- Learn **Polkadot Hub** - - --- - - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. - - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) - -- Learn **Parachains** - - --- - - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. - - [:octicons-arrow-right-24: Reference](/reference/parachains/) - -- Learn **On-Chain Governance** - - --- - - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. - - [:octicons-arrow-right-24: Reference](/reference/governance/) - -- Guide **Glossary** - - --- - - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. - - [:octicons-arrow-right-24: Reference](/reference/glossary/) - -- Guide **Tools** - - --- - - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. - - [:octicons-arrow-right-24: Reference](/reference/tools/) - -
    - - ---- - -Page Title: Transactions - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/ -- Summary: Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. - -# Transactions - -## Introduction - -Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions. - -This guide walks you through the different transaction types and how they're formatted, validated, and processed within the Polkadot ecosystem. You'll also learn how to customize transaction formats and construct transactions for FRAME-based runtimes, ensuring a complete understanding of how transactions are built and executed in Polkadot SDK-based chains. - -## What Is a Transaction? - -In the Polkadot SDK, transactions represent operations that modify the chain's state, bundled into blocks for execution. The term extrinsic is often used to refer to any data that originates outside the runtime and is included in the chain. While other blockchain systems typically refer to these operations as "transactions," the Polkadot SDK adopts the broader term "extrinsic" to capture the wide variety of data types that can be added to a block. - -There are three primary types of transactions (extrinsics) in the Polkadot SDK: - -- **Signed transactions**: Signed by the submitting account, often carrying transaction fees. -- **Unsigned transactions**: Submitted without a signature, often requiring custom validation logic. -- **Inherent transactions**: Typically inserted directly into blocks by block authoring nodes, without gossiping between peers. - -Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. - -### Signed Transactions - -Signed transactions require an account's signature and typically involve submitting a request to execute a runtime call. The signature serves as a form of cryptographic proof that the sender has authorized the action, using their private key. These transactions often involve a transaction fee to cover the cost of execution and incentivize block producers. - -Signed transactions are the most common type of transaction and are integral to user-driven actions, such as token transfers. For instance, when you transfer tokens from one account to another, the sending account must sign the transaction to authorize the operation. - -For example, the [`pallet_balances::Call::transfer_allow_death`](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/pallet/struct.Pallet.html#method.transfer_allow_death){target=\_blank} extrinsic in the Balances pallet allows you to transfer tokens. Since your account initiates this transaction, your account key is used to sign it. You'll also be responsible for paying the associated transaction fee, with the option to include an additional tip to incentivize faster inclusion in the block. - -### Unsigned Transactions - -Unsigned transactions do not require a signature or account-specific data from the sender. Unlike signed transactions, they do not come with any form of economic deterrent, such as fees, which makes them susceptible to spam or replay attacks. Custom validation logic must be implemented to mitigate these risks and ensure these transactions are secure. - -Unsigned transactions typically involve scenarios where including a fee or signature is unnecessary or counterproductive. However, due to the absence of fees, they require careful validation to protect the network. For example, [`pallet_im_online::Call::heartbeat`](https://paritytech.github.io/polkadot-sdk/master/pallet_im_online/pallet/struct.Pallet.html#method.heartbeat){target=\_blank} extrinsic allows validators to send a heartbeat signal, indicating they are active. Since only validators can make this call, the logic embedded in the transaction ensures that the sender is a validator, making the need for a signature or fee redundant. - -Unsigned transactions are more resource-intensive than signed ones because custom validation is required, but they play a crucial role in certain operational scenarios, especially when regular user accounts aren't involved. - -### Inherent Transactions - -Inherent transactions are a specialized type of unsigned transaction that is used primarily for block authoring. Unlike signed or other unsigned transactions, inherent transactions are added directly by block producers and are not broadcasted to the network or stored in the transaction queue. They don't require signatures or the usual validation steps and are generally used to insert system-critical data directly into blocks. - -A key example of an inherent transaction is inserting a timestamp into each block. The [`pallet_timestamp::Call::now`](https://paritytech.github.io/polkadot-sdk/master/pallet_timestamp/pallet/struct.Pallet.html#method.now-1){target=\_blank} extrinsic allows block authors to include the current time in the block they are producing. Since the block producer adds this information, there is no need for transaction validation, like signature verification. The validation in this case is done indirectly by the validators, who check whether the timestamp is within an acceptable range before finalizing the block. - -Another example is the [`paras_inherent::Call::enter`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/paras_inherent/pallet/struct.Pallet.html#method.enter){target=\_blank} extrinsic, which enables parachain collator nodes to send validation data to the relay chain. This inherent transaction ensures that the necessary parachain data is included in each block without the overhead of gossiped transactions. - -Inherent transactions serve a critical role in block authoring by allowing important operational data to be added directly to the chain without needing the validation processes required for standard transactions. - -## Transaction Formats - -Understanding the structure of signed and unsigned transactions is crucial for developers building on Polkadot SDK-based chains. Whether you're optimizing transaction processing, customizing formats, or interacting with the transaction pool, knowing the format of extrinsics, Polkadot's term for transactions, is essential. - -### Types of Transaction Formats - -In Polkadot SDK-based chains, extrinsics can fall into three main categories: - -- **Unchecked extrinsics**: Typically used for signed transactions that require validation. They contain a signature and additional data, such as a nonce and information for fee calculation. Unchecked extrinsics are named as such because they require validation checks before being accepted into the transaction pool. -- **Checked extrinsics**: Typically used for inherent extrinsics (unsigned transactions); these don't require signature verification. Instead, they carry information such as where the extrinsic originates and any additional data required for the block authoring process. -- **Opaque extrinsics**: Used when the format of an extrinsic is not yet fully committed or finalized. They are still decodable, but their structure can be flexible depending on the context. - -### Signed Transaction Data Structure - -A signed transaction typically includes the following components: - -- **Signature**: Verifies the authenticity of the transaction sender. -- **Call**: The actual function or method call the transaction is requesting (for example, transferring funds). -- **Nonce**: Tracks the number of prior transactions sent from the account, helping to prevent replay attacks. -- **Tip**: An optional incentive to prioritize the transaction in block inclusion. -- **Additional data**: Includes details such as spec version, block hash, and genesis hash to ensure the transaction is valid within the correct runtime and chain context. - -Here's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime: - -``` code - + + -``` - -Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. - -### Signed Extensions - -Polkadot SDK also provides the concept of [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}, which allow developers to extend extrinsics with additional data or validation logic before they are included in a block. The [`SignedExtension`](https://paritytech.github.io/try-runtime-cli/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} set helps enforce custom rules or protections, such as ensuring the transaction's validity or calculating priority. - -The transaction queue regularly calls signed extensions to verify a transaction's validity before placing it in the ready queue. This safeguard ensures transactions won't fail in a block. Signed extensions are commonly used to enforce validation logic and protect the transaction pool from spam and replay attacks. - -In FRAME, a signed extension can hold any of the following types by default: - -- **[`AccountId`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/types_common/type.AccountId.html){target=\_blank}**: To encode the sender's identity. -- **[`Call`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Call){target=\_blank}**: To encode the pallet call to be dispatched. This data is used to calculate transaction fees. -- **[`AdditionalSigned`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.AdditionalSigned){target=\_blank}**: To handle any additional data to go into the signed payload allowing you to attach any custom logic prior to dispatching a transaction. -- **[`Pre`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Pre){target=\_blank}**: To encode the information that can be passed from before a call is dispatched to after it gets dispatched. - -Signed extensions can enforce checks like: - -- **[`CheckSpecVersion`](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/extensions/check_spec_version.rs.html){target=\_blank}**: Ensures the transaction is compatible with the runtime's current version. -- **[`CheckWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.CheckWeight.html){target=\_blank}**: Calculates the weight (or computational cost) of the transaction, ensuring the block doesn't exceed the maximum allowed weight. - -These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. - -## Transaction Construction - -Building transactions in the Polkadot SDK involves constructing a payload that can be verified, signed, and submitted for inclusion in a block. Each runtime in the Polkadot SDK has its own rules for validating and executing transactions, but there are common patterns for constructing a signed transaction. - -### Construct a Signed Transaction - -A signed transaction in the Polkadot SDK includes various pieces of data to ensure security, prevent replay attacks, and prioritize processing. Here's an overview of how to construct one: - -1. **Construct the unsigned payload**: Gather the necessary information for the call, including: - - - **Pallet index**: Identifies the pallet where the runtime function resides. - - **Function index**: Specifies the particular function to call in the pallet. - - **Parameters**: Any additional arguments required by the function call. - -2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: - - - **Transaction nonce**: Unique identifier to prevent replay attacks. - - **Era information**: Defines how long the transaction is valid before it's dropped from the pool. - - **Block hash**: Ensures the transaction doesn't execute on the wrong chain or fork. - -3. **Sign the payload**: Using the sender's private key, sign the payload to ensure that the transaction can only be executed by the account holder. -4. **Serialize the signed payload**: Once signed, the transaction must be serialized into a binary format, ensuring the data is compact and easy to transmit over the network. -5. **Submit the serialized transaction**: Finally, submit the serialized transaction to the network, where it will enter the transaction pool and wait for processing by an authoring node. - -The following is an example of how a signed transaction might look: - -``` rust -node_runtime::UncheckedExtrinsic::new_signed( - function.clone(), // some call - sp_runtime::AccountId32::from(sender.public()).into(), // some sending account - node_runtime::Signature::Sr25519(signature.clone()), // the account's signature - extra.clone(), // the signed extensions -) -``` - -### Transaction Encoding - -Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: - -- **`[1]`**: Compact encoded length in bytes of the entire transaction. -- **`[2]`**: A u8 containing 1 byte to indicate whether the transaction is signed or unsigned (1 bit) and the encoded transaction version ID (7 bits). -- **`[3]`**: If signed, this field contains an account ID, an SR25519 signature, and some extra data. -- **`[4]`**: Encoded call data, including pallet and function indices and any required arguments. - -This encoded format ensures consistency and efficiency in processing transactions across the network. By adhering to this format, applications can construct valid transactions and pass them to the network for execution. - -To learn more about how compact encoding works using SCALE, see the [SCALE Codec](https://github.com/paritytech/parity-scale-codec){target=\_blank} README on GitHub. - -### Customize Transaction Construction - -Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: +| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | -- **Custom pallets**: You can define new pallets with custom function calls, each with its own parameters and validation logic. -- **Signed extensions**: Developers can implement custom extensions that modify how transactions are prioritized, validated, or included in blocks. +## Port Ethereum DApps -By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. +| Title | Difficulty | Tools | Description | +|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| +| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | -## Lifecycle of a Transaction -In the Polkadot SDK, transactions are often referred to as extrinsics because the data in transactions originates outside of the runtime. These transactions contain data that initiates changes to the chain state. The most common type of extrinsic is a signed transaction, which is cryptographically verified and typically incurs a fee. This section focuses on how signed transactions are processed, validated, and ultimately included in a block. +--- -### Define Transaction Properties +Page Title: Smart Contracts Overview -The Polkadot SDK runtime defines key transaction properties, such as: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ +- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. -- **Transaction validity**: Ensures the transaction meets all runtime requirements. -- **Signed or unsigned**: Identifies whether a transaction needs to be signed by an account. -- **State changes**: Determines how the transaction modifies the state of the chain. +# Smart Contracts on Polkadot -Pallets, which compose the runtime's logic, define the specific transactions that your chain supports. When a user submits a transaction, such as a token transfer, it becomes a signed transaction, verified by the user's account signature. If the account has enough funds to cover fees, the transaction is executed, and the chain's state is updated accordingly. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -### Process on a Block Authoring Node +Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. -In Polkadot SDK-based networks, some nodes are authorized to author blocks. These nodes validate and process transactions. When a transaction is sent to a node that can produce blocks, it undergoes a lifecycle that involves several stages, including validation and execution. Non-authoring nodes gossip the transaction across the network until an authoring node receives it. The following diagram illustrates the lifecycle of a transaction that's submitted to a network and processed by an authoring node. +Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. -![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } +These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. -### Validate and Queue +## Native Smart Contracts -Once a transaction reaches an authoring node, it undergoes an initial validation process to ensure it meets specific conditions defined in the runtime. This validation includes checks for: +### Introduction -- **Correct nonce**: Ensures the transaction is sequentially valid for the account. -- **Sufficient funds**: Confirms the account can cover any associated transaction fees. -- **Signature validity**: Verifies that the sender's signature matches the transaction data. +Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. -After these checks, valid transactions are placed in the transaction pool, where they are queued for inclusion in a block. The transaction pool regularly re-validates queued transactions to ensure they remain valid before being processed. To reach consensus, two-thirds of the nodes must agree on the order of the transactions executed and the resulting state change. Transactions are validated and queued on the local node in a transaction pool to prepare for consensus. +### Smart Contract Development -#### Transaction Pool +The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. -The transaction pool is responsible for managing valid transactions. It ensures that only transactions that pass initial validity checks are queued. Transactions that fail validation, expire, or become invalid for other reasons are removed from the pool. +Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. -The transaction pool organizes transactions into two queues: +### Technical Architecture -- **Ready queue**: Transactions that are valid and ready to be included in a block. -- **Future queue**: Transactions that are not yet valid but could be in the future, such as transactions with a nonce too high for the current state. +PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: -Details on how the transaction pool validates transactions, including fee and signature handling, can be found in the [`validate_transaction`](https://paritytech.github.io/polkadot-sdk/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction){target=\_blank} method. +- Enhanced performance for smart contract execution. +- Improved gas efficiency for complex operations. +- Native compatibility with Polkadot's runtime environment. +- Optimized storage and state management. -#### Invalid Transactions +### Development Tools and Resources -If a transaction is invalid, for example, due to an invalid signature or insufficient funds, it is rejected and won't be added to the block. Invalid transactions might be rejected for reasons such as: +Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: -- The transaction has already been included in a block. -- The transaction's signature does not match the sender. -- The transaction is too large to fit in the current block. +- Contract development in Solidity or Rust. +- Support for standard Ethereum development libraries. +- Integration with widely used development environments. +- Access to blockchain explorers and indexing solutions. +- Compatibility with contract monitoring and management tools. -### Transaction Ordering and Priority +### Cross-Chain Capabilities -When a node is selected as the next block author, it prioritizes transactions based on weight, length, and tip amount. The goal is to fill the block with high-priority transactions without exceeding its maximum size or computational limits. Transactions are ordered as follows: +Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. -- **Inherents first**: Inherent transactions, such as block timestamp updates, are always placed first. -- **Nonce-based ordering**: Transactions from the same account are ordered by their nonce. -- **Fee-based ordering**: Among transactions with the same nonce or priority level, those with higher fees are prioritized. +### Use Cases -### Transaction Execution +Polkadot Hub's smart contract platform is suitable for a wide range of applications: -Once a block author selects transactions from the pool, the transactions are executed in priority order. As each transaction is processed, the state changes are written directly to the chain's storage. It's important to note that these changes are not cached, meaning a failed transaction won't revert earlier state changes, which could leave the block in an inconsistent state. +- DeFi protocols leveraging _cross-chain capabilities_. +- NFT platforms utilizing Polkadot's native token standards. +- Governance systems integrated with Polkadot's democracy mechanisms. +- Cross-chain bridges and asset management solutions. -Events are also written to storage. Runtime logic should not emit an event before performing the associated actions. If the associated transaction fails after the event was emitted, the event will not revert. +## Other Smart Contract Environments -## Transaction Mortality +Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: -Transactions in the network can be configured as either mortal (with expiration) or immortal (without expiration). Every transaction payload contains a block checkpoint (reference block number and hash) and an era/validity period that determines how many blocks after the checkpoint the transaction remains valid. +- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). -When a transaction is submitted, the network validates it against these parameters. If the transaction is not included in a block within the specified validity window, it is automatically removed from the transaction queue. +- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. -- **Mortal transactions**: Have a finite lifespan and will expire after a specified number of blocks. For example, a transaction with a block checkpoint of 1000 and a validity period of 64 blocks will be valid from blocks 1000 to 1064. -- **Immortal transactions**: Never expire and remain valid indefinitely. To create an immortal transaction, set the block checkpoint to 0 (genesis block), use the genesis hash as a reference, and set the validity period to 0. +Each environment provides unique advantages based on developer preferences and application requirements. -However, immortal transactions pose significant security risks through replay attacks. If an account is reaped (balance drops to zero, account removed) and later re-funded, malicious actors can replay old immortal transactions. +## Where to Go Next -The blockchain maintains only a limited number of prior block hashes for reference validation, called `BlockHashCount`. If your validity period exceeds `BlockHashCount`, the effective validity period becomes the minimum of your specified period and the block hash count. +Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. -## Unique Identifiers for Extrinsics +Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. -Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. +
    -Key differences from traditional blockchains: +- Guide __Libraries__ -- Transaction hashes serve only as fingerprints of transaction information. -- Multiple valid transactions can share the same hash. -- Hash uniqueness assumptions lead to serious issues. + --- -For example, when an account is reaped (removed due to insufficient balance) and later recreated, it resets to nonce 0, allowing identical transactions to be valid at different points: + Explore essential libraries to optimize smart contract development and interaction. -| Block | Extrinsic Index | Hash | Origin | Nonce | Call | Result | -|-------|----------------|------|-----------|-------|---------------------|-------------------------------| -| 100 | 0 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Account A reaped | -| 150 | 5 | 0x02 | Account B | 4 | Transfer 7 DOT to A | Account A created (nonce = 0) | -| 200 | 2 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Successful transaction | + [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) -Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. +- Guide __Dev Environments__ -Additional complexity comes from Polkadot SDK's origin abstraction. Origins can represent collectives, governance bodies, or other non-account entities that don't maintain nonces like regular accounts and might dispatch identical calls multiple times with the same hash values. Each execution occurs in different chain states with different results. + --- -The correct way to uniquely identify an extrinsic on a Polkadot SDK-based chain is to use the block ID (height or hash) and the extrinsic index. Since the Polkadot SDK defines blocks as headers plus ordered arrays of extrinsics, the index position within a canonical block provides guaranteed uniqueness. + Set up your development environment for seamless contract deployment and testing. -## Additional Resources + [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) -For a video overview of the lifecycle of transactions and the types of transactions that exist, see the [Transaction lifecycle](https://www.youtube.com/watch?v=3pfM0GOp02c){target=\_blank} seminar from Parity Tech. +
    --- @@ -7219,436 +3692,3 @@ The system maintains precise conversion mechanisms between: - Different resource metrics within the multi-dimensional model. This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. - - ---- - -Page Title: Transactions Weights and Fees - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/ -- Summary: Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. - -# Transactions Weights and Fees - -## Introductions - -When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop the network from producing new blocks. To protect blockchain resources from being drained or overloaded, you need to manage how they are made available and how they are consumed. The resources to be aware of include: - -- Memory usage -- Storage input and output -- Computation -- Transaction and block size -- State database size - -The Polkadot SDK provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource. Two of the most important mechanisms available to block authors are weights and transaction fees. - -[Weights](/reference/glossary/#weight){target=\_blank} manage the time it takes to validate a block and characterize the time it takes to execute the calls in the block's body. By controlling the execution time a block can consume, weights set limits on storage input, output, and computation. - -Some of the weight allowed for a block is consumed as part of the block's initialization and finalization. The weight might also be used to execute mandatory inherent extrinsic calls. To help ensure blocks don’t consume too much execution time and prevent malicious users from overloading the system with unnecessary calls, weights are combined with transaction fees. - -[Transaction fees](/reference/parachains/blocks-transactions-fees/transactions/#transaction-fees){target=\_blank} provide an economic incentive to limit execution time, computation, and the number of calls required to perform operations. Transaction fees are also used to make the blockchain economically sustainable because they are typically applied to transactions initiated by users and deducted before a transaction request is executed. - -## How Fees are Calculated - -The final fee for a transaction is calculated using the following parameters: - -- **`base fee`**: This is the minimum amount a user pays for a transaction. It is declared a base weight in the runtime and converted to a fee using the [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} conversion. -- **`weight fee`**: A fee proportional to the execution time (input and output and computation) that a transaction consumes. -- **`length fee`**: A fee proportional to the encoded length of the transaction. -- **`tip`**: An optional tip to increase the transaction’s priority, giving it a higher chance to be included in the transaction queue. - -The base fee and proportional weight and length fees constitute the inclusion fee. The inclusion fee is the minimum fee that must be available for a transaction to be included in a block. - -```text -inclusion fee = base fee + weight fee + length fee -``` - -Transaction fees are withdrawn before the transaction is executed. After the transaction is executed, the weight can be adjusted to reflect the resources used. If a transaction uses fewer resources than expected, the transaction fee is corrected, and the adjusted transaction fee is deposited. - -## Using the Transaction Payment Pallet - -The [Transaction Payment pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/transaction-payment){target=\_blank} provides the basic logic for calculating the inclusion fee. You can also use the Transaction Payment pallet to: - -- Convert a weight value into a deductible fee based on a currency type using [`Config::WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank}. -- Update the fee for the next block by defining a multiplier based on the chain’s final state at the end of the previous block using [`Config::FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank}. -- Manage the withdrawal, refund, and deposit of transaction fees using [`Config::OnChargeTransaction`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.OnChargeTransaction){target=\_blank}. - -You can learn more about these configuration traits in the [Transaction Payment documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_payment/index.html){target=\_blank}. - -### Understanding the Inclusion Fee - -The formula for calculating the inclusion fee is as follows: - -```text -inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] -``` - -And then, for calculating the final fee: - -```text -final_fee = inclusion_fee + tip -``` - -In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. - -- The `base_fee` derived from the base weight covers inclusion overhead like signature verification. -- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic. -- The `weight_fee` fee is calculated using two parameters: - - The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics. - - The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity. - -To convert the weight to `Currency`, the runtime must define a `WeightToFee` struct that implements a conversion function, [`Convert`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/struct.Pallet.html#method.weight_to_fee){target=\_blank}. - -Note that the extrinsic sender is charged the inclusion fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution. - -### Accounts with an Insufficient Balance - -If an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum existential deposit—then you should ensure the transaction is canceled so that no fee is deducted and the transaction does not begin execution. - -The Polkadot SDK doesn't enforce this rollback behavior. However, this scenario would be rare because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block. - -### Fee Multipliers - -The inclusion fee formula always results in the same fee for the same input. However, weight can be dynamic and—based on how [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} is defined—the final fee can include some degree of variability. -The Transaction Payment pallet provides the [`FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank} configurable parameter to account for this variability. - -The Polkadot network inspires the default update function and implements a targeted adjustment in which a target saturation level of block weight is defined. If the previous block is more saturated, the fees increase slightly. Similarly, if the last block has fewer transactions than the target, fees are decreased by a small amount. For more information about fee multiplier adjustments, see the [Web3 Research Page](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank}. - -## Transactions with Special Requirements - -Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: - -- Bonds are a type of fee that might be returned or slashed after some on-chain event. For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior. -- Deposits are fees that might be returned later. For example, you might require users to pay a deposit to execute an operation that uses storage. The user’s deposit could be returned if a subsequent operation frees up storage. -- Burn operations are used to pay for a transaction based on its internal logic. For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased state size. -- Limits enable you to enforce constant or configurable limits on specific operations. For example, the default [Staking pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/staking){target=\_blank} only allows nominators to nominate 16 validators to limit the complexity of the validator election process. - -It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. - -## Default Weight Annotations - -All dispatchable functions in the Polkadot SDK must specify a weight. The way of doing that is using the annotation-based system that lets you combine fixed values for database read/write weight and/or fixed values based on benchmarks. The most basic example would look like this: - -```rust -#[pallet::weight(100_000)] -fn my_dispatchable() { - // ... -} -``` - -Note that the [`ExtrinsicBaseWeight`](https://crates.parity.io/frame_support/weights/constants/struct.ExtrinsicBaseWeight.html){target=\_blank} is automatically added to the declared weight to account for the costs of simply including an empty extrinsic into a block. - -### Weights and Database Read/Write Operations - -To make weight annotations independent of the deployed database backend, they are defined as a constant and then used in the annotations when expressing database accesses performed by the dispatchable: - -```rust -#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] -fn my_dispatchable() { - // ... -} -``` - -This dispatchable allows one database to read and two to write, in addition to other things that add the additional 20,000. Database access is generally every time a value declared inside the [`#[pallet::storage]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} block is accessed. However, unique accesses are counted because after a value is accessed, it is cached, and reaccessing it does not result in a database operation. That is: - -- Multiple reads of the exact value count as one read. -- Multiple writes of the exact value count as one write. -- Multiple reads of the same value, followed by a write to that value, count as one read and one write. -- A write followed by a read-only counts as one write. - -### Dispatch Classes - -Dispatches are broken into three classes: - -- Normal -- Operational -- Mandatory - -If a dispatch is not defined as `Operational` or `Mandatory` in the weight annotation, the dispatch is identified as `Normal` by default. You can specify that the dispatchable uses another class like this: - -```rust -#[pallet::dispatch((DispatchClass::Operational))] -fn my_dispatchable() { - // ... -} -``` - -This tuple notation also allows you to specify a final argument determining whether the user is charged based on the annotated weight. If you don't specify otherwise, `Pays::Yes` is assumed: - -```rust -#[pallet::dispatch(DispatchClass::Normal, Pays::No)] -fn my_dispatchable() { - // ... -} -``` - -#### Normal Dispatches - -Dispatches in this class represent normal user-triggered transactions. These types of dispatches only consume a portion of a block's total weight limit. For information about the maximum portion of a block that can be consumed for normal dispatches, see [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Normal dispatches are sent to the transaction pool. - -#### Operational Dispatches - -Unlike normal dispatches, which represent the usage of network capabilities, operational dispatches are those that provide network capabilities. Operational dispatches can consume the entire weight limit of a block. They are not bound by the [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Dispatches in this class are given maximum priority and are exempt from paying the [`length_fee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/){target=\_blank}. - -#### Mandatory Dispatches - -Mandatory dispatches are included in a block even if they cause the block to surpass its weight limit. You can only use the mandatory dispatch class for inherent transactions that the block author submits. This dispatch class is intended to represent functions in the block validation process. Because these dispatches are always included in a block regardless of the function weight, the validation process must prevent malicious nodes from abusing the function to craft valid but impossibly heavy blocks. You can typically accomplish this by ensuring that: - -- The operation performed is always light. -- The operation can only be included in a block once. - -To make it more difficult for malicious nodes to abuse mandatory dispatches, they cannot be included in blocks that return errors. This dispatch class serves the assumption that it is better to allow an overweight block to be created than not to allow any block to be created at all. - -### Dynamic Weights - -In addition to purely fixed weights and constants, the weight calculation can consider the input arguments of a dispatchable. The weight should be trivially computable from the input arguments with some basic arithmetic: - -```rust -use frame_support:: { - dispatch:: { - DispatchClass::Normal, - Pays::Yes, - }, - weights::Weight, -}; - -#[pallet::weight(FunctionOf( - |args: (&Vec,)| args.0.len().saturating_mul(10_000), - ) -] -fn handle_users(origin, calls: Vec) { - // Do something per user -} -``` - -## Post Dispatch Weight Correction - -Depending on the execution logic, a dispatchable function might consume less weight than was prescribed pre-dispatch. To correct weight, the function declares a different return type and returns its actual weight: - -```rust -#[pallet::weight(10_000 + 500_000_000)] -fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo { - let was_heavy = do_calculation(input); - - if (was_heavy) { - // None means "no correction" from the weight annotation. - Ok(None.into()) - } else { - // Return the actual weight consumed. - Ok(Some(10_000).into()) - } -} -``` - -## Custom Fees - -You can also define custom fee systems through custom weight functions or inclusion fee functions. - -### Custom Weights - -Instead of using the default weight annotations, you can create a custom weight calculation type using the weights module. The custom weight calculation type must implement the following traits: - -- [`WeighData`](https://crates.parity.io/frame_support/weights/trait.WeighData.html){target=\_blank} to determine the weight of the dispatch. -- [`ClassifyDispatch`](https://crates.parity.io/frame_support/weights/trait.ClassifyDispatch.html){target=\_blank} to determine the class of the dispatch. -- [`PaysFee`](https://crates.parity.io/frame_support/weights/trait.PaysFee.html){target=\_blank} to determine whether the sender of the dispatch pays fees. - -The Polkadot SDK then bundles the output information of the three traits into the [`DispatchInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.DispatchInfo.html){target=\_blank} struct and provides it by implementing the [`GetDispatchInfo`](https://docs.rs/frame-support/latest/frame_support/dispatch/trait.GetDispatchInfo.html){target=\_blank} for all `Call` variants and opaque extrinsic types. This is used internally by the System and Executive modules. - -`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over T, which gets resolved into the tuple of all dispatch arguments except for the origin. The following example illustrates a struct that calculates the weight as `m * len(args)`, where `m` is a given multiplier and args is the concatenated tuple of all dispatch arguments. In this example, the dispatch class is `Operational` if the transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length exceeds 10 bytes. - -```rust -struct LenWeight(u32); -impl WeighData for LenWeight { - fn weigh_data(&self, target: T) -> Weight { - let multiplier = self.0; - let encoded_len = target.encode().len() as u32; - multiplier * encoded_len - } -} - -impl ClassifyDispatch for LenWeight { - fn classify_dispatch(&self, target: T) -> DispatchClass { - let encoded_len = target.encode().len() as u32; - if encoded_len > 100 { - DispatchClass::Operational - } else { - DispatchClass::Normal - } - } -} - -impl PaysFee { - fn pays_fee(&self, target: T) -> Pays { - let encoded_len = target.encode().len() as u32; - if encoded_len > 10 { - Pays::Yes - } else { - Pays::No - } - } -} -``` - -A weight calculator function can also be coerced to the final type of the argument instead of defining it as a vague type that can be encoded. The code would roughly look like this: - -```rust -struct CustomWeight; -impl WeighData<(&u32, &u64)> for CustomWeight { - fn weigh_data(&self, target: (&u32, &u64)) -> Weight { - ... - } -} - -// given a dispatch: -#[pallet::call] -impl, I: 'static> Pallet { - #[pallet::weight(CustomWeight)] - fn foo(a: u32, b: u64) { ... } -} -``` - -In this example, the `CustomWeight` can only be used in conjunction with a dispatch with a particular signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because there aren't any assumptions about ``. - -#### Custom Inclusion Fee - -The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. - -```rust -// Assume this is the balance type -type Balance = u64; - -// Assume we want all the weights to have a `100 + 2 * w` conversion to fees -struct CustomWeightToFee; -impl WeightToFee for CustomWeightToFee { - fn convert(w: Weight) -> Balance { - let a = Balance::from(100); - let b = Balance::from(2); - let w = Balance::from(w); - a + b * w - } -} - -parameter_types! { - pub const ExtrinsicBaseWeight: Weight = 10_000_000; -} - -impl frame_system::Config for Runtime { - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; -} - -parameter_types! { - pub const TransactionByteFee: Balance = 10; -} - -impl transaction_payment::Config { - type TransactionByteFee = TransactionByteFee; - type WeightToFee = CustomWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} - -struct TargetedFeeAdjustment(sp_std::marker::PhantomData); -impl> WeightToFee for TargetedFeeAdjustment { - fn convert(multiplier: Fixed128) -> Fixed128 { - // Don't change anything. Put any fee update info here. - multiplier - } -} -``` - -## Additional Resources - -You now know the weight system, how it affects transaction fee computation, and how to specify weights for your dispatchable calls. The next step is determining the correct weight for your dispatchable operations. You can use Substrate benchmarking functions and frame-benchmarking calls to test your functions with different parameters and empirically determine the proper weight in their worst-case scenarios. - -- [Benchmark](/parachains/customize-runtime/pallet-development/benchmark-pallet/) -- [`SignedExtension`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} -- [Custom weights for the Example pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/examples/basic/src/weights.rs){target=\_blank} -- [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} - - ---- - -Page Title: XCM Tools - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/xcm-tools/ -- Summary: Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. - -# XCM Tools - -## Introduction - -As described in the [Interoperability](/develop/interoperability){target=\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem. - -As XCM is central to enabling communication between blockchains, developers need robust tools to help interact with, build, and test XCM messages. Several XCM tools simplify working with the protocol by providing libraries, frameworks, and utilities that enhance the development process, ensuring that applications built within the Polkadot ecosystem can efficiently use cross-chain functionalities. - -## Popular XCM Tools - -### Moonsong Labs XCM Tools - -[Moonsong Labs XCM Tools](https://github.com/Moonsong-Labs/xcm-tools){target=\_blank} provides a collection of scripts for managing and testing XCM operations between Polkadot SDK-based runtimes. These tools allow performing tasks like asset registration, channel setup, and XCM initialization. Key features include: - -- **Asset registration**: Registers assets, setting units per second (up-front fees), and configuring error (revert) codes. -- **XCM initializer**: Initializes XCM, sets default XCM versions, and configures revert codes for XCM-related precompiles. -- **HRMP manipulator**: Manages HRMP channel actions, including opening, accepting, or closing channels. -- **XCM-Transactor-Info-Setter**: Configures transactor information, including extra weight and fee settings. -- **Decode XCM**: Decodes XCM messages on the relay chain or parachains to help interpret cross-chain communication. - -To get started, clone the repository and install the required dependencies: - -```bash -git clone https://github.com/Moonsong-Labs/xcm-tools && -cd xcm-tools && -yarn install -``` - -For a full overview of each script, visit the [scripts](https://github.com/Moonsong-Labs/xcm-tools/tree/main/scripts){target=\_blank} directory or refer to the [official documentation](https://github.com/Moonsong-Labs/xcm-tools/blob/main/README.md){target=\_blank} on GitHub. - -### ParaSpell - -[ParaSpell](/reference/tools/paraspell/){target=\_blank} is a collection of open-source XCM tools that streamline cross-chain asset transfers and interactions across the Polkadot and Kusama ecosystems. It provides developers with an intuitive interface to build, test, and deploy interoperable dApps, featuring message composition, decoding, and practical utilities for parachain interactions that simplify debugging and cross-chain communication optimization. - -### Astar XCM Tools - -The [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks: - -- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command. -- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments. -- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs. - -To start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\_blank} and compile the xcm-tools package: - -```bash -git clone https://github.com/AstarNetwork/Astar && -cd Astar && -cargo build --release -p xcm-tools -``` - -After compiling, verify the setup with the following command: - -```bash -./target/release/xcm-tools --help -``` -For more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\_blank}. - -### Chopsticks - -The Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\_blank} about XCM. - -### Moonbeam XCM SDK - -The [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank} of the origin or destination assets or which extrinsics are used on which networks. - -The SDK consists of two main packages: - -- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem. -- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum. - -Key features include: - -- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection. -- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems. -- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality. -- **Comprehensive documentation**: Includes usage guides and API references for both packages. - -For detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\_blank}. diff --git a/.ai/categories/reference.md b/.ai/categories/reference.md index db1273b99..825037625 100644 --- a/.ai/categories/reference.md +++ b/.ai/categories/reference.md @@ -1,374 +1,6 @@ Begin New Bundle: Reference ---- - -Page Title: Glossary - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md -- Canonical (HTML): https://docs.polkadot.com/reference/glossary/ -- Summary: Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. - -# Glossary - -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. - -Additional glossaries from around the ecosystem you might find helpful: - -- [Polkadot Wiki Glossary](https://wiki.polkadot.com/general/glossary){target=\_blank} -- [Polkadot SDK Glossary](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/glossary/index.html){target=\_blank} - -## Authority - -The role in a blockchain that can participate in consensus mechanisms. - -- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final. -- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author). - -Authority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol. - -## Authority Round (Aura) - -A deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol. - -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. - -## Blind Assignment of Blockchain Extension (BABE) - -A [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block. - -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. - -## Block Author - -The node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_. - -## Byzantine Fault Tolerance (BFT) - -The ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack. - -### Byzantine Failure - -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. - -### Practical Byzantine Fault Tolerance (pBFT) - -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. - -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. - -### Preimage - -A preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\_blank}, the output, the hash, cannot be used to reveal the input, the preimage. - -## Call - -In the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object. - -## Chain Specification - -A chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains. - -## Collator - -An [author](#block-author) of a [parachain](#parachain) network. -They aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus). - -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. - -## Collective - -Most often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network. - -## Consensus - -Consensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship. - -See also [hybrid consensus](#hybrid-consensus). - -## Consensus Algorithm - -Ensures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft). - -Consensus algorithms are generally concerned with ensuring two properties: - -- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. -- **Liveness**: Indicating the ability of the chain to keep progressing. - -## Consensus Engine - -The node subsystem responsible for consensus tasks. - -For detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} blog series. - -See also [hybrid consensus](#hybrid-consensus). - -## Coretime - -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. - -On-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety. - -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank}. - -## Development Phrase - -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. - -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: - -``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk -``` - -Many tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`. - -## Digest - -An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: - -- [Light clients](#light-client) for chain synchronization. -- Consensus engines for block verification. -- The runtime itself, in the case of pre-runtime digests. - -## Dispatchable - -Function objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations. - -## Events - -A means of recording that some particular [state](#state) transition happened. - -In the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization. - -## Executor - -A means of executing a function call in a given [runtime](#runtime) with a set of dependencies. -There are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_. - -- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes. - -- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain. - -## Existential Deposit - -The minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. - -If an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\_blank} to drop its references to that account. - -If the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\_blank}. - -## Extrinsic - -A general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder. - -It is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). - -For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. - -## Fork Choice Rule/Strategy - -A fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\_blank}, in which the chain with the most blocks is selected. - -## FRAME (Framework for Runtime Aggregation of Modularized Entities) - -Enables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes. - -[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank} - -## Full Node - -A node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization. - -## Genesis Configuration - -A mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file. - -## GRANDPA - -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. - -The [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\_blank}. - -## Header - -A structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization. - -## Hybrid Consensus - -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. - -Hybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa). - -## Inherent Transactions - -A special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block. - -Only the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified. - -## JSON-RPC - -A stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON. - -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. - -## Keystore - -A subsystem for managing keys for the purpose of producing new blocks. - -## Kusama - -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. - -Kusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\_blank} network and is referred to as [Polkadot's "wild cousin."](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\_blank}. - -As a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation. - -## libp2p - -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). - -Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. - -## Light Client - -A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. - -A light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\_blank} server, enabling blockchain users to interact with the network. - -## Metadata - -Data that provides information about one or more aspects of a system. -The metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system. - -## Nominated Proof of Stake (NPoS) - -A method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes. - -## Oracle - -An entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services. - -## Origin - -A [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\_blank}. - -## Pallet - -A module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime). -Pallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item). - -## Parachain - -A parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_. -You can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\_blank}. - -## Paseo - -Paseo TestNet provisions testing on Polkadot's "production" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing. - -## Polkadot - -The [Polkadot network](https://polkadot.com/){target=\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain). - -## Polkadot Cloud - -Polkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance. - -## Polkadot Hub - -Polkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3. - -## PolkaVM - -PolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution. - -## Relay Chain - -Relay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another. - -## Rococo - -A [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead. - -## Runtime - -The runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function. - -## Slot - -A fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block. - -## Sovereign Account - -The unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem. - -The sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier. - -## SS58 Address Format - -A public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain - -The [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks - -## State Transition Function (STF) - -The logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime). - -## Storage Item - -[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime). -Learn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\_blank} reference document in the Polkadot SDK. - -## Substrate - -A flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\_blank}. - -## Transaction - -An [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}. - -## Transaction Era - -A definable period expressed as a range of block numbers during which a transaction can be included in a block. -Transaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero. - -## Trie (Patricia Merkle Tree) - -A data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set. - -In Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays. - -## Validator - -A validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance. - -## WebAssembly (Wasm) - -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. - -[Wasm](https://webassembly.org/){target=\_blank} can be compiled from many languages, including -the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state. - -## Weight - -A convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block. -Polkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware. - -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: - -- Block construction -- Network propagation -- Import and verification - -By defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements. - -## Westend - -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. - - --- Page Title: JSON-RPC APIs @@ -1238,128 +870,3 @@ If an error occurs, the response will include an error object: } } ``` - - ---- - -Page Title: Technical Reference Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md -- Canonical (HTML): https://docs.polkadot.com/reference/ -- Summary: Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. - -## Introduction - -The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need. - -Polkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\_blank} to the [governance](/reference/glossary#governance){target=\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants. - -This guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem. - -## Polkadot Hub - -[Polkadot Hub](/reference/polkadot-hub/){target=\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain. - -The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: - -- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications. -- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem. -- **Staking**: Participate in network security and earn rewards by staking DOT. -- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov. -- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities. -- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem. -- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations. - -## Parachains - -[Parachains](/reference/parachains/){target=\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers: - -- **Accounts**: Deep dive into account types, storage, and management on parachains. -- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms. -- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus. -- **Chain data**: Explore data structures, storage layouts, and state management. -- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains. -- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility. -- **Networks**: Learn about networking protocols and peer-to-peer communication. -- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\_blank}, the standard for cross-chain communication. -- **Randomness**: Understand how randomness is generated and used in Polkadot chains. -- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. - -## On-Chain Governance - -[On-Chain governance](/reference/governance/){target=\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details: - -- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums. -- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity. -- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance. -- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system. - -## Glossary - -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: - -- Blockchain concepts (blocks, transactions, state) -- Consensus mechanisms (validators, collators, finality) -- Polkadot-specific terms (relay chain, parachain, XCM, FRAME) -- Network components (nodes, runtimes, storage) -- Governance terminology (origins, tracks, referendums) - -## Tools - -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: - -- **Light clients**: Lightweight solutions for interacting with the network without running full nodes. -- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\_blank} and [PAPI](/reference/tools/papi/){target=\_blank} for building applications. -- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\_blank} and other Rust-based libraries for SDK development. -- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\_blank} for Python developers. -- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\_blank}, and [Omninode](/reference/tools/omninode/){target=\_blank} for smart contract and parachain testing. -- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\_blank} for substrate interaction. -- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\_blank} for XCM integration and asset transfers. - -## Where to Go Next - -For detailed exploration of specific areas, proceed to any of the main sections: - -
    - -- Learn **Polkadot Hub** - - --- - - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. - - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) - -- Learn **Parachains** - - --- - - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. - - [:octicons-arrow-right-24: Reference](/reference/parachains/) - -- Learn **On-Chain Governance** - - --- - - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. - - [:octicons-arrow-right-24: Reference](/reference/governance/) - -- Guide **Glossary** - - --- - - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. - - [:octicons-arrow-right-24: Reference](/reference/glossary/) - -- Guide **Tools** - - --- - - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. - - [:octicons-arrow-right-24: Reference](/reference/tools/) - -
    diff --git a/.ai/categories/smart-contracts.md b/.ai/categories/smart-contracts.md index 51b361f54..b5f0bfcb7 100644 --- a/.ai/categories/smart-contracts.md +++ b/.ai/categories/smart-contracts.md @@ -516,440 +516,6 @@ BlockScout is an open-source explorer platform with a user-friendly interface ad ![](/images/smart-contracts/explorers/block-explorers-2.webp) ---- - -Page Title: Blocks - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/ -- Summary: Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. - -# Blocks - -## Introduction - -In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the network. By understanding these concepts, developers can better grasp how blockchains maintain security, consistency, and performance within the Polkadot ecosystem. - -## What is a Block? - -In the Polkadot SDK, a block is a fundamental unit that encapsulates both the header and an array of transactions. The block header includes critical metadata to ensure the integrity and sequence of the blockchain. Here's a breakdown of its components: - -- **Block height**: Indicates the number of blocks created in the chain so far. -- **Parent hash**: The hash of the previous block, providing a link to maintain the blockchain's immutability. -- **Transaction root**: Cryptographic digest summarizing all transactions in the block. -- **State root**: A cryptographic digest representing the post-execution state. -- **Digest**: Additional information that can be attached to a block, such as consensus-related messages. - -Each transaction is part of a series that is executed according to the runtime's rules. The transaction root is a cryptographic digest of this series, which prevents alterations and enables succinct verification by light clients. This verification process allows light clients to confirm whether a transaction exists in a block with only the block header, avoiding downloading the entire block. - -## Block Production - -When an authoring node is authorized to create a new block, it selects transactions from the transaction queue based on priority. This step, known as block production, relies heavily on the executive module to manage the initialization and finalization of blocks. The process is summarized as follows: - -### Initialize Block - -The block initialization process begins with a series of function calls that prepare the block for transaction execution: - -1. **Call `on_initialize`**: The executive module calls the [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hook from the system pallet and other runtime pallets to prepare for the block's transactions. -2. **Coordinate runtime calls**: Coordinates function calls in the order defined by the transaction queue. -3. **Verify information**: Once [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} functions are executed, the executive module checks the parent hash in the block header and the trie root to verify information is consistent. - -### Finalize Block - -Once transactions are processed, the block must be finalized before being broadcast to the network. The finalization steps are as follows: - -1. **Call `on_finalize`**: The executive module calls the [`on_finalize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_finalize){target=\_blank} hooks in each pallet to ensure any remaining state updates or checks are completed before the block is sealed and published. -2. **Verify information**: The block's digest and storage root in the header are checked against the initialized block to ensure consistency. -3. **Call `on_idle`**: The [`on_idle`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_idle){target=\_blank} hook is triggered to process any remaining tasks using the leftover weight from the block. - -## Block Authoring and Import - -Once the block is finalized, it is gossiped to other nodes in the network. Nodes follow this procedure: - -1. **Receive transactions**: The authoring node collects transactions from the network. -2. **Validate**: Transactions are checked for validity. -3. **Queue**: Valid transactions are placed in the transaction pool for execution. -4. **Execute**: State changes are made as the transactions are executed. -5. **Publish**: The finalized block is broadcast to the network. - -### Block Import Queue - -After a block is published, other nodes on the network can import it into their chain state. The block import queue is part of the outer node in every Polkadot SDK-based node and ensures incoming blocks are valid before adding them to the node's state. - -In most cases, you don't need to know details about how transactions are gossiped or how other nodes on the network import blocks. The following traits are relevant, however, if you plan to write any custom consensus logic or want a deeper dive into the block import queue: - -- **[`ImportQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.ImportQueue.html){target=\_blank}**: The trait that defines the block import queue. -- **[`Link`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Link.html){target=\_blank}**: The trait that defines the link between the block import queue and the network. -- **[`BasicQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/struct.BasicQueue.html){target=\_blank}**: A basic implementation of the block import queue. -- **[`Verifier`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Verifier.html){target=\_blank}**: The trait that defines the block verifier. -- **[`BlockImport`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/block_import/trait.BlockImport.html){target=\_blank}**: The trait that defines the block import process. - -These traits govern how blocks are validated and imported across the network, ensuring consistency and security. - -## Additional Resources - -To learn more about the block structure in the Polkadot SDK runtime, see the [`Block` reference](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.Block.html){target=\_blank} entry in the Rust Docs. - - ---- - -Page Title: Chain Data - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/chain-data/ -- Summary: Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. - -# Chain Data - -## Introduction - -Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you can ensure seamless communication between your applications and the blockchain. - -## Application Development - -You might not be directly involved in building frontend applications as a blockchain developer. However, most applications that run on a blockchain require some form of frontend or user-facing client to enable users or other programs to access and modify the data that the blockchain stores. For example, you might develop a browser-based, mobile, or desktop application that allows users to submit transactions, post articles, view their assets, or track previous activity. The backend for that application is configured in the runtime logic for your blockchain, but the frontend client makes the runtime features accessible to your users. - -For your custom chain to be useful to others, you'll need to provide a client application that allows users to view, interact with, or update information that the blockchain keeps track of. In this article, you'll learn how to expose information about your runtime so that client applications can use it, see examples of the information exposed, and explore tools and libraries that use it. - -## Understand Metadata - -Polkadot SDK-based blockchain networks are designed to expose their runtime information, allowing developers to learn granular details regarding pallets, RPC calls, and runtime APIs. The metadata also exposes their related documentation. The chain's metadata is [SCALE-encoded](/reference/parachains/data-encoding/){target=\_blank}, allowing for the development of browser-based, mobile, or desktop applications to support the chain's runtime upgrades seamlessly. It is also possible to develop applications compatible with multiple Polkadot SDK-based chains simultaneously. - -## Expose Runtime Information as Metadata - -To interact with a node or the state of the blockchain, you need to know how to connect to the chain and access the exposed runtime features. This interaction involves a Remote Procedure Call (RPC) through a node endpoint address, commonly through a secure web socket connection. - -An application developer typically needs to know the contents of the runtime logic, including the following details: - -- Version of the runtime the application is connecting to. -- Supported APIs. -- Implemented pallets. -- Defined functions and corresponding type signatures. -- Defined custom types. -- Exposed parameters users can set. - -As the Polkadot SDK is modular and provides a composable framework for building blockchains, there are limitless opportunities to customize the schema of properties. Each runtime can be configured with its properties, including function calls and types, which can be changed over time with runtime upgrades. - -The Polkadot SDK enables you to generate the runtime metadata schema to capture information unique to a runtime. The metadata for a runtime describes the pallets in use and types defined for a specific runtime version. The metadata includes information about each pallet's storage items, functions, events, errors, and constants. The metadata also provides type definitions for any custom types included in the runtime. - -Metadata provides a complete inventory of a chain's runtime. It is key to enabling client applications to interact with the node, parse responses, and correctly format message payloads sent back to that chain. - -## Generate Metadata - -To efficiently use the blockchain's networking resources and minimize the data transmitted over the network, the metadata schema is encoded using the [Parity SCALE Codec](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank}. This encoding is done automatically through the [`scale-info`](https://docs.rs/scale-info/latest/scale_info/){target=\_blank}crate. - -At a high level, generating the metadata involves the following steps: - -1. The pallets in the runtime logic expose callable functions, types, parameters, and documentation that need to be encoded in the metadata. -2. The `scale-info` crate collects type information for the pallets in the runtime, builds a registry of the pallets that exist in a particular runtime, and the relevant types for each pallet in the registry. The type information is detailed enough to enable encoding and decoding for every type. -3. The [`frame-metadata`](https://github.com/paritytech/frame-metadata){target=\_blank} crate describes the structure of the runtime based on the registry provided by the `scale-info` crate. -4. Nodes provide the RPC method `state_getMetadata` to return a complete description of all the types in the current runtime as a hex-encoded vector of SCALE-encoded bytes. - -## Retrieve Runtime Metadata - -The type information provided by the metadata enables applications to communicate with nodes using different runtime versions and across chains that expose different calls, events, types, and storage items. The metadata also allows libraries to generate a substantial portion of the code needed to communicate with a given node, enabling libraries like [`subxt`](https://github.com/paritytech/subxt){target=\_blank} to generate frontend interfaces that are specific to a target chain. - -### Use Polkadot.js - -Visit the [Polkadot.js Portal](https://polkadot.js.org/apps/#/rpc){target=\_blank} and select the **Developer** dropdown in the top banner. Select **RPC Calls** to make the call to request metadata. Follow these steps to make the RPC call: - -1. Select **state** as the endpoint to call. -2. Select **`getMetadata(at)`** as the method to call. -3. Click **Submit RPC call** to submit the call and return the metadata in JSON format. - -### Use Curl - -You can fetch the metadata for the network by calling the node's RPC endpoint. This request returns the metadata in bytes rather than human-readable JSON: - -```sh -curl -H "Content-Type: application/json" \ --d '{"id":1, "jsonrpc":"2.0", "method": "state_getMetadata"}' \ -https://rpc.polkadot.io - -``` - -### Use Subxt - -[`subxt`](https://github.com/paritytech/subxt){target=\_blank} may also be used to fetch the metadata of any data in a human-readable JSON format: - -```sh -subxt metadata --url wss://rpc.polkadot.io --format json > spec.json -``` - -Another option is to use the [`subxt` explorer web UI](https://paritytech.github.io/subxt-explorer/#/){target=\_blank}. - -## Client Applications and Metadata - -The metadata exposes the expected way to decode each type, meaning applications can send, retrieve, and process application information without manual encoding and decoding. Client applications must use the [SCALE codec library](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank} to encode and decode RPC payloads to use the metadata. Client applications use the metadata to interact with the node, parse responses, and format message payloads sent to the node. - -## Metadata Format - -Although the SCALE-encoded bytes can be decoded using the `frame-metadata` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} libraries, there are other tools, such as `subxt` and the Polkadot-JS API, that can convert the raw data to human-readable JSON format. - -The types and type definitions included in the metadata returned by the `state_getMetadata` RPC call depend on the runtime's metadata version. - -In general, the metadata includes the following information: - -- A constant identifying the file as containing metadata. -- The version of the metadata format used in the runtime. -- Type definitions for all types used in the runtime and generated by the `scale-info` crate. -- Pallet information for the pallets included in the runtime in the order that they are defined in the `construct_runtime` macro. - -!!!tip - Depending on the frontend library used (such as the [Polkadot API](https://papi.how/){target=\_blank}), they may format the metadata differently than the raw format shown. - -The following example illustrates a condensed and annotated section of metadata decoded and converted to JSON: - -```json -[ - 1635018093, - { - "V14": { - "types": { - "types": [{}] - }, - "pallets": [{}], - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [{}] - }, - "ty": 141 - } - } -] - -``` - -The constant `1635018093` is a magic number that identifies the file as a metadata file. The rest of the metadata is divided into the `types`, `pallets`, and `extrinsic` sections: - -- The `types` section contains an index of the types and information about each type's type signature. -- The `pallets` section contains information about each pallet in the runtime. -- The `extrinsic` section describes the type identifier and transaction format version that the runtime uses. - -Different extrinsic versions can have varying formats, especially when considering [signed transactions](/reference/parachains/blocks-transactions-fees/transactions/#signed-transactions){target=\_blank}. - -### Pallets - -The following is a condensed and annotated example of metadata for a single element in the `pallets` array (the [`sudo`](https://paritytech.github.io/polkadot-sdk/master/pallet_sudo/index.html){target=\_blank} pallet): - -```json -{ - "name": "Sudo", - "storage": { - "prefix": "Sudo", - "entries": [ - { - "name": "Key", - "modifier": "Optional", - "ty": { - "Plain": 0 - }, - "default": [0], - "docs": ["The `AccountId` of the sudo key."] - } - ] - }, - "calls": { - "ty": 117 - }, - "event": { - "ty": 42 - }, - "constants": [], - "error": { - "ty": 124 - }, - "index": 8 -} - -``` - -Every element metadata contains the name of the pallet it represents and information about its storage, calls, events, and errors. You can look up details about the definition of the calls, events, and errors by viewing the type index identifier. The type index identifier is the `u32` integer used to access the type information for that item. For example, the type index identifier for calls in the Sudo pallet is 117. If you view information for that type identifier in the `types` section of the metadata, it provides information about the available calls, including the documentation for each call. - -For example, the following is a condensed excerpt of the calls for the Sudo pallet: - -```json -{ - "id": 117, - "type": { - "path": ["pallet_sudo", "pallet", "Call"], - "params": [ - { - "name": "T", - "type": null - } - ], - "def": { - "variant": { - "variants": [ - { - "name": "sudo", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 0, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "sudo_unchecked_weight", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - }, - { - "name": "weight", - "type": 8, - "typeName": "Weight" - } - ], - "index": 1, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "set_key", - "fields": [ - { - "name": "new", - "type": 103, - "typeName": "AccountIdLookupOf" - } - ], - "index": 2, - "docs": [ - "Authenticates current sudo key, sets the given AccountId (`new`) as the new sudo" - ] - }, - { - "name": "sudo_as", - "fields": [ - { - "name": "who", - "type": 103, - "typeName": "AccountIdLookupOf" - }, - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 3, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Signed` origin from a given account" - ] - } - ] - } - } - } -} - -``` - -For each field, you can access type information and metadata for the following: - -- **Storage metadata**: Provides the information required to enable applications to get information for specific storage items. -- **Call metadata**: Includes information about the runtime calls defined by the `#[pallet]` macro including call names, arguments and documentation. -- **Event metadata**: Provides the metadata generated by the `#[pallet::event]` macro, including the name, arguments, and documentation for each pallet event. -- **Constants metadata**: Provides metadata generated by the `#[pallet::constant]` macro, including the name, type, and hex-encoded value of the constant. -- **Error metadata**: Provides metadata generated by the `#[pallet::error]` macro, including the name and documentation for each pallet error. - -!!!tip - Type identifiers change from time to time, so you should avoid relying on specific type identifiers in your applications. - -### Extrinsic - -The runtime generates extrinsic metadata and provides useful information about transaction format. When decoded, the metadata contains the transaction version and the list of signed extensions. - -For example: - -```json -{ - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [ - { - "identifier": "CheckNonZeroSender", - "ty": 132, - "additional_signed": 41 - }, - { - "identifier": "CheckSpecVersion", - "ty": 133, - "additional_signed": 4 - }, - { - "identifier": "CheckTxVersion", - "ty": 134, - "additional_signed": 4 - }, - { - "identifier": "CheckGenesis", - "ty": 135, - "additional_signed": 11 - }, - { - "identifier": "CheckMortality", - "ty": 136, - "additional_signed": 11 - }, - { - "identifier": "CheckNonce", - "ty": 138, - "additional_signed": 41 - }, - { - "identifier": "CheckWeight", - "ty": 139, - "additional_signed": 41 - }, - { - "identifier": "ChargeTransactionPayment", - "ty": 140, - "additional_signed": 41 - } - ] - }, - "ty": 141 -} - -``` - -The type system is [composite](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank}, meaning each type identifier contains a reference to a specific type or to another type identifier that provides information about the associated primitive types. - -For example, you can encode the `BitVec` type, but to decode it properly, you must know the types used for the `Order` and `Store` types. To find type information for `Order` and `Store`, you can use the path in the decoded JSON to locate their type identifiers. - -## Included RPC APIs - -A standard node comes with the following APIs to interact with a node: - -- **[`AuthorApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/author/trait.AuthorApiServer.html){target=\_blank}**: Make calls into a full node, including authoring extrinsics and verifying session keys. -- **[`ChainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/chain/trait.ChainApiServer.html){target=\_blank}**: Retrieve block header and finality information. -- **[`OffchainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/offchain/trait.OffchainApiServer.html){target=\_blank}**: Make RPC calls for off-chain workers. -- **[`StateApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/state/trait.StateApiServer.html){target=\_blank}**: Query information about on-chain state such as runtime version, storage items, and proofs. -- **[`SystemApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/system/trait.SystemApiServer.html){target=\_blank}**: Retrieve information about network state, such as connected peers and node roles. - -## Additional Resources - -The following tools can help you locate and decode metadata: - -- [Subxt Explorer](https://paritytech.github.io/subxt-explorer/#/){target=\_blank} -- [Metadata Portal 🌗](https://github.com/paritytech/metadata-portal){target=\_blank} -- [De[code] Sub[strate]](https://github.com/paritytech/desub){target=\_blank} - - --- Page Title: Connect to Polkadot @@ -1170,413 +736,139 @@ Both backends support contract deployment effectively, with REVM offering drop-i --- -Page Title: Cryptography +Page Title: Deploy a Basic Contract to Polkadot Hub -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/cryptography/ -- Summary: A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/.deploy-basic-pvm/ +- Summary: Learn how to deploy a basic smart contract to Polkadot Hub using the PolkaVM. -# Cryptography +# Deploy a Basic Contract ## Introduction -Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem. - -## Hash Functions - -Hash functions are fundamental to blockchain technology, creating a unique digital fingerprint for any piece of data, including simple text, images, or any other form of file. They map input data of any size to a fixed-size output (typically 32 bytes) using complex mathematical operations. Hashing is used to verify data integrity, create digital signatures, and provide a secure way to store passwords. This form of mapping is known as the ["pigeonhole principle,"](https://en.wikipedia.org/wiki/Pigeonhole_principle){target=\_blank} it is primarily implemented to efficiently and verifiably identify data from large sets. - -### Key Properties of Hash Functions - -- **Deterministic**: The same input always produces the same output. -- **Quick computation**: It's easy to calculate the hash value for any given input. -- **Pre-image resistance**: It's infeasible to generate the input data from its hash. -- **Small changes in input yield large changes in output**: Known as the ["avalanche effect"](https://en.wikipedia.org/wiki/Avalanche_effect){target=\_blank}. -- **Collision resistance**: The probabilities are extremely low to find two different inputs with the same hash. - -### Blake2 - -The Polkadot SDK utilizes Blake2, a state-of-the-art hashing method that offers: - -- Equal or greater security compared to [SHA-2](https://en.wikipedia.org/wiki/SHA-2){target=\_blank}. -- Significantly faster performance than other algorithms. - -These properties make Blake2 ideal for blockchain systems, reducing sync times for new nodes and lowering the resources required for validation. For detailed technical specifications about Blake2, see the [official Blake2 paper](https://www.blake2.net/blake2.pdf){target=\_blank}. +Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\_blank}, [Remix IDE](https://remix.live/){target=\_blank}, [Hardhat](https://hardhat.org/){target=\_blank}, and [Foundry](https://getfoundry.sh/){target=\_blank}. -## Types of Cryptography +All these tools leverage the `revive` compiler to transform Solidity smart contracts into PolkaVM bytecode, making them compatible with Polkadot Hub's native smart contract environment. Whether you prefer working with lightweight JavaScript libraries, visual browser-based IDEs, comprehensive development frameworks, or fast command-line toolkits, this guide covers the deployment process for each approach. -There are two different ways that cryptographic algorithms are implemented: symmetric cryptography and asymmetric cryptography. +**Prerequisites:** -### Symmetric Cryptography +- Basic understanding of Solidity programming. +- [Node.js](https://nodejs.org/en/download){target=\_blank} v22.13.1 or later (for JavaScript/Hardhat approaches). +- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). +- A wallet with a private key for signing transactions. -Symmetric encryption is a branch of cryptography that isn't based on one-way functions, unlike asymmetric cryptography. It uses the same cryptographic key to encrypt plain text and decrypt the resulting ciphertext. +## JavaScript with Ethers.js -Symmetric cryptography is a type of encryption that has been used throughout history, such as the Enigma Cipher and the Caesar Cipher. It is still widely used today and can be found in Web2 and Web3 applications alike. There is only one single key, and a recipient must also have access to it to access the contained information. +Ethers.js provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications. -#### Advantages {: #symmetric-advantages } +### Setup -- Fast and efficient for large amounts of data. -- Requires less computational power. +First, initialize your project and install dependencies: -#### Disadvantages {: #symmetric-disadvantages } +```bash +mkdir ethers-deployment +cd ethers-deployment +npm init -y +npm install ethers @parity/resolc +``` -- Key distribution can be challenging. -- Scalability issues in systems with many users. +### Create and Compile Your Contract -### Asymmetric Cryptography +Create a simple storage contract in `contracts/Storage.sol`: -Asymmetric encryption is a type of cryptography that uses two different keys, known as a keypair: a public key, used to encrypt plain text, and a private counterpart, used to decrypt the ciphertext. +```solidity title="contracts/Storage.sol" +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.9; -The public key encrypts a fixed-length message that can only be decrypted with the recipient's private key and, sometimes, a set password. The public key can be used to cryptographically verify that the corresponding private key was used to create a piece of data without compromising the private key, such as with digital signatures. This has obvious implications for identity, ownership, and properties and is used in many different protocols across Web2 and Web3. +contract Storage { + uint256 private storedNumber; -#### Advantages {: #asymmetric-advantages } + function store(uint256 num) public { + storedNumber = num; + } -- Solves the key distribution problem. -- Enables digital signatures and secure key exchange. + function retrieve() public view returns (uint256) { + return storedNumber; + } +} +``` -#### Disadvantages {: #asymmetric-disadvantages } +Create a compilation script `compile.js`: -- Slower than symmetric encryption. -- Requires more computational resources. +```javascript title="compile.js" +const { compile } = require('@parity/resolc'); +const { readFileSync, writeFileSync } = require('fs'); +const { basename, join } = require('path'); -### Trade-offs and Compromises +const compileContract = async (solidityFilePath, outputDir) => { + try { + // Read the Solidity file + const source = readFileSync(solidityFilePath, 'utf8'); -Symmetric cryptography is faster and requires fewer bits in the key to achieve the same level of security that asymmetric cryptography provides. However, it requires a shared secret before communication can occur, which poses issues to its integrity and a potential compromise point. On the other hand, asymmetric cryptography doesn't require the secret to be shared ahead of time, allowing for far better end-user security. + // Construct the input object for the compiler + const input = { + [basename(solidityFilePath)]: { content: source }, + }; -Hybrid symmetric and asymmetric cryptography is often used to overcome the engineering issues of asymmetric cryptography, as it is slower and requires more bits in the key to achieve the same level of security. It encrypts a key and then uses the comparatively lightweight symmetric cipher to do the "heavy lifting" with the message. + console.log(`Compiling contract: ${basename(solidityFilePath)}...`); -## Digital Signatures + // Compile the contract + const out = await compile(input); -Digital signatures are a way of verifying the authenticity of a document or message using asymmetric keypairs. They are used to ensure that a sender or signer's document or message hasn't been tampered with in transit, and for recipients to verify that the data is accurate and from the expected sender. + for (const contracts of Object.values(out.contracts)) { + for (const [name, contract] of Object.entries(contracts)) { + console.log(`Compiled contract: ${name}`); -Signing digital signatures only requires a low-level understanding of mathematics and cryptography. For a conceptual example -- when signing a check, it is expected that it cannot be cashed multiple times. This isn't a feature of the signature system but rather the check serialization system. The bank will check that the serial number on the check hasn't already been used. Digital signatures essentially combine these two concepts, allowing the signature to provide the serialization via a unique cryptographic fingerprint that cannot be reproduced. + // Write the ABI + const abiPath = join(outputDir, `${name}.json`); + writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); + console.log(`ABI saved to ${abiPath}`); -Unlike pen-and-paper signatures, knowledge of a digital signature cannot be used to create other signatures. Digital signatures are often used in bureaucratic processes, as they are more secure than simply scanning in a signature and pasting it onto a document. + // Write the bytecode + const bytecodePath = join(outputDir, `${name}.polkavm`); + writeFileSync( + bytecodePath, + Buffer.from(contract.evm.bytecode.object, 'hex'), + ); + console.log(`Bytecode saved to ${bytecodePath}`); + } + } + } catch (error) { + console.error('Error compiling contracts:', error); + } +}; -Polkadot SDK provides multiple different cryptographic schemes and is generic so that it can support anything that implements the [`Pair` trait](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Pair.html){target=\_blank}. +const solidityFilePath = join(__dirname, 'contracts/Storage.sol'); +const outputDir = join(__dirname, 'contracts'); -### Example of Creating a Digital Signature +compileContract(solidityFilePath, outputDir); +``` -The process of creating and verifying a digital signature involves several steps: +Run the compilation: -1. The sender creates a hash of the message. -2. The hash is encrypted using the sender's private key, creating the signature. -3. The message and signature are sent to the recipient. -4. The recipient decrypts the signature using the sender's public key. -5. The recipient hashes the received message and compares it to the decrypted hash. +```bash +node compile.js +``` -If the hashes match, the signature is valid, confirming the message's integrity and the sender's identity. +### Deploy the Contract -## Elliptic Curve +Create a deployment script `deploy.js`: -Blockchain technology requires the ability to have multiple keys creating a signature for block proposal and validation. To this end, Elliptic Curve Digital Signature Algorithm (ECDSA) and Schnorr signatures are two of the most commonly used methods. While ECDSA is a far simpler implementation, Schnorr signatures are more efficient when it comes to multi-signatures. +```javascript title="deploy.js" +const { writeFileSync, existsSync, readFileSync } = require('fs'); +const { join } = require('path'); +const { ethers, JsonRpcProvider } = require('ethers'); -Schnorr signatures bring some noticeable features over the ECDSA/EdDSA schemes: +const codegenDir = join(__dirname); -- It is better for hierarchical deterministic key derivations. -- It allows for native multi-signature through [signature aggregation](https://bitcoincore.org/en/2017/03/23/schnorr-signature-aggregation/){target=\_blank}. -- It is generally more resistant to misuse. - -One sacrifice that is made when using Schnorr signatures over ECDSA is that both require 64 bytes, but only ECDSA signatures communicate their public key. - -### Various Implementations - -- **[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm){target=\_blank}**: Polkadot SDK provides an ECDSA signature scheme using the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1){target=\_blank} curve. This is the same cryptographic algorithm used to secure [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin){target=\_blank} and [Ethereum](https://en.wikipedia.org/wiki/Ethereum){target=\_blank}. - -- **[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519){target=\_blank}**: An EdDSA signature scheme using [Curve25519](https://en.wikipedia.org/wiki/Curve25519){target=\_blank}. It is carefully engineered at several levels of design and implementation to achieve very high speeds without compromising security. - -- **[SR25519](https://research.web3.foundation/Polkadot/security/keys/accounts-more){target=\_blank}**: Based on the same underlying curve as Ed25519. However, it uses Schnorr signatures instead of the EdDSA scheme. - - ---- - -Page Title: Data Encoding - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/data-encoding/ -- Summary: SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. - -# Data Encoding - -## Introduction - -The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data. - -The SCALE codec enables communication between the runtime and the outer node. This mechanism is designed for high-performance, copy-free data encoding and decoding in resource-constrained environments like the Polkadot SDK [Wasm runtime](/develop/parachains/deployment/build-deterministic-runtime/#introduction){target=\_blank}. - -It is not self-describing, meaning the decoding context must fully know the encoded data types. - -Parity's libraries utilize the [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} crate (a Rust implementation of the SCALE codec) to handle encoding and decoding for interactions between RPCs and the runtime. - -The `codec` mechanism is ideal for Polkadot SDK-based chains because: - -- It is lightweight compared to generic serialization frameworks like [`serde`](https://serde.rs/){target=\_blank}, which add unnecessary bulk to binaries. -- It doesn’t rely on Rust’s `libstd`, making it compatible with `no_std` environments like Wasm runtime. -- It integrates seamlessly with Rust, allowing easy derivation of encoding and decoding logic for new types using `#[derive(Encode, Decode)]`. - -Defining a custom encoding scheme in the Polkadot SDK-based chains, rather than using an existing Rust codec library, is crucial for enabling cross-platform and multi-language support. - -## SCALE Codec - -The codec is implemented using the following traits: - -- [`Encode`](#encode) -- [`Decode`](#decode) -- [`CompactAs`](#compactas) -- [`HasCompact`](#hascompact) -- [`EncodeLike`](#encodelike) - -### Encode - -The [`Encode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Encode.html){target=\_blank} trait handles data encoding into SCALE format and includes the following key functions: - -- **`size_hint(&self) -> usize`**: Estimates the number of bytes required for encoding to prevent multiple memory allocations. This should be inexpensive and avoid complex operations. Optional if the size isn’t known. -- **`encode_to(&self, dest: &mut T)`**: Encodes the data, appending it to a destination buffer. -- **`encode(&self) -> Vec`**: Encodes the data and returns it as a byte vector. -- **`using_encoded R>(&self, f: F) -> R`**: Encodes the data and passes it to a closure, returning the result. -- **`encoded_size(&self) -> usize`**: Calculates the encoded size. Should be used when the encoded data isn’t required. - -!!!tip - For best performance, value types should override `using_encoded`, and allocating types should override `encode_to`. It's recommended to implement `size_hint` for all types where possible. - -### Decode - -The [`Decode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Decode.html){target=\_blank} trait handles decoding SCALE-encoded data back into the appropriate types: - -- **`fn decode(value: &mut I) -> Result`**: Decodes data from the SCALE format, returning an error if decoding fails. - -### CompactAs - -The [`CompactAs`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.CompactAs.html){target=\_blank} trait wraps custom types for compact encoding: - -- **`encode_as(&self) -> &Self::As`**: Encodes the type as a compact type. -- **`decode_from(_: Self::As) -> Result`**: decodes from a compact encoded type. - -### HasCompact - -The [`HasCompact`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.HasCompact.html){target=\_blank} trait indicates a type supports compact encoding. - -### EncodeLike - -The [`EncodeLike`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.EncodeLike.html){target=\_blank} trait is used to ensure multiple types that encode similarly are accepted by the same function. When using `derive`, it is automatically implemented. - -### Data Types - -The table below outlines how the Rust implementation of the Parity SCALE codec encodes different data types. - -| Type | Description | Example SCALE Decoded Value | SCALE Encoded Value | -|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| -| Boolean | Boolean values are encoded using the least significant bit of a single byte. | `false` / `true` | `0x00` / `0x01` | -| Compact/general integers | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2^536) and is more efficient at encoding most values than the fixed-width version. | `unsigned integer 0` / `unsigned integer 1` / `unsigned integer 42` / `unsigned integer 69` / `unsigned integer 65535` / `BigInt(100000000000000)` | `0x00` / `0x04` / `0xa8` / `0x1501` / `0xfeff0300` / `0x0b00407a10f35a` | -| Enumerations (tagged-unions) | A fixed number of variants, each mutually exclusive and potentially implying a further value or series of values. Encoded as the first byte identifying the index of the variant that the value is. Any further bytes are used to encode any data that the variant implies. Thus, no more than 256 variants are supported. | `Int(42)` and `Bool(true)` where `enum IntOrBool { Int(u8), Bool(bool) }` | `0x002a` and `0x0101` | -| Fixed-width integers | Basic integers are encoded using a fixed-width little-endian (LE) format. | `signed 8-bit integer 69` / `unsigned 16-bit integer 42` / `unsigned 32-bit integer 16777215` | `0x45` / `0x2a00` / `0xffffff00` | -| Options | One or zero values of a particular type. | `Some` / `None` | `0x01` followed by the encoded value / `0x00` | -| Results | Results are commonly used enumerations which indicate whether certain operations were successful or unsuccessful. | `Ok(42)` / `Err(false)` | `0x002a` / `0x0100` | -| Strings | Strings are Vectors of bytes (Vec) containing a valid UTF8 sequence. | | | -| Structs | For structures, the values are named, but that is irrelevant for the encoding (names are ignored - only order matters). | `SortedVecAsc::from([3, 5, 2, 8])` | `[3, 2, 5, 8] ` | -| Tuples | A fixed-size series of values, each with a possibly different but predetermined and fixed type. This is simply the concatenation of each encoded value. | Tuple of compact unsigned integer and boolean: `(3, false)` | `0x0c00` | -| Vectors (lists, series, sets) | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. | Vector of unsigned `16`-bit integers: `[4, 8, 15, 16, 23, 42]` | `0x18040008000f00100017002a00` | - -## Encode and Decode Rust Trait Implementations - -Here's how the `Encode` and `Decode` traits are implemented: - - -```rust -use parity_scale_codec::{Encode, Decode}; - -[derive(Debug, PartialEq, Encode, Decode)] -enum EnumType { - #[codec(index = 15)] - A, - B(u32, u64), - C { - a: u32, - b: u64, - }, -} - -let a = EnumType::A; -let b = EnumType::B(1, 2); -let c = EnumType::C { a: 1, b: 2 }; - -a.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x0f"); -}); - -b.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -c.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -let mut da: &[u8] = b"\x0f"; -assert_eq!(EnumType::decode(&mut da).ok(), Some(a)); - -let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut db).ok(), Some(b)); - -let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut dc).ok(), Some(c)); - -let mut dz: &[u8] = &[0]; -assert_eq!(EnumType::decode(&mut dz).ok(), None); -``` - -## SCALE Codec Libraries - -Several SCALE codec implementations are available in various languages. Here's a list of them: - -- **AssemblyScript**: [`LimeChain/as-scale-codec`](https://github.com/LimeChain/as-scale-codec){target=\_blank} -- **C**: [`MatthewDarnell/cScale`](https://github.com/MatthewDarnell/cScale){target=\_blank} -- **C++**: [`qdrvm/scale-codec-cpp`](https://github.com/qdrvm/scale-codec-cpp){target=\_blank} -- **JavaScript**: [`polkadot-js/api`](https://github.com/polkadot-js/api){target=\_blank} -- **Dart**: [`leonardocustodio/polkadart`](https://github.com/leonardocustodio/polkadart){target=\_blank} -- **Haskell**: [`airalab/hs-web3`](https://github.com/airalab/hs-web3/tree/master/packages/scale){target=\_blank} -- **Golang**: [`itering/scale.go`](https://github.com/itering/scale.go){target=\_blank} -- **Java**: [`splix/polkaj`](https://github.com/splix/polkaj){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **Ruby**: [` wuminzhe/scale_rb`](https://github.com/wuminzhe/scale_rb){target=\_blank} -- **TypeScript**: [`parity-scale-codec-ts`](https://github.com/tjjfvi/subshape){target=\_blank}, [`scale-ts`](https://github.com/unstoppablejs/unstoppablejs/tree/main/packages/scale-ts#scale-ts){target=\_blank}, [`soramitsu/scale-codec-js-library`](https://github.com/soramitsu/scale-codec-js-library){target=\_blank}, [`subsquid/scale-codec`](https://github.com/subsquid/squid-sdk/tree/master/substrate/scale-codec){target=\_blank} - - ---- - -Page Title: Deploy a Basic Contract to Polkadot Hub - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-.deploy-basic-pvm.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/.deploy-basic-pvm/ -- Summary: Learn how to deploy a basic smart contract to Polkadot Hub using the PolkaVM. - -# Deploy a Basic Contract - -## Introduction - -Deploying smart contracts to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank} can be accomplished through various tools and environments, each suited to different development workflows. This guide demonstrates how to deploy a basic PolkaVM (PVM) smart contract using four popular approaches: JavaScript with [Ethers.js](https://docs.ethers.org/v6/){target=\_blank}, [Remix IDE](https://remix.live/){target=\_blank}, [Hardhat](https://hardhat.org/){target=\_blank}, and [Foundry](https://getfoundry.sh/){target=\_blank}. - -All these tools leverage the `revive` compiler to transform Solidity smart contracts into PolkaVM bytecode, making them compatible with Polkadot Hub's native smart contract environment. Whether you prefer working with lightweight JavaScript libraries, visual browser-based IDEs, comprehensive development frameworks, or fast command-line toolkits, this guide covers the deployment process for each approach. - -**Prerequisites:** - -- Basic understanding of Solidity programming. -- [Node.js](https://nodejs.org/en/download){target=\_blank} v22.13.1 or later (for JavaScript/Hardhat approaches). -- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). -- A wallet with a private key for signing transactions. - -## JavaScript with Ethers.js - -Ethers.js provides a lightweight approach for deploying contracts using pure JavaScript. This method is ideal for developers who want programmatic control over the deployment process or need to integrate contract deployment into existing applications. - -### Setup - -First, initialize your project and install dependencies: - -```bash -mkdir ethers-deployment -cd ethers-deployment -npm init -y -npm install ethers @parity/resolc -``` - -### Create and Compile Your Contract - -Create a simple storage contract in `contracts/Storage.sol`: - -```solidity title="contracts/Storage.sol" -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.9; - -contract Storage { - uint256 private storedNumber; - - function store(uint256 num) public { - storedNumber = num; - } - - function retrieve() public view returns (uint256) { - return storedNumber; - } -} -``` - -Create a compilation script `compile.js`: - -```javascript title="compile.js" -const { compile } = require('@parity/resolc'); -const { readFileSync, writeFileSync } = require('fs'); -const { basename, join } = require('path'); - -const compileContract = async (solidityFilePath, outputDir) => { - try { - // Read the Solidity file - const source = readFileSync(solidityFilePath, 'utf8'); - - // Construct the input object for the compiler - const input = { - [basename(solidityFilePath)]: { content: source }, - }; - - console.log(`Compiling contract: ${basename(solidityFilePath)}...`); - - // Compile the contract - const out = await compile(input); - - for (const contracts of Object.values(out.contracts)) { - for (const [name, contract] of Object.entries(contracts)) { - console.log(`Compiled contract: ${name}`); - - // Write the ABI - const abiPath = join(outputDir, `${name}.json`); - writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); - console.log(`ABI saved to ${abiPath}`); - - // Write the bytecode - const bytecodePath = join(outputDir, `${name}.polkavm`); - writeFileSync( - bytecodePath, - Buffer.from(contract.evm.bytecode.object, 'hex'), - ); - console.log(`Bytecode saved to ${bytecodePath}`); - } - } - } catch (error) { - console.error('Error compiling contracts:', error); - } -}; - -const solidityFilePath = join(__dirname, 'contracts/Storage.sol'); -const outputDir = join(__dirname, 'contracts'); - -compileContract(solidityFilePath, outputDir); -``` - -Run the compilation: - -```bash -node compile.js -``` - -### Deploy the Contract - -Create a deployment script `deploy.js`: - -```javascript title="deploy.js" -const { writeFileSync, existsSync, readFileSync } = require('fs'); -const { join } = require('path'); -const { ethers, JsonRpcProvider } = require('ethers'); - -const codegenDir = join(__dirname); - -// Creates a provider with specified RPC URL and chain details -const createProvider = (rpcUrl, chainId, chainName) => { - const provider = new JsonRpcProvider(rpcUrl, { - chainId: chainId, - name: chainName, - }); - return provider; -}; +// Creates a provider with specified RPC URL and chain details +const createProvider = (rpcUrl, chainId, chainName) => { + const provider = new JsonRpcProvider(rpcUrl, { + chainId: chainId, + name: chainName, + }); + return provider; +}; // Reads and parses the ABI file for a given contract const getAbi = (contractName) => { @@ -3912,49 +3204,6 @@ Revive implements the standard set of Ethereum precompiles: Ethereum-native precompiles provide a powerful foundation for smart contract development on Polkadot Hub, offering high-performance implementations of essential cryptographic and utility functions. By maintaining compatibility with standard Ethereum precompile addresses and interfaces, Revive ensures that developers can leverage existing knowledge and tools while benefiting from the enhanced performance of native execution. ---- - -Page Title: Faucet - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-faucet.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/faucet/ -- Summary: Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. - -# Faucet - -Test tokens allow you to experiment with smart contracts, test transactions, and validate your dApp functionality without using real cryptocurrency. - -Polkadot has a faucet that distributes free TestNet tokens to developers for testing purposes: - -- Execute transactions on TestNet networks. -- Pay for gas fees when deploying smart contracts. -- Test dApp functionality before MainNet deployment. -- Experiment with blockchain interactions without financial risk. - - -## Get Test Tokens - -For Polkadot Hub TestNet, you can use the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank} to obtain test tokens. Here's how to do it: - -1. Navigate to the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. If the desired network is not already selected, choose it from the **Network** drop-down. This example uses the Polkadot Hub TestNet. -2. Copy your address linked to the TestNet and paste it into the designated field. -3. Click the **Get Some PASs** button to request free test PAS tokens. These tokens will be sent to your wallet shortly. - -![Polkadot Faucet](/images/smart-contracts/faucet/faucet-1.gif) - -## Things to Consider - -!!! info "Rate Limiting" - Faucets typically implement rate limiting to prevent abuse. You may need to wait between requests if you've recently obtained tokens from the same faucet. - -!!! warning "Network Compatibility" - Ensure your wallet is connected to the correct network (Polkadot Hub TestNet) before requesting tokens. Tokens sent to addresses on different networks will not be accessible. - -## Using Your Test Tokens - -Getting started with test tokens is the first step in your Polkadot development journey. These free resources enable you to build, experiment with, and refine your applications without financial constraints, ensuring your projects are robust and ready for deployment on MainNet. - - --- Page Title: Get Started with Parachain Development @@ -4159,370 +3408,173 @@ From here, follow the quick starts to get connected, iterate locally with your p --- -Page Title: Glossary - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md -- Canonical (HTML): https://docs.polkadot.com/reference/glossary/ -- Summary: Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. - -# Glossary +Page Title: Get Started with XCM -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. - -Additional glossaries from around the ecosystem you might find helpful: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ +- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. -- [Polkadot Wiki Glossary](https://wiki.polkadot.com/general/glossary){target=\_blank} -- [Polkadot SDK Glossary](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/glossary/index.html){target=\_blank} +# Get Started with XCM -## Authority +## Introduction -The role in a blockchain that can participate in consensus mechanisms. +Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. -- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final. -- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author). +With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. -Authority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol. +## Messaging Format -## Authority Round (Aura) +XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. -A deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol. +XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. +## The Four Principles of XCM -## Blind Assignment of Blockchain Extension (BABE) +XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: -A [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block. - -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. - -## Block Author - -The node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_. - -## Byzantine Fault Tolerance (BFT) - -The ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack. - -### Byzantine Failure - -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. - -### Practical Byzantine Fault Tolerance (pBFT) - -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. - -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. - -### Preimage - -A preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\_blank}, the output, the hash, cannot be used to reveal the input, the preimage. - -## Call - -In the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object. - -## Chain Specification - -A chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains. - -## Collator - -An [author](#block-author) of a [parachain](#parachain) network. -They aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus). - -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. - -## Collective - -Most often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network. - -## Consensus - -Consensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship. - -See also [hybrid consensus](#hybrid-consensus). - -## Consensus Algorithm - -Ensures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft). - -Consensus algorithms are generally concerned with ensuring two properties: - -- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. -- **Liveness**: Indicating the ability of the chain to keep progressing. - -## Consensus Engine +- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. +- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. +- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. +- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. -The node subsystem responsible for consensus tasks. +These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. -For detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} blog series. +## The XCM Tech Stack -See also [hybrid consensus](#hybrid-consensus). +![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) -## Coretime +The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. +## Core Functionalities of XCM -On-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety. +XCM enhances cross-consensus communication by introducing several powerful features: -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank}. +- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. +- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. +- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. -## Development Phrase +The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. +## XCM Example -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: +The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). +```rust +let message = Xcm(vec![ + WithdrawAsset((Here, amount).into()), + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } +]); ``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk -``` - -Many tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`. - -## Digest - -An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: - -- [Light clients](#light-client) for chain synchronization. -- Consensus engines for block verification. -- The runtime itself, in the case of pre-runtime digests. - -## Dispatchable - -Function objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations. - -## Events - -A means of recording that some particular [state](#state) transition happened. - -In the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization. - -## Executor - -A means of executing a function call in a given [runtime](#runtime) with a set of dependencies. -There are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_. - -- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes. - -- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain. - -## Existential Deposit - -The minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. - -If an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\_blank} to drop its references to that account. - -If the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\_blank}. - -## Extrinsic - -A general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder. - -It is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). - -For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. - -## Fork Choice Rule/Strategy - -A fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\_blank}, in which the chain with the most blocks is selected. - -## FRAME (Framework for Runtime Aggregation of Modularized Entities) - -Enables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes. - -[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank} - -## Full Node - -A node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization. - -## Genesis Configuration - -A mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file. - -## GRANDPA - -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. - -The [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\_blank}. - -## Header - -A structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization. - -## Hybrid Consensus - -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. - -Hybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa). - -## Inherent Transactions - -A special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block. - -Only the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified. - -## JSON-RPC - -A stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON. - -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. - -## Keystore - -A subsystem for managing keys for the purpose of producing new blocks. - -## Kusama - -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. - -Kusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\_blank} network and is referred to as [Polkadot's "wild cousin."](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\_blank}. - -As a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation. - -## libp2p - -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). - -Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. - -## Light Client - -A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. - -A light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\_blank} server, enabling blockchain users to interact with the network. - -## Metadata - -Data that provides information about one or more aspects of a system. -The metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system. - -## Nominated Proof of Stake (NPoS) - -A method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes. - -## Oracle - -An entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services. - -## Origin - -A [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\_blank}. -## Pallet - -A module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime). -Pallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item). - -## Parachain - -A parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_. -You can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\_blank}. - -## Paseo - -Paseo TestNet provisions testing on Polkadot's "production" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing. - -## Polkadot - -The [Polkadot network](https://polkadot.com/){target=\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain). - -## Polkadot Cloud - -Polkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance. - -## Polkadot Hub - -Polkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3. - -## PolkaVM - -PolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution. - -## Relay Chain - -Relay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another. - -## Rococo - -A [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead. - -## Runtime - -The runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function. - -## Slot +The message consists of three instructions described as follows: -A fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block. +- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. -## Sovereign Account + ```rust + WithdrawAsset((Here, amount).into()), + ``` -The unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem. + - **`Here`**: The native parachain token. + - **`amount`**: The number of tokens that are transferred. -The sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier. + The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. -## SS58 Address Format +- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. -A public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain + ```rust + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + ``` -The [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks + - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. + - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. -## State Transition Function (STF) +- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. -The logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime). + ```rust + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } + ``` -## Storage Item + - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. + +This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. -[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime). -Learn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\_blank} reference document in the Polkadot SDK. +## Overview -## Substrate +XCM revolutionizes cross-chain communication by enabling use cases such as: -A flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\_blank}. +- Token transfers between blockchains. +- Asset locking for cross-chain smart contract interactions. +- Remote execution of functions on other blockchains. -## Transaction +These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. -An [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}. -## Transaction Era +--- -A definable period expressed as a range of block numbers during which a transaction can be included in a block. -Transaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero. +Page Title: Get Tokens from the Official Faucet -## Trie (Patricia Merkle Tree) +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-faucet.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/faucet/ +- Summary: Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. -A data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set. +# Faucet -In Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays. +Test tokens allow you to experiment with smart contracts, test transactions, and validate your dApp functionality without using real cryptocurrency. -## Validator +Polkadot has a faucet that distributes free TestNet tokens to developers for testing purposes: -A validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance. +- Execute transactions on TestNet networks. +- Pay for gas fees when deploying smart contracts. +- Test dApp functionality before MainNet deployment. +- Experiment with blockchain interactions without financial risk. -## WebAssembly (Wasm) -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. +## Get Test Tokens -[Wasm](https://webassembly.org/){target=\_blank} can be compiled from many languages, including -the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state. +For Polkadot Hub TestNet, you can use the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank} to obtain test tokens. Here's how to do it: -## Weight +1. Navigate to the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. If the desired network is not already selected, choose it from the **Network** drop-down. This example uses the Polkadot Hub TestNet. +2. Copy your address linked to the TestNet and paste it into the designated field. +3. Click the **Get Some PASs** button to request free test PAS tokens. These tokens will be sent to your wallet shortly. -A convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block. -Polkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware. +![Polkadot Faucet](/images/smart-contracts/faucet/faucet-1.gif) -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: +## Things to Consider -- Block construction -- Network propagation -- Import and verification +!!! info "Rate Limiting" + Faucets typically implement rate limiting to prevent abuse. You may need to wait between requests if you've recently obtained tokens from the same faucet. -By defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements. +!!! warning "Network Compatibility" + Ensure your wallet is connected to the correct network (Polkadot Hub TestNet) before requesting tokens. Tokens sent to addresses on different networks will not be accessible. -## Westend +## Using Your Test Tokens -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. +Getting started with test tokens is the first step in your Polkadot development journey. These free resources enable you to build, experiment with, and refine your applications without financial constraints, ensuring your projects are robust and ready for deployment on MainNet. --- @@ -5138,271 +4190,73 @@ You can use PAPI to build XCM programs and test them with Chopsticks. --- -Page Title: Interoperability +Page Title: JSON-RPC APIs -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/interoperability/ -- Summary: Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ +- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. -# Interoperability +# JSON-RPC APIs +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions. +Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. -Polkadot’s design ensures that blockchains can transcend their individual limitations by working together as part of a unified system. This cooperative architecture is what sets Polkadot apart in the blockchain landscape. +This guide uses the Polkadot Hub TestNet endpoint: -## Why Interoperability Matters +```text +https://testnet-passet-hub-eth-rpc.polkadot.io +``` -The blockchain ecosystem is inherently fragmented. Different blockchains excel in specialized domains such as finance, gaming, or supply chain management, but these chains function in isolation without interoperability. This lack of connectivity stifles the broader utility of blockchain technology. +## Available Methods -Interoperability solves this problem by enabling blockchains to: +### eth_accounts -- **Collaborate across networks**: Chains can interact to share assets, functionality, and data, creating synergies that amplify their individual strengths. -- **Achieve greater scalability**: Specialized chains can offload tasks to others, optimizing performance and resource utilization. -- **Expand use-case potential**: Cross-chain applications can leverage features from multiple blockchains, unlocking novel user experiences and solutions. +Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. -In the Polkadot ecosystem, interoperability transforms a collection of isolated chains into a cohesive, efficient network, pushing the boundaries of what blockchains can achieve together. +**Parameters**: -## Key Mechanisms for Interoperability +None. -At the core of Polkadot's cross-chain collaboration are foundational technologies designed to break down barriers between networks. These mechanisms empower blockchains to communicate, share resources, and operate as a cohesive ecosystem. +**Example**: -### Cross-Consensus Messaging (XCM): The Backbone of Communication +```bash title="eth_accounts" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_accounts", + "params":[], + "id":1 +}' +``` -Polkadot's Cross-Consensus Messaging (XCM) is the standard framework for interaction between parachains, relay chains, and, eventually, external blockchains. XCM provides a trustless, secure messaging format for exchanging assets, sharing data, and executing cross-chain operations. +--- -Through XCM, decentralized applications can: +### eth_blockNumber -- Transfer tokens and other assets across chains. -- Coordinate complex workflows that span multiple blockchains. -- Enable seamless user experiences where underlying blockchain differences are invisible. -- XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem. +Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. +**Parameters**: -### Bridges: Connecting External Networks +None. -While XCM enables interoperability within the Polkadot ecosystem, bridges extend this functionality to external blockchains such as Ethereum and Bitcoin. By connecting these networks, bridges allow Polkadot-based chains to access external liquidity, additional functionalities, and broader user bases. +**Example**: -With bridges, developers and users gain the ability to: +```bash title="eth_blockNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_blockNumber", + "params":[], + "id":1 +}' +``` -- Integrate external assets into Polkadot-based applications. -- Combine the strengths of Polkadot’s scalability with the liquidity of other networks. -- Facilitate accurate multi-chain applications that transcend ecosystem boundaries. - -For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. - -## The Polkadot Advantage - -Polkadot was purpose-built for interoperability. Unlike networks that add interoperability as an afterthought, Polkadot integrates it as a fundamental design principle. This approach offers several distinct advantages: - -- **Developer empowerment**: Polkadot’s interoperability tools allow developers to build applications that leverage multiple chains’ capabilities without added complexity. -- **Enhanced ecosystem collaboration**: Chains in Polkadot can focus on their unique strengths while contributing to the ecosystem’s overall growth. -- **Future-proofing blockchain**: By enabling seamless communication, Polkadot ensures its ecosystem can adapt to evolving demands and technologies. - -## Looking Ahead - -Polkadot’s vision of interoperability extends beyond technical functionality, representing a shift towards a more collaborative blockchain landscape. By enabling chains to work together, Polkadot fosters innovation, efficiency, and accessibility, paving the way for a decentralized future where blockchains are not isolated competitors but interconnected collaborators. - - ---- - -Page Title: Introduction to XCM - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ -- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. - -# Introduction to XCM - -## Introduction - -Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. - -With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. - -## Messaging Format - -XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. - -XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. - -## The Four Principles of XCM - -XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: - -- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. -- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. -- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. -- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. - -These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. - -## The XCM Tech Stack - -![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) - -The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. - -## Core Functionalities of XCM - -XCM enhances cross-consensus communication by introducing several powerful features: - -- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. -- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. -- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. - -The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. - -## XCM Example - -The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). - -```rust -let message = Xcm(vec![ - WithdrawAsset((Here, amount).into()), - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } -]); -``` - -The message consists of three instructions described as follows: - -- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. - - ```rust - WithdrawAsset((Here, amount).into()), - ``` - - - **`Here`**: The native parachain token. - - **`amount`**: The number of tokens that are transferred. - - The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. - -- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. - - ```rust - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - ``` - - - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. - - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. - -- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. - - ```rust - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } - ``` - - - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. - -This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - -## Overview - -XCM revolutionizes cross-chain communication by enabling use cases such as: - -- Token transfers between blockchains. -- Asset locking for cross-chain smart contract interactions. -- Remote execution of functions on other blockchains. - -These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - - ---- - -Page Title: JSON-RPC APIs - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ -- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. - -# JSON-RPC APIs - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. - -This guide uses the Polkadot Hub TestNet endpoint: - -```text -https://testnet-passet-hub-eth-rpc.polkadot.io -``` - -## Available Methods - -### eth_accounts - -Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_accounts" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_accounts", - "params":[], - "id":1 -}' -``` - ---- - -### eth_blockNumber - -Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_blockNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_blockNumber", - "params":[], - "id":1 -}' -``` - ---- +--- ### eth_call @@ -6496,376 +5350,84 @@ Your existing Solidity knowledge and tooling transfer directly to Polkadot Hub, --- -Page Title: Networks +Page Title: Overview of FRAME -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/networks/ -- Summary: Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md +- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ +- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. -# Networks +# Customize Your Runtime ## Introduction -The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's various networks and explain how they fit into the development workflow. - -## Network Overview +A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. -Polkadot's development process is structured to ensure new features and upgrades are rigorously tested before being deployed on live production networks. The progression follows a well-defined path, starting from local environments and advancing through TestNets, ultimately reaching the Polkadot MainNet. The diagram below outlines the typical progression of the Polkadot development cycle: +This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. -``` mermaid -flowchart LR - id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] - id1[Local] --> id3[Paseo] --> id5[Polkadot] -``` +## Understanding Your Runtime -This flow ensures developers can thoroughly test and iterate without risking real tokens or affecting production networks. Testing tools like [Chopsticks](#chopsticks) and various TestNets make it easier to experiment safely before releasing to production. +The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. -A typical journey through the Polkadot core protocol development process might look like this: +Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. -1. **Local development node**: Development starts in a local environment, where developers can create, test, and iterate on upgrades or new features using a local development node. This stage allows rapid experimentation in an isolated setup without any external dependencies. +## Runtime Architecture -2. **Westend**: After testing locally, upgrades are deployed to [Westend](#westend), Polkadot's primary TestNet. Westend simulates real-world conditions without using real tokens, making it the ideal place for rigorous feature testing before moving on to production networks. +The following diagram shows how FRAME components work together to form your runtime: -3. **Kusama**: Once features have passed extensive testing on Westend, they move to Kusama, Polkadot's experimental and fast-moving "canary" network. Kusama operates as a high-fidelity testing ground with actual economic incentives, giving developers insights into how their features will perform in a real-world environment. +![](/images/parachains/customize-runtime/index/frame-overview-01.webp) -4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network. +The main components are: - In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. +- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. +- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. +- **`frame_system`**: Provides core runtime primitives and storage. +- **`frame_support`**: Utilities and macros that simplify pallet development. -5. **Paseo**: For parachain and dApp developers, Paseo serves as a community-run TestNet that mirrors Polkadot's runtime. Like Westend for core protocol development, Paseo provides a testing ground for parachain development without affecting live networks. +## Building Blocks: Pallets -!!!note - The Rococo TestNet deprecation date was October 14, 2024. Teams should use Westend for Polkadot protocol and feature testing and Paseo for chain development-related testing. +[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. -## Polkadot Development Networks +A pallet can implement virtually any blockchain feature you need: -Development and testing are crucial to building robust dApps and parachains and performing network upgrades within the Polkadot ecosystem. To achieve this, developers can leverage various networks and tools that provide a risk-free environment for experimentation and validation before deploying features to live networks. These networks help avoid the costs and risks associated with real tokens, enabling testing for functionalities like governance, cross-chain messaging, and runtime upgrades. +- Expose new transactions that users can submit. +- Store data on-chain. +- Enforce business rules and validation logic. +- Emit events to notify users of state changes. +- Handle errors gracefully. -## Kusama Network +### Pre-Built Pallets vs. Custom Pallets -Kusama is the experimental version of Polkadot, designed for developers who want to move quickly and test their applications in a real-world environment with economic incentives. Kusama serves as a production-grade testing ground where developers can deploy features and upgrades with the pressure of game theory and economics in mind. It mirrors Polkadot but operates as a more flexible space for innovation. +FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. -The native token for Kusama is KSM. For more information about KSM, visit the [Native Assets](https://wiki.polkadot.com/kusama/kusama-getting-started/){target=\_blank} page. +However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. -## Test Networks +### Pallet Structure -The following test networks provide controlled environments for testing upgrades and new features. TestNet tokens are available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}. +FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. -### Westend +A typical pallet looks like this: -Westend is Polkadot's primary permanent TestNet. Unlike temporary test networks, Westend is not reset to the genesis block, making it an ongoing environment for testing Polkadot core features. Managed by Parity Technologies, Westend ensures that developers can test features in a real-world simulation without using actual tokens. +```rust +pub use pallet::*; -The native token for Westend is WND. More details about WND can be found on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_2){target=\_blank} page. +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; -### Paseo + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); -[Paseo](https://github.com/paseo-network){target=\_blank} is a community-managed TestNet designed for parachain and dApp developers. It mirrors Polkadot's runtime and is maintained by Polkadot community members. Paseo provides a dedicated space for parachain developers to test their applications in a Polkadot-like environment without the risks associated with live networks. + #[pallet::config] // snip + #[pallet::event] // snip + #[pallet::error] // snip + #[pallet::storage] // snip + #[pallet::call] // snip +} +``` -The native token for Paseo is PAS. Additional information on PAS is available on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_1){target=\_blank} page. - -## Local Test Networks - -Local test networks are an essential part of the development cycle for blockchain developers using the Polkadot SDK. They allow for fast, iterative testing in controlled, private environments without connecting to public TestNets. Developers can quickly spin up local instances to experiment, debug, and validate their code before deploying to larger TestNets like Westend or Paseo. Two key tools for local network testing are Zombienet and Chopsticks. - -### Zombienet - -[Zombienet](https://github.com/paritytech/zombienet){target=\_blank} is a flexible testing framework for Polkadot SDK-based blockchains. It enables developers to create and manage ephemeral, short-lived networks. This feature makes Zombienet particularly useful for quick iterations, as it allows you to run multiple local networks concurrently, mimicking different runtime conditions. Whether you're developing a parachain or testing your custom blockchain logic, Zombienet gives you the tools to automate local testing. - -Key features of Zombienet include: - -- Creating dynamic, local networks with different configurations. -- Running parachains and relay chains in a simulated environment. -- Efficient testing of network components like cross-chain messaging and governance. - -Zombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets. - -### Chopsticks - -[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\_blank} is a tool designed to create forks of Polkadot SDK-based blockchains, allowing developers to interact with network forks as part of their testing process. This capability makes Chopsticks a powerful option for testing upgrades, runtime changes, or cross-chain applications in a forked network environment. - -Key features of Chopsticks include: - -- Forking live Polkadot SDK-based blockchains for isolated testing. -- Simulating cross-chain messages in a private, controlled setup. -- Debugging network behavior by interacting with the fork in real-time. - -Chopsticks provides a controlled environment for developers to safely explore the effects of runtime changes. It ensures that network behavior is tested and verified before upgrades are deployed to live networks. - - ---- - -Page Title: Node and Runtime - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/node-and-runtime/ -- Summary: Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. - -# Node and Runtime - -## Introduction - -Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network. - -Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. - -If the system were a monolithic protocol, any modification would require updating the entire system. Instead, Polkadot achieves true upgradeability by defining an immutable meta-protocol (the client) and a protocol (the runtime) that can be upgraded independently. - -This separation gives the [Polkadot Relay Chain](/polkadot-protocol/architecture/polkadot-chain){target=\_blank} and all connected [parachains](/polkadot-protocol/architecture/parachains){target=\_blank} an evolutionary advantage over other blockchain platforms. - -## Architectural Principles - -The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: - -- Client (Meta-protocol): - - Handles the foundational infrastructure of the blockchain. - - Manages runtime execution, networking, consensus, and other off-chain components. - - Provides an immutable base layer that ensures network stability. - - Upgradable only through hard forks. - -- Runtime (Protocol): - - Defines the blockchain's state transition logic. - - Determines the specific rules and behaviors of the blockchain. - - Compiled to WebAssembly (Wasm) for platform-independent execution. - - Capable of being upgraded without network-wide forking. - -### Advantages of this Architecture - -- **Forkless upgrades**: Runtime can be updated without disrupting the entire network. -- **Modularity**: Clear separation allows independent development of client and runtime. -- **Flexibility**: Enables rapid iteration and evolution of blockchain logic. -- **Performance**: WebAssembly compilation provides efficient, cross-platform execution. - -## Node (Client) - -The node, also known as the client, is the core component responsible for executing the Wasm runtime and orchestrating various essential blockchain components. It ensures the correct execution of the state transition function and manages multiple critical subsystems, including: - -- **Wasm execution**: Runs the blockchain runtime, which defines the state transition rules. -- **Database management**: Stores blockchain data. -- **Networking**: Facilitates peer-to-peer communication, block propagation, and transaction gossiping. -- **Transaction pool (Mempool)**: Manages pending transactions before they are included in a block. -- **Consensus mechanism**: Ensures agreement on the blockchain state across nodes. -- **RPC services**: Provides external interfaces for applications and users to interact with the node. - -## Runtime - -The runtime is more than just a set of rules. It's the fundamental logic engine that defines a blockchain's entire behavior. In Polkadot SDK-based blockchains, the runtime represents a complete, self-contained description of the blockchain's state transition function. - -### Characteristics - -The runtime is distinguished by three key characteristics: - -- **Business logic**: Defines the complete application-specific blockchain behavior. -- **WebAssembly compilation**: Ensures platform-independent, secure execution. -- **On-chain storage**: Stored within the blockchain's state, allowing dynamic updates. - -### Key Functions - -The runtime performs several critical functions, such as: - -- Define state transition rules. -- Implement blockchain-specific logic. -- Manage account interactions. -- Control transaction processing. -- Define governance mechanisms. -- Handle custom pallets and modules. - -## Communication Between Node and Runtime - -The client and runtime communicate exclusively using [SCALE-encoded](/polkadot-protocol/parachain-basics/data-encoding){target=\_blank} communication. This ensures efficient and compact data exchange between the two components. - -### Runtime APIs - -The Runtime API consists of well-defined functions and constants a client assumes are implemented in the Runtime Wasm blob. These APIs enable the client to interact with the runtime to execute blockchain operations and retrieve information. The client invokes these APIs to: - -- Build, execute, and finalize blocks. -- Access metadata. -- Access consensus related information. -- Handle transaction execution. - -### Host Functions - -During execution, the runtime can access certain external client functionalities via host functions. The specific functions the client exposes allow the runtime to perform operations outside the WebAssembly domain. Host functions enable the runtime to: - -- Perform cryptographic operations. -- Access the current blockchain state. -- Handle storage modifications. -- Allocate memory. - - ---- - -Page Title: On-Chain Governance Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md -- Canonical (HTML): https://docs.polkadot.com/reference/governance/ -- Summary: Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. - -# On-Chain Governance - -## Introduction - -Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model. - -This guide will explain the principles and structure of OpenGov and walk you through its key components, such as Origins, Tracks, and Delegation. You will learn about improvements over earlier governance systems, including streamlined voting processes and enhanced stakeholder participation. - -With OpenGov, Polkadot achieves a flexible, scalable, and democratic governance framework that allows multiple proposals to proceed simultaneously, ensuring the network evolves in alignment with its community's needs. - -## Governance Evolution - -Polkadot’s governance journey began with [Governance V1](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#governance-summary){target=\_blank}, a system that proved effective in managing treasury funds and protocol upgrades. However, it faced limitations, such as: - -- Slow voting cycles, causing delays in decision-making. -- Inflexibility in handling multiple referendums, restricting scalability. - -To address these challenges, Polkadot introduced OpenGov, a governance model designed for greater inclusivity, efficiency, and scalability. OpenGov replaces the centralized structures of Governance V1, such as the Council and Technical Committee, with a fully decentralized and dynamic framework. - -For a full comparison of the historic and current governance models, visit the [Gov1 vs. Polkadot OpenGov](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#gov1-vs-polkadot-opengov){target=\_blank} section of the Polkadot Wiki. - -## OpenGov Key Features - -OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: - -- **Decentralization**: Shifts all decision-making power to the public, ensuring a more democratic process. -- **Enhanced delegation**: Allows users to delegate their votes to trusted experts across specific governance tracks. -- **Simultaneous referendums**: Multiple proposals can progress at once, enabling faster decision-making. -- **Polkadot Technical Fellowship**: A broad, community-driven group replacing the centralized Technical Committee. - -This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. - -## Origins and Tracks - -In OpenGov, origins and tracks are central to managing proposals and votes. - -- **Origin**: Determines the authority level of a proposal (e.g., Treasury, Root) which decides the track of all referendums from that origin. -- **Track**: Define the procedural flow of a proposal, such as voting duration, approval thresholds, and enactment timelines. - -Developers must be aware that referendums from different origins and tracks will take varying amounts of time to reach approval and enactment. The [Polkadot Technical Fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} has the option to shorten this timeline by whitelisting a proposal and allowing it to be enacted through the [Whitelist Caller](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#whitelisted-caller){target=\_blank} origin. - -Visit [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#origins-and-tracks){target=\_blank} for details on current origins and tracks, associated terminology, and parameters. - -## Referendums - -In OpenGov, anyone can submit a referendum, fostering an open and participatory system. The timeline for a referendum depends on the privilege level of the origin with more significant changes offering more time for community voting and participation before enactment. - -The timeline for an individual referendum includes four distinct periods: - -- **Lead-in**: A minimum amount of time to allow for community participation, available room in the origin, and payment of the decision deposit. Voting is open during this period. -- **Decision**: Voting continues. -- **Confirmation**: Referendum must meet [approval and support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} criteria during entire period to avoid rejection. -- **Enactment**: Changes approved by the referendum are executed. - -### Vote on Referendums - -Voters can vote with their tokens on each referendum. Polkadot uses a voluntary token locking mechanism, called conviction voting, as a way for voters to increase their voting power. A token holder signals they have a stronger preference for approving a proposal based upon their willingness to lock up tokens. Longer voluntary token locks are seen as a signal of continual approval and translate to increased voting weight. - -See [Voting on a Referendum](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank} for a deeper look at conviction voting and related token locks. - -### Delegate Voting Power - -The OpenGov system also supports multi-role delegations, allowing token holders to assign their voting power on different tracks to entities with expertise in those areas. - -For example, if a token holder lacks the technical knowledge to evaluate proposals on the [Root track](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#root){target=\_blank}, they can delegate their voting power for that track to an expert they trust to vote in the best interest of the network. This ensures informed decision-making across tracks while maintaining flexibility for token holders. - -Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. - -### Cancel a Referendum - -Polkadot OpenGov has two origins for rejecting ongoing referendums: - -- [**Referendum Canceller**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-canceller){target=\_blank}: Cancels an active referendum when non-malicious errors occur and refunds the deposits to the originators. -- [**Referendum Killer**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-killer){target=\_blank}: Used for urgent, malicious cases this origin instantly terminates an active referendum and slashes deposits. - -See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. - -## Additional Resources - -- **[Democracy pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/democracy/src){target=\_blank}**: Handles administration of general stakeholder voting. -- **[Gov2: Polkadot’s Next Generation of Decentralised Governance](https://medium.com/polkadot-network/gov2-polkadots-next-generation-of-decentralised-governance-4d9ef657d11b){target=\_blank}**: Medium article by Gavin Wood. -- **[Polkadot Direction](https://matrix.to/#/#Polkadot-Direction:parity.io){target=\_blank}**: Matrix Element client. -- **[Polkassembly](https://polkadot.polkassembly.io/){target=\_blank}**: OpenGov dashboard and UI. -- **[Polkadot.js Apps Governance](https://polkadot.js.org/apps/#/referenda){target=\_blank}**: Overview of active referendums. - - ---- - -Page Title: Overview of FRAME - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md -- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ -- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. - -# Customize Your Runtime - -## Introduction - -A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. - -This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. - -## Understanding Your Runtime - -The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. - -Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. - -## Runtime Architecture - -The following diagram shows how FRAME components work together to form your runtime: - -![](/images/parachains/customize-runtime/index/frame-overview-01.webp) - -The main components are: - -- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. -- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. -- **`frame_system`**: Provides core runtime primitives and storage. -- **`frame_support`**: Utilities and macros that simplify pallet development. - -## Building Blocks: Pallets - -[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. - -A pallet can implement virtually any blockchain feature you need: - -- Expose new transactions that users can submit. -- Store data on-chain. -- Enforce business rules and validation logic. -- Emit events to notify users of state changes. -- Handle errors gracefully. - -### Pre-Built Pallets vs. Custom Pallets - -FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. - -However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. - -### Pallet Structure - -FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. - -A typical pallet looks like this: - -```rust -pub use pallet::*; - -#[frame_support::pallet] -pub mod pallet { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - #[pallet::config] // snip - #[pallet::event] // snip - #[pallet::error] // snip - #[pallet::storage] // snip - #[pallet::call] // snip -} -``` - -Every pallet can implement these core macros: +Every pallet can implement these core macros: - **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. - **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. @@ -6879,967 +5441,45 @@ For a comprehensive reference, see the [`pallet_macros` documentation](https://p ## How Runtime Customization Works -Customizing your runtime typically follows these patterns: - -**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. - -**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. - -**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. - -**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. - -The following diagram illustrates how pallets combine to form a complete runtime: - -![](/images/parachains/customize-runtime/index/frame-overview-02.webp) - -## Starting Templates - -The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. - -- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. - -- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. - -- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. - -- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. - -## Key Customization Scenarios - -This section covers the most common customization patterns you'll encounter: - -- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. - -- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. - -- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. - -- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. - -- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. - - ---- - -Page Title: Overview of the Polkadot Relay Chain - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/ -- Summary: Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. - -# Overview - -## Introduction - -Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank}, and cross-chain interactions via its native [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank}. - -This guide covers key aspects of Polkadot’s architecture, including its high-level protocol structure, blockspace commoditization, and the role of its native token, DOT, in governance, staking, and resource allocation. - -## Polkadot 1.0 - -Polkadot 1.0 represents the state of Polkadot as of 2023, coinciding with the release of [Polkadot runtime v1.0.0](https://github.com/paritytech/polkadot/releases/tag/v1.0.0){target=\_blank}. This section will focus on Polkadot 1.0, along with philosophical insights into network resilience and blockspace. - -As a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including: - -- **Application-specific Layer-1 blockchains (parachains)**: Polkadot's sharded network allows for parallel transaction processing, with shards that can have unique state transition functions, enabling custom-built L1 chains optimized for specific applications. - -- **Shared security and scalability**: L1 chains connected to Polkadot benefit from its [Nominated Proof of Stake (NPoS)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#nominated-proof-of-stake){target=\_blank} system, providing security out-of-the-box without the need to bootstrap their own. - -- **Secure interoperability**: Polkadot's native interoperability enables seamless data and value exchange between parachains. This interoperability can also be used outside of the ecosystem for bridging with external networks. - -- **Resilient infrastructure**: Decentralized and scalable, Polkadot ensures ongoing support for development and community initiatives via its on-chain [treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} and governance. - -- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. - -- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. - - - [Polkadot Blockchain Academy](https://polkadot.com/blockchain-academy){target=\_blank} - - [EdX courses](https://www.edx.org/school/web3x){target=\_blank} - - Rust and Substrate courses (coming soon) - -### High-Level Architecture - -Polkadot features a chain that serves as the central component of the system. This chain is depicted as a ring encircled by several parachains that are connected to it. - -According to Polkadot's design, any blockchain that can compile to WebAssembly (Wasm) and adheres to the Parachains Protocol becomes a parachain on the Polkadot network. - -Here’s a high-level overview of the Polkadot protocol architecture: - -![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } - -Parachains propose blocks to Polkadot validators, who check for availability and validity before finalizing them. With the relay chain providing security, collators—full nodes of parachains—can focus on their tasks without needing strong incentives. - -The [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank} allows parachains to exchange messages freely, leveraging the chain's security for trust-free communication. - -In order to interact with chains that want to use their own finalization process (e.g., Bitcoin), Polkadot has [bridges](/reference/parachains/interoperability/#bridges-connecting-external-networks){target=\_blank} that offer two-way compatibility, meaning that transactions can be made between different parachains. - -### Polkadot's Additional Functionalities - -Historically, obtaining core slots on Polkadot chain relied upon crowdloans and auctions. Chain cores were leased through auctions for three-month periods, up to a maximum of two years. Crowdloans enabled users to securely lend funds to teams for lease deposits in exchange for pre-sale tokens, which is the only way to access slots on Polkadot 1.0. Auctions are now deprecated in favor of [coretime](/polkadot-protocol/architecture/system-chains/coretime/){target=\_blank}. - -Additionally, the chain handles [staking](https://wiki.polkadot.com/learn/learn-staking/){target=\_blank}, [accounts](/reference/parachains/accounts/){target=\_blank}, balances, and [governance](/reference/governance/){target=\_blank}. - -#### Agile Coretime - -The new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. - -[Agile coretime](/reference/polkadot-hub/consensus-and-security/agile-coretime/){target=\_blank} improves the efficient use of Polkadot's network resources and offers economic flexibility for developers, extending Polkadot's capabilities far beyond the original vision outlined in the [whitepaper](https://polkadot.com/papers/Polkadot-whitepaper.pdf){target=\_blank}. - -It enables parachains to purchase monthly "bulk" allocations of coretime (the time allocated for utilizing a core, measured in Polkadot relay chain blocks), ensuring heavy-duty parachains that can author a block every six seconds with [Asynchronous Backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} can reliably renew their coretime each month. Although six-second block times are now the default, parachains have the option of producing blocks less frequently. - -Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. - -### Polkadot's Resilience - -Decentralization is a vital component of blockchain networks, but it comes with trade-offs: - -- An overly decentralized network may face challenges in reaching consensus and require significant energy to operate. -- Also, a network that achieves consensus quickly risks centralization, making it easier to manipulate or attack. - -A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. - -Polkadot 1.0 currently achieves resilience through several strategies: - -- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. - -- **Decentralized nodes**: Designed to encourage operators to join the network. This program aims to expand and diversify the validators in the ecosystem who aim to become independent of the program during their term. Feel free to explore more about the program on the official [Decentralized Nodes](https://nodes.web3.foundation/){target=\_blank} page. - -- **On-chain treasury and governance**: Known as [OpenGov](/reference/governance/){target=\_blank}, this system allows every decision to be made through public referenda, enabling any token holder to cast a vote. - -### Polkadot's Blockspace - -Polkadot 1.0’s design allows for the commoditization of blockspace. - -Blockspace is a blockchain's capacity to finalize and commit operations, encompassing its security, computing, and storage capabilities. Its characteristics can vary across different blockchains, affecting security, flexibility, and availability. - -- **Security**: Measures the robustness of blockspace in Proof of Stake (PoS) networks linked to the stake locked on validator nodes, the variance in stake among validators, and the total number of validators. It also considers social centralization (how many validators are owned by single operators) and physical centralization (how many validators run on the same service provider). - -- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes. - -- **Availability**: Indicates how easily users can access blockspace. It should be easily accessible, allowing diverse business models to thrive, ideally regulated by a marketplace based on demand and supplemented by options for "second-hand" blockspace. - -Polkadot is built on core blockspace principles, but there's room for improvement. Tasks like balance transfers, staking, and governance are managed on the relay chain. - -Delegating these responsibilities to [system chains](/polkadot-protocol/architecture/system-chains/){target=\_blank} could enhance flexibility and allow the relay chain to concentrate on providing shared security and interoperability. - -For more information about blockspace, watch [Robert Habermeier’s interview](https://www.youtube.com/watch?v=e1vISppPwe4){target=\_blank} or read his [technical blog post](https://www.rob.tech/blog/polkadot-blockspace-over-blockchains/){target=\_blank}. - -## DOT Token - -DOT is the native token of the Polkadot network, much like BTC for Bitcoin and Ether for the Ethereum blockchain. DOT has 10 decimals, uses the Planck base unit, and has a balance type of `u128`. The same is true for Kusama's KSM token with the exception of having 12 decimals. - -### Redenomination of DOT - -Polkadot conducted a community poll, which ended on 27 July 2020 at block 888,888, to decide whether to redenominate the DOT token. The stakeholders chose to redenominate the token, changing the value of 1 DOT from 1e12 plancks to 1e10 plancks. - -Importantly, this did not affect the network's total number of base units (plancks); it only affects how a single DOT is represented. The redenomination became effective 72 hours after transfers were enabled, occurring at block 1,248,328 on 21 August 2020 around 16:50 UTC. - -### The Planck Unit - -The smallest unit of account balance on Polkadot SDK-based blockchains (such as Polkadot and Kusama) is called _Planck_, named after the Planck length, the smallest measurable distance in the physical universe. - -Similar to how BTC's smallest unit is the Satoshi and ETH's is the Wei, Polkadot's native token DOT equals 1e10 Planck, while Kusama's native token KSM equals 1e12 Planck. - -### Uses for DOT - -DOT serves three primary functions within the Polkadot network: - -- **Governance**: It is used to participate in the governance of the network. -- **Staking**: DOT is staked to support the network's operation and security. -- **Buying coretime**: Used to purchase coretime in-bulk or on-demand and access the chain to benefit from Polkadot's security and interoperability. - -Additionally, DOT can serve as a transferable token. For example, DOT, held in the treasury, can be allocated to teams developing projects that benefit the Polkadot ecosystem. - -## JAM and the Road Ahead - -The Join-Accumulate Machine (JAM) represents a transformative redesign of Polkadot's core architecture, envisioned as the successor to the current relay chain. Unlike traditional blockchain architectures, JAM introduces a unique computational model that processes work through two primary functions: - -- **Join**: Handles data integration. -- **Accumulate**: Folds computations into the chain's state. - -JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: - -- **Permissionless code execution**: JAM is designed to be more generic and flexible, allowing for permissionless code execution through services that can be deployed without governance approval. -- **More effective block time utilization**: JAM's efficient pipeline processing model places the prior state root in block headers instead of the posterior state root, enabling more effective utilization of block time for computations. - -This architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes. - - ---- - -Page Title: Parachains Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/ -- Summary: Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. - -# Parachains Overview - -## Introduction - -A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network. - -Unlike standalone blockchains that must bootstrap their own validator sets and security, parachains leverage Polkadot's pooled security model. This allows parachain developers to focus on their application-specific functionality rather than consensus and security infrastructure. Parachains can communicate with each other through Cross-Consensus Messaging (XCM), enabling seamless interoperability across the Polkadot ecosystem. - -Key capabilities that parachains provide include: - -- **Shared security**: Inherit security from Polkadot's validator set without maintaining your own. -- **Interoperability**: Communicate trustlessly with other parachains via XCM. -- **Scalability**: Process transactions in parallel with other parachains. -- **Customization**: Build application-specific logic tailored to your use case. -- **Upgradeability**: Upgrade runtime logic without hard forks. - -## Polkadot SDK: Parachain Architecture - -Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: - -![](/images/reference/parachains/index/overview-01.webp) - -- **[Substrate](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html){target=\_blank}**: The foundation providing core blockchain primitives and libraries. -- **[FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank}**: A modular framework for building your parachain's runtime logic. -- **[Cumulus](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html){target=\_blank}**: Essential libraries and pallets that enable parachain functionality. -- **[XCM (Cross Consensus Messaging)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/xcm/index.html){target=\_blank}**: The messaging format for communicating with other parachains and the relay chain. -- **[Polkadot](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/polkadot/index.html){target=\_blank}**: The relay chain that provides security and coordination. - -### Substrate: The Foundation - -Substrate provides the core infrastructure that every parachain is built upon. It handles the low-level blockchain functionality, allowing you to focus on your application's unique features. Substrate includes implementations for networking, database management, consensus participation, and the execution environment for your runtime. - -Every Polkadot SDK node consists of two main components: - -- **Client (Host)**: Handles infrastructure services. - - - Native binary that runs on validator and collator nodes. - - Executes the Wasm-compiled runtime. - - Manages networking, database, mempool, and block production. - - Interfaces with the relay chain for validation. - -- **Runtime (State Transition Function)**: Contains your business logic. - - - Defines how your Polkadot SDK node processes transactions. - - Compiled to [Wasm](https://webassembly.org/){target=\_blank} for deterministic execution. - - Stored on-chain and upgradeable via governance. - -```mermaid -%%{init: {'flowchart': {'padding': 5, 'nodeSpacing': 50, 'rankSpacing': 10}}}%% -graph TB - classDef title font-size:20px,font-weight:bold,stroke-width:0px - classDef clientStyle font-size:16px,font-weight:bold - classDef clientSubNodeStyle margin-top:10px - classDef runtimeCallExecutorStyle padding-top:10px - - subgraph sg1[Parachain
    Node] - direction TB - - I[RuntimeCall Executor] - B[Wasm Runtime - STF] - - subgraph sg2[Client] - direction TB - C[Network and Blockchain
    Infrastructure Services
    + Relay Chain Interface] - end - - I --> B - end - - class sg1 title - class sg2 clientStyle - class C clientSubNodeStyle - class I runtimeCallExecutorStyle - -``` - -### FRAME: Building Blocks for Your Runtime - -FRAME provides modular components called [pallets](/reference/glossary#pallet){target=\_blank} that you can compose to build your parachain's runtime. Each pallet provides specific functionality that you can customize and configure for your needs. This modular approach allows you to quickly assemble complex functionality without writing everything from scratch. - -```mermaid -graph LR - subgraph SP["Parachain Runtime"] - direction LR - Timestamp ~~~ Aura ~~~ ParachainSystem - Balances ~~~ TransactionPayment ~~~ Sudo - subgraph Timestamp["Timestamp"] - SS1[Custom Config] - end - subgraph Aura["Aura"] - SS2[Custom Config] - end - subgraph ParachainSystem["Parachain System"] - SS3[Custom Config] - end - subgraph Balances["Balances"] - SS4[Custom Config] - end - subgraph TransactionPayment["Transaction Payment"] - SS5[Custom Config] - end - subgraph Sudo["Sudo"] - SS6[Custom Config] - end - style Timestamp stroke:#FF69B4 - style Aura stroke:#FF69B4 - style ParachainSystem stroke:#FF69B4 - style Balances stroke:#FF69B4 - style TransactionPayment stroke:#FF69B4 - style Sudo stroke:#FF69B4 - style SS1 stroke-dasharray: 5 - style SS2 stroke-dasharray: 5 - style SS3 stroke-dasharray: 5 - style SS4 stroke-dasharray: 5 - style SS5 stroke-dasharray: 5 - style SS6 stroke-dasharray: 5 - - end - subgraph AP["Available FRAME Pallets"] - direction LR - A1[Aura]~~~A2[Parachain
    System]~~~A3[Transaction
    Payment]~~~A4[Sudo] - B1[Identity]~~~B2[Balances]~~~B3[Assets]~~~B4[EVM] - C1[Timestamp]~~~C2[Staking]~~~C3[Contracts]~~~C4[and more...] - end - AP --> SP -``` - -### Cumulus: Parachain-Specific Functionality - -Cumulus is what transforms a Polkadot SDK-based runtime into a parachain-capable runtime. It provides the essential components for communicating with the relay chain, participating in Polkadot's consensus, and handling parachain-specific operations like block validation and collation. - -Key Cumulus components include: - -- **Parachain system pallet**: Core parachain functionality and relay chain communication. -- **Collator consensus**: Block production logic for parachain collators. -- **Relay chain interface**: APIs for interacting with the Polkadot relay chain. -- **Validation data**: Handling proof-of-validity data required by relay chain validators. - -## Where to Go Next - -Building a parachain requires understanding the relationship between your chain and the Polkadot relay chain. The Polkadot SDK provides all the tools needed to design custom runtime logic, enable cross-chain communication, and deploy your parachain to production. - -The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. - -
    - -- Guide __Launch a Simple Parachain__ - - --- - - Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. - - [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) - - -- Guide __Customize Your Runtime__ - - --- - - Design your parachain's runtime logic and choose appropriate pallets for your use case. - - [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) - -- Guide __Interoperability__ - - --- - - Implement XCM for trustless cross-chain communication with other parachains. - - [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/) - -- Guide __Runtime Upgrades__ - - --- - - Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. - - [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) - -
    - - ---- - -Page Title: Polkadot SDK Accounts - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/accounts/ -- Summary: Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. - -# Accounts - -## Introduction - -Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains. - -This page will guide you through the essential aspects of accounts, including their data structure, balance types, reference counters, and address formats. You’ll learn how accounts are managed within the runtime, how balances are categorized, and how addresses are encoded and validated. - -## Account Data Structure - -Accounts are foundational to any blockchain, and the Polkadot SDK provides a flexible management system. This section explains how the Polkadot SDK defines accounts and manages their lifecycle through data structures within the runtime. - -### Account - -The [`Account` data type](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/type.Account.html){target=\_blank} is a storage map within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank} that links an account ID to its corresponding data. This structure is fundamental for mapping account-related information within the chain. - -The code snippet below shows how accounts are defined: - -```rs - /// The full account information for a particular account ID. - #[pallet::storage] - #[pallet::getter(fn account)] - pub type Account = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - AccountInfo, - ValueQuery, - >; -``` - -The preceding code block defines a storage map named `Account`. The `StorageMap` is a type of on-chain storage that maps keys to values. In the `Account` map, the key is an account ID, and the value is the account's information. Here, `T` represents the generic parameter for the runtime configuration, which is defined by the pallet's configuration trait (`Config`). - -The `StorageMap` consists of the following parameters: - -- **`_`**: Used in macro expansion and acts as a placeholder for the storage prefix type. Tells the macro to insert the default prefix during expansion. -- **`Blake2_128Concat`**: The hashing function applied to keys in the storage map. -- **`T: :AccountId`**: Represents the key type, which corresponds to the account’s unique ID. -- **`AccountInfo`**: The value type stored in the map. For each account ID, the map stores an `AccountInfo` struct containing: - - - **`T::Nonce`**: A nonce for the account, which is incremented with each transaction to ensure transaction uniqueness. - - **`T: :AccountData`**: Custom account data defined by the runtime configuration, which could include balances, locked funds, or other relevant information. - -- **`ValueQuery`**: Defines how queries to the storage map behave when no value is found; returns a default value instead of `None`. - -For a detailed explanation of storage maps, see the [`StorageMap`](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/struct.StorageMap.html){target=\_blank} entry in the Rust docs. - -### Account Info - -The `AccountInfo` structure is another key element within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank}, providing more granular details about each account's state. This structure tracks vital data, such as the number of transactions and the account’s relationships with other modules. - -```rs -/// Information of an account. -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct AccountInfo { - /// The number of transactions this account has sent. - pub nonce: Nonce, - /// The number of other modules that currently depend on this account's existence. The account - /// cannot be reaped until this is zero. - pub consumers: RefCount, - /// The number of other modules that allow this account to exist. The account may not be reaped - /// until this and `sufficients` are both zero. - pub providers: RefCount, - /// The number of modules that allow this account to exist for their own purposes only. The - /// account may not be reaped until this and `providers` are both zero. - pub sufficients: RefCount, - /// The additional data that belongs to this account. Used to store the balance(s) in a lot of - /// chains. - pub data: AccountData, -} -``` - -The `AccountInfo` structure includes the following components: - -- **`nonce`**: Tracks the number of transactions initiated by the account, which ensures transaction uniqueness and prevents replay attacks. -- **`consumers`**: Counts how many other modules or pallets rely on this account’s existence. The account cannot be removed from the chain (reaped) until this count reaches zero. -- **`providers`**: Tracks how many modules permit this account’s existence. An account can only be reaped once both `providers` and `sufficients` are zero. -- **`sufficients`**: Represents the number of modules that allow the account to exist for internal purposes, independent of any other modules. -- **`AccountData`**: A flexible data structure that can be customized in the runtime configuration, usually containing balances or other user-specific data. - -This structure helps manage an account's state and prevents its premature removal while it is still referenced by other on-chain data or modules. The [`AccountInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.AccountInfo.html){target=\_blank} structure can vary as long as it satisfies the trait bounds defined by the `AccountData` associated type in the [`frame-system::pallet::Config`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/trait.Config.html){target=\_blank} trait. - -### Account Reference Counters - -Polkadot SDK uses reference counters to track an account’s dependencies across different runtime modules. These counters ensure that accounts remain active while data is associated with them. - -The reference counters include: - -- **`consumers`**: Prevents account removal while other pallets still rely on the account. -- **`providers`**: Ensures an account is active before other pallets store data related to it. -- **`sufficients`**: Indicates the account’s independence, ensuring it can exist even without a native token balance, such as when holding sufficient alternative assets. - -#### Providers Reference Counters - -The `providers` counter ensures that an account is ready to be depended upon by other runtime modules. For example, it is incremented when an account has a balance above the existential deposit, which marks the account as active. - -The system requires this reference counter to be greater than zero for the `consumers` counter to be incremented, ensuring the account is stable before any dependencies are added. - -#### Consumers Reference Counters - -The `consumers` counter ensures that the account cannot be reaped until all references to it across the runtime have been removed. This check prevents the accidental deletion of accounts that still have active on-chain data. - -It is the user’s responsibility to clear out any data from other runtime modules if they wish to remove their account and reclaim their existential deposit. - -#### Sufficients Reference Counter - -The `sufficients` counter tracks accounts that can exist independently without relying on a native account balance. This is useful for accounts holding other types of assets, like tokens, without needing a minimum balance in the native token. - -For instance, the [Assets pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank}, may increment this counter for an account holding sufficient tokens. - -#### Account Deactivation - -In Polkadot SDK-based chains, an account is deactivated when its reference counters (such as `providers`, `consumers`, and `sufficient`) reach zero. These counters ensure the account remains active as long as other runtime modules or pallets reference it. - -When all dependencies are cleared and the counters drop to zero, the account becomes deactivated and may be removed from the chain (reaped). This is particularly important in Polkadot SDK-based blockchains, where accounts with balances below the existential deposit threshold are pruned from storage to conserve state resources. - -Each pallet that references an account has cleanup functions that decrement these counters when the pallet no longer depends on the account. Once these counters reach zero, the account is marked for deactivation. - -#### Updating Counters - -The Polkadot SDK provides runtime developers with various methods to manage account lifecycle events, such as deactivation or incrementing reference counters. These methods ensure that accounts cannot be reaped while still in use. - -The following helper functions manage these counters: - -- **`inc_consumers()`**: Increments the `consumer` reference counter for an account, signaling that another pallet depends on it. -- **`dec_consumers()`**: Decrements the `consumer` reference counter, signaling that a pallet no longer relies on the account. -- **`inc_providers()`**: Increments the `provider` reference counter, ensuring the account remains active. -- **`dec_providers()`**: Decrements the `provider` reference counter, allowing for account deactivation when no longer in use. -- **`inc_sufficients()`**: Increments the `sufficient` reference counter for accounts that hold sufficient assets. -- **`dec_sufficients()`**: Decrements the `sufficient` reference counter. - -To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. - -The `System` pallet offers three query functions to assist developers in tracking account states: - -- **[`can_inc_consumer()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_inc_consumer){target=\_blank}**: Checks if the account can safely increment the consumer reference. -- **[`can_dec_provider()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_dec_provider){target=\_blank}**: Ensures that no consumers exist before allowing the decrement of the provider counter. -- **[`is_provider_required()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.is_provider_required){target=\_blank}**: Verifies whether the account still has any active consumer references. - -This modular and flexible system of reference counters tightly controls the lifecycle of accounts in Polkadot SDK-based blockchains, preventing the accidental removal or retention of unneeded accounts. You can refer to the [System pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html){target=\_blank} for more details. - - -## Account Balance Types - -In the Polkadot ecosystem, account balances are categorized into different types based on how the funds are utilized and their availability. These balance types determine the actions that can be performed, such as transferring tokens, paying transaction fees, or participating in governance activities. Understanding these balance types helps developers manage user accounts and implement balance-dependent logic. - -!!! note "A more efficient distribution of account balance types is in development" - Soon, pallets in the Polkadot SDK will implement the [`Fungible` trait](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} (see the [tracking issue](https://github.com/paritytech/polkadot-sdk/issues/226){target=\_blank} for more details). For example, the [`transaction-storage`](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_storage/index.html){target=\_blank} pallet changed the implementation of the [`Currency`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/currency/index.html){target=\_blank} trait (see the [Refactor transaction storage pallet to use fungible traits](https://github.com/paritytech/polkadot-sdk/pull/1800){target=\_blank} PR for further details): - - ```rust - type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - ``` - - To the [`Fungible`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} trait: - - ```rust - type BalanceOf = <::Currency as FnInspect<::AccountId>>::Balance; - ``` - - This update will enable more efficient use of account balances, allowing the free balance to be utilized for on-chain activities such as setting proxies and managing identities. - -### Balance Types - -The five main balance types are: - -- **Free balance**: Represents the total tokens available to the account for any on-chain activity, including staking, governance, and voting. However, it may not be fully spendable or transferrable if portions of it are locked or reserved. -- **Locked balance**: Portions of the free balance that cannot be spent or transferred because they are tied up in specific activities like [staking](https://wiki.polkadot.com/learn/learn-staking/#nominating-validators){target=\_blank}, [vesting](https://wiki.polkadot.com/learn/learn-guides-transfers/#vested-transfers-with-the-polkadot-js-ui){target=\_blank}, or participating in [governance](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank}. While the tokens remain part of the free balance, they are non-transferable for the duration of the lock. -- **Reserved balance**: Funds locked by specific system actions, such as setting up an [identity](https://wiki.polkadot.com/learn/learn-identity/){target=\_blank}, creating [proxies](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}, or submitting [deposits for governance proposals](https://wiki.polkadot.com/learn/learn-guides-polkadot-opengov/#claiming-opengov-deposits){target=\_blank}. These tokens are not part of the free balance and cannot be spent unless they are unreserved. -- **Spendable balance**: The portion of the free balance that is available for immediate spending or transfers. It is calculated by subtracting the maximum of locked or reserved amounts from the free balance, ensuring that existential deposit limits are met. -- **Untouchable balance**: Funds that cannot be directly spent or transferred but may still be utilized for on-chain activities, such as governance participation or staking. These tokens are typically tied to certain actions or locked for a specific period. - -The spendable balance is calculated as follows: - -```text -spendable = free - max(locked - reserved, ED) -``` - -Here, `free`, `locked`, and `reserved` are defined above. The `ED` represents the [existential deposit](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank}, the minimum balance required to keep an account active and prevent it from being reaped. You may find you can't see all balance types when looking at your account via a wallet. Wallet providers often display only spendable, locked, and reserved balances. - -### Locks - -Locks are applied to an account's free balance, preventing that portion from being spent or transferred. Locks are automatically placed when an account participates in specific on-chain activities, such as staking or governance. Although multiple locks may be applied simultaneously, they do not stack. Instead, the largest lock determines the total amount of locked tokens. - -Locks follow these basic rules: - -- If different locks apply to varying amounts, the largest lock amount takes precedence. -- If multiple locks apply to the same amount, the lock with the longest duration governs when the balance can be unlocked. - -#### Locks Example - -Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: - -- 80 DOT is staked with a 28-day lock period. -- 24 DOT is locked for governance with a 1x conviction and a 7-day lock period. -- 4 DOT is locked for governance with a 6x conviction and a 224-day lock period. - -In this case, the total locked amount is 80 DOT because only the largest lock (80 DOT from staking) governs the locked balance. These 80 DOT will be released at different times based on the lock durations. In this example, the 24 DOT locked for governance will be released first since the shortest lock period is seven days. The 80 DOT stake with a 28-day lock period is released next. Now, all that remains locked is the 4 DOT for governance. After 224 days, all 80 DOT (minus the existential deposit) will be free and transferable. - -![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) - -#### Edge Cases for Locks - -In scenarios where multiple convictions and lock periods are active, the lock duration and amount are determined by the longest period and largest amount. For example, if you delegate with different convictions and attempt to undelegate during an active lock period, the lock may be extended for the full amount of tokens. For a detailed discussion on edge case lock behavior, see this [Stack Exchange post](https://substrate.stackexchange.com/questions/5067/delegating-and-undelegating-during-the-lock-period-extends-it-for-the-initial-am){target=\_blank}. - -### Balance Types on Polkadot.js - -Polkadot.js provides a user-friendly interface for managing and visualizing various account balances on Polkadot and Kusama networks. When interacting with Polkadot.js, you will encounter multiple balance types that are critical for understanding how your funds are distributed and restricted. This section explains how different balances are displayed in the Polkadot.js UI and what each type represents. - -![](/images/reference/parachains/accounts/accounts-02.webp) - -The most common balance types displayed on Polkadot.js are: - -- **Total balance**: The total number of tokens available in the account. This includes all tokens, whether they are transferable, locked, reserved, or vested. However, the total balance does not always reflect what can be spent immediately. In this example, the total balance is 0.6274 KSM. - -- **Transferable balance**: Shows how many tokens are immediately available for transfer. It is calculated by subtracting the locked and reserved balances from the total balance. For example, if an account has a total balance of 0.6274 KSM and a transferable balance of 0.0106 KSM, only the latter amount can be sent or spent freely. - -- **Vested balance**: Tokens that allocated to the account but released according to a specific schedule. Vested tokens remain locked and cannot be transferred until fully vested. For example, an account with a vested balance of 0.2500 KSM means that this amount is owned but not yet transferable. - -- **Locked balance**: Tokens that are temporarily restricted from being transferred or spent. These locks typically result from participating in staking, governance, or vested transfers. In Polkadot.js, locked balances do not stack—only the largest lock is applied. For instance, if an account has 0.5500 KSM locked for governance and staking, the locked balance would display 0.5500 KSM, not the sum of all locked amounts. - -- **Reserved balance**: Refers to tokens locked for specific on-chain actions, such as setting an identity, creating a proxy, or making governance deposits. Reserved tokens are not part of the free balance, but can be freed by performing certain actions. For example, removing an identity would unreserve those funds. - -- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period. - -- **Redeemable balance**: The number of tokens that have completed the unbonding period and are ready to be unlocked and transferred again. For example, if an account has a redeemable balance of 0.1000 KSM, those tokens are now available for spending. - -- **Democracy balance**: Reflects the number of tokens locked for governance activities, such as voting on referenda. These tokens are locked for the duration of the governance action and are only released after the lock period ends. - -By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. - -## Address Formats - -The SS58 address format is a core component of the Polkadot SDK that enables accounts to be uniquely identified across Polkadot-based networks. This format is a modified version of Bitcoin's Base58Check encoding, specifically designed to accommodate the multi-chain nature of the Polkadot ecosystem. SS58 encoding allows each chain to define its own set of addresses while maintaining compatibility and checksum validation for security. - -### Basic Format - -SS58 addresses consist of three main components: - -```text -base58encode(concat(,
    , )) -``` - -- **Address type**: A byte or set of bytes that define the network (or chain) for which the address is intended. This ensures that addresses are unique across different Polkadot SDK-based chains. -- **Address**: The public key of the account encoded as bytes. -- **Checksum**: A hash-based checksum which ensures that addresses are valid and unaltered. The checksum is derived from the concatenated address type and address components, ensuring integrity. - -The encoding process transforms the concatenated components into a Base58 string, providing a compact and human-readable format that avoids easily confused characters (e.g., zero '0', capital 'O', lowercase 'l'). This encoding function ([`encode`](https://docs.rs/bs58/latest/bs58/fn.encode.html){target=\_blank}) is implemented exactly as defined in Bitcoin and IPFS specifications, using the same alphabet as both implementations. - -For more details about the SS58 address format implementation, see the [`Ss58Codec`](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Ss58Codec.html){target=\_blank} trait in the Rust Docs. - -### Address Type - -The address type defines how an address is interpreted and to which network it belongs. Polkadot SDK uses different prefixes to distinguish between various chains and address formats: - -- **Address types `0-63`**: Simple addresses, commonly used for network identifiers. -- **Address types `64-127`**: Full addresses that support a wider range of network identifiers. -- **Address types `128-255`**: Reserved for future address format extensions. - -For example, Polkadot’s main network uses an address type of 0, while Kusama uses 2. This ensures that addresses can be used without confusion between networks. - -The address type is always encoded as part of the SS58 address, making it easy to quickly identify the network. Refer to the [SS58 registry](https://github.com/paritytech/ss58-registry){target=\_blank} for the canonical listing of all address type identifiers and how they map to Polkadot SDK-based networks. - -### Address Length - -SS58 addresses can have different lengths depending on the specific format. Address lengths range from as short as 3 to 35 bytes, depending on the complexity of the address and network requirements. This flexibility allows SS58 addresses to adapt to different chains while providing a secure encoding mechanism. - -| Total | Type | Raw account | Checksum | -|-------|------|-------------|----------| -| 3 | 1 | 1 | 1 | -| 4 | 1 | 2 | 1 | -| 5 | 1 | 2 | 2 | -| 6 | 1 | 4 | 1 | -| 7 | 1 | 4 | 2 | -| 8 | 1 | 4 | 3 | -| 9 | 1 | 4 | 4 | -| 10 | 1 | 8 | 1 | -| 11 | 1 | 8 | 2 | -| 12 | 1 | 8 | 3 | -| 13 | 1 | 8 | 4 | -| 14 | 1 | 8 | 5 | -| 15 | 1 | 8 | 6 | -| 16 | 1 | 8 | 7 | -| 17 | 1 | 8 | 8 | -| 35 | 1 | 32 | 2 | - -SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. - -### Checksum Types - -A checksum is applied to validate SS58 addresses. Polkadot SDK uses a Blake2b-512 hash function to calculate the checksum, which is appended to the address before encoding. The checksum length can vary depending on the address format (e.g., 1-byte, 2-byte, or longer), providing varying levels of validation strength. - -The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. - -### Validating Addresses - -SS58 addresses can be validated using the subkey command-line interface or the Polkadot.js API. These tools help ensure an address is correctly formatted and valid for the intended network. The following sections will provide an overview of how validation works with these tools. - -#### Using Subkey - -[Subkey](https://paritytech.github.io/polkadot-sdk/master/subkey/index.html){target=\_blank} is a CLI tool provided by Polkadot SDK for generating and managing keys. It can inspect and validate SS58 addresses. - -The `inspect` command gets a public key and an SS58 address from the provided secret URI. The basic syntax for the `subkey inspect` command is: - -```bash -subkey inspect [flags] [options] uri -``` - -For the `uri` command-line argument, you can specify the secret seed phrase, a hex-encoded private key, or an SS58 address. If the input is a valid address, the `subkey` program displays the corresponding hex-encoded public key, account identifier, and SS58 addresses. - -For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: - -```bash -subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" -``` - -The command displays output similar to the following: - -
    - subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" - Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account: - Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849 - Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR - Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - SS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR -
    - -The `subkey` program assumes an address is based on a public/private key pair. If you inspect an address, the command returns the 32-byte account identifier. - -However, not all addresses in Polkadot SDK-based networks are based on keys. - -Depending on the command-line options you specify and the input you provided, the command output might also display the network for which the address has been encoded. For example: - -```bash -subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" -``` - -The command displays output similar to the following: - -
    - subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" - Public Key URI `12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU` is account: - Network ID/Version: polkadot - Public key (hex): 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Account ID: 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Public key (SS58): 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU - SS58 Address: 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU -
    - -#### Using Polkadot.js API - -To verify an address in JavaScript or TypeScript projects, you can use the functions built into the [Polkadot.js API](https://polkadot.js.org/docs/){target=\_blank}. For example: - -```js -// Import Polkadot.js API dependencies -const { decodeAddress, encodeAddress } = require('@polkadot/keyring'); -const { hexToU8a, isHex } = require('@polkadot/util'); - -// Specify an address to test. -const address = 'INSERT_ADDRESS_TO_TEST'; - -// Check address -const isValidSubstrateAddress = () => { - try { - encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); - - return true; - } catch (error) { - return false; - } -}; - -// Query result -const isValid = isValidSubstrateAddress(); -console.log(isValid); - -``` - -If the function returns `true`, the specified address is a valid address. - -#### Other SS58 Implementations - -Support for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries. - -- **Crystal**: [`wyhaines/base58.cr`](https://github.com/wyhaines/base58.cr){target=\_blank} -- **Go**: [`itering/subscan-plugin`](https://github.com/itering/subscan-plugin){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **TypeScript**: [`subsquid/squid-sdk`](https://github.com/subsquid/squid-sdk){target=\_blank} - - ---- - -Page Title: Randomness - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/randomness/ -- Summary: Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. - -# Randomness - -## Introduction - -Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as "random" numbers on a computer are actually pseudo-random. These numbers rely on an initial "seed," which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\_blank}, [heart rates](https://mdpi.altmetric.com/details/47574324){target=\_blank}, or even [lava lamps](https://en.wikipedia.org/wiki/Lavarand){target=\_blank}. While this may seem random, given the same "seed," the same sequence of numbers will always be generated. - -In a global blockchain network, relying on real-world entropy for randomness isn’t feasible because these inputs vary by time and location. If nodes use different inputs, blockchains can fork. Hence, real-world randomness isn't suitable for use as a seed in blockchain systems. - -Currently, two primary methods for generating randomness in blockchains are used: [`RANDAO`](#randao) and [`VRF`](#vrf) (Verifiable Random Function). Polkadot adopts the `VRF` approach for its randomness. - -## VRF - -A Verifiable Random Function (VRF) is a cryptographic function that generates a random number and proof that ensures the submitter produced the number. This proof allows anyone to verify the validity of the random number. - -Polkadot's VRF is similar to the one used in [**Ouroboros Praos**](https://eprint.iacr.org/2017/573.pdf){target=\_blank}, which secures randomness for block production in systems like [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe){target=\_blank} (Polkadot’s block production mechanism). - -The key difference is that Polkadot's VRF doesn’t rely on a central clock—avoiding the issue of whose clock to trust. Instead, it uses its own past results and slot numbers to simulate time and determine future outcomes. - -### How VRF Works - -Slots on Polkadot are discrete units of time, each lasting six seconds, and can potentially hold a block. Multiple slots form an epoch, with 2400 slots making up one four-hour epoch. - -In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: - -1. A "secret key," unique to each validator, is used for the die roll. -2. An epoch randomness value, derived from the hash of VRF outputs from blocks two epochs ago (N-2), so past randomness influences the current epoch (N). -3. The current slot number. - -This process helps maintain fair randomness across the network. - -Here is a graphical representation: - -![](/images/reference/parachains/randomness/randomness-01.webp) - -The VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). - -The result is checked by the validator against a protocol threshold. If it's below the threshold, the validator becomes a candidate for block production in that slot. - -The validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`. - -So, VRF can be expressed like: - -`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)` - -Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. - -After executing the VRF, the `RESULT` is compared to a protocol-defined `THRESHOLD`. If the `RESULT` is below the `THRESHOLD`, the validator becomes a valid candidate to propose a block for that slot. Otherwise, the validator skips the slot. - -As a result, there may be multiple validators eligible to propose a block for a slot. In this case, the block accepted by other nodes will prevail, provided it is on the chain with the latest finalized block as determined by the GRANDPA finality gadget. It's also possible for no block producers to be available for a slot, in which case the AURA consensus takes over. AURA is a fallback mechanism that randomly selects a validator to produce a block, running in parallel with BABE and only stepping in when no block producers exist for a slot. Otherwise, it remains inactive. - -Because validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. - -To verify resolution of this issue and that Polkadot block times remain near constant-time, see the [PoS Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} page of this documentation. - -## RANDAO - -An alternative on-chain randomness method is Ethereum's RANDAO, where validators perform thousands of hashes on a seed and publish the final hash during a round. The collective input from all validators forms the random number, and as long as one honest validator participates, the randomness is secure. - -To enhance security, RANDAO can optionally be combined with a Verifiable Delay Function (VDF), ensuring that randomness can't be predicted or manipulated during computation. - -For more information about RANDAO, see the [Randomness - RANDAO](https://eth2book.info/capella/part2/building_blocks/randomness/){target=\_blank} section of the Upgrading Ethereum documentation. - -## VDFs - -Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. - -They produce a unique result that can be quickly verified publicly. When combined with RANDAO, feeding RANDAO's output into a VDF introduces a delay that nullifies an attacker's chance to influence the randomness. - -However, VDF likely requires specialized ASIC devices to run separately from standard nodes. - -!!!warning - While only one is needed to secure the system, and they will be open-source and inexpensive, running VDF devices involves significant costs without direct incentives, adding friction for blockchain users. - -## Additional Resources - -For more information about the reasoning for choices made along with proofs, see Polkadot's research on blockchain randomness and sortition in the [Block production](https://research.web3.foundation/Polkadot/protocols/block-production){target=\_blank} entry of the Polkadot Wiki. - -For a discussion with Web3 Foundation researchers about when and under what conditions Polkadot's randomness can be utilized, see the [Discussion on Randomness used in Polkadot](https://github.com/use-ink/ink/issues/57){target=\_blank} issue on GitHub. - - ---- - -Page Title: Register a Local Asset - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md -- Canonical (HTML): https://docs.polkadot.com/chain-interactions/token-operations/register-local-asset/ -- Summary: Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. - -# Register a Local Asset on Asset Hub - -## Introduction - -As detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation. - -This guide will take you through the steps of registering a local asset on the Asset Hub parachain. - -## Prerequisites - -Before you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and a funded wallet with DOT or KSM. - -- For Polkadot Asset Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata. -- For Kusama Asset Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata. - -You need to ensure that your Asset Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees. - -## Steps to Register a Local Asset - -To register a local asset on the Asset Hub parachain, follow these steps: - -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. - - - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`. - - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider. - -2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. - - ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) - -3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column. - - ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) - -4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. - - ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) +Customizing your runtime typically follows these patterns: -5. Fill in the required fields in the **Create Asset** form: +**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. - 1. **creator account**: The account to be used for creating this asset and setting up the initial metadata. - 2. **asset name**: The descriptive name of the asset you are registering. - 3. **asset symbol**: The symbol that will be used to represent the asset. - 4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface. - 5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested. - 6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id. - 7. Click on the **Next** button. - - ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp) +**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. -6. Choose the accounts for the roles listed below: +**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. - 1. **admin account**: The account designated for continuous administration of the token. - 2. **issuer account**: The account that will be used for issuing this token. - 3. **freezer account**: The account that will be used for performing token freezing operations. - 4. Click on the **Create** button. +**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. - ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp) +The following diagram illustrates how pallets combine to form a complete runtime: -7. Click on the **Sign and Submit** button to complete the asset registration process. +![](/images/parachains/customize-runtime/index/frame-overview-02.webp) - ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) +## Starting Templates -## Verify Asset Registration +The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. -After completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets){target=\_blank} section of the Polkadot.js Apps interface. +- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. -![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp) +- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. -!!! tip - Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field. +- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. -In this way, you have successfully registered a local asset on the Asset Hub parachain. +- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. -For an in-depth explanation about Asset Hub and its features, see the [Asset Hub](/chain-interactions/token-operations/convert-assets/){target=\_blank} entry in the Polkadot Wiki. +## Key Customization Scenarios -## Test Setup Environment +This section covers the most common customization patterns you'll encounter: -You can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank} documentation. +- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. -To set up a test environment, execute the following command: +- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` +- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. -The above command will spawn a lazy fork of Polkadot Asset Hub with the latest block data from the network. If you need to test Kusama Asset Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. +- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. -An Asset Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet. +- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. --- @@ -8102,503 +5742,111 @@ This page contains a list of all relevant tutorials and guides to help you get s ## Port Ethereum DApps -| Title | Difficulty | Tools | Description | -|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| -| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | - - ---- - -Page Title: Smart Contracts Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ -- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. - -# Smart Contracts on Polkadot - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. - -Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. - -These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. - -## Native Smart Contracts - -### Introduction - -Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. - -### Smart Contract Development - -The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. - -Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. - -### Technical Architecture - -PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: - -- Enhanced performance for smart contract execution. -- Improved gas efficiency for complex operations. -- Native compatibility with Polkadot's runtime environment. -- Optimized storage and state management. - -### Development Tools and Resources - -Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: - -- Contract development in Solidity or Rust. -- Support for standard Ethereum development libraries. -- Integration with widely used development environments. -- Access to blockchain explorers and indexing solutions. -- Compatibility with contract monitoring and management tools. - -### Cross-Chain Capabilities - -Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. - -### Use Cases - -Polkadot Hub's smart contract platform is suitable for a wide range of applications: - -- DeFi protocols leveraging _cross-chain capabilities_. -- NFT platforms utilizing Polkadot's native token standards. -- Governance systems integrated with Polkadot's democracy mechanisms. -- Cross-chain bridges and asset management solutions. - -## Other Smart Contract Environments - -Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: - -- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). - -- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. - - -Each environment provides unique advantages based on developer preferences and application requirements. - -## Where to Go Next - -Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. - -Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. - -
    - -- Guide __Libraries__ - - --- - - Explore essential libraries to optimize smart contract development and interaction. - - [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) - -- Guide __Dev Environments__ - - --- - - Set up your development environment for seamless contract deployment and testing. - - [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) - -
    - - ---- - -Page Title: Technical Reference Overview - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md -- Canonical (HTML): https://docs.polkadot.com/reference/ -- Summary: Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. - -## Introduction - -The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need. - -Polkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\_blank} to the [governance](/reference/glossary#governance){target=\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants. - -This guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem. - -## Polkadot Hub - -[Polkadot Hub](/reference/polkadot-hub/){target=\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain. - -The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: - -- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications. -- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem. -- **Staking**: Participate in network security and earn rewards by staking DOT. -- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov. -- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities. -- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem. -- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations. - -## Parachains - -[Parachains](/reference/parachains/){target=\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers: - -- **Accounts**: Deep dive into account types, storage, and management on parachains. -- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms. -- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus. -- **Chain data**: Explore data structures, storage layouts, and state management. -- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains. -- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility. -- **Networks**: Learn about networking protocols and peer-to-peer communication. -- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\_blank}, the standard for cross-chain communication. -- **Randomness**: Understand how randomness is generated and used in Polkadot chains. -- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. - -## On-Chain Governance - -[On-Chain governance](/reference/governance/){target=\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details: - -- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums. -- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity. -- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance. -- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system. - -## Glossary - -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: - -- Blockchain concepts (blocks, transactions, state) -- Consensus mechanisms (validators, collators, finality) -- Polkadot-specific terms (relay chain, parachain, XCM, FRAME) -- Network components (nodes, runtimes, storage) -- Governance terminology (origins, tracks, referendums) - -## Tools - -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: - -- **Light clients**: Lightweight solutions for interacting with the network without running full nodes. -- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\_blank} and [PAPI](/reference/tools/papi/){target=\_blank} for building applications. -- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\_blank} and other Rust-based libraries for SDK development. -- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\_blank} for Python developers. -- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\_blank}, and [Omninode](/reference/tools/omninode/){target=\_blank} for smart contract and parachain testing. -- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\_blank} for substrate interaction. -- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\_blank} for XCM integration and asset transfers. - -## Where to Go Next - -For detailed exploration of specific areas, proceed to any of the main sections: - -
    - -- Learn **Polkadot Hub** - - --- - - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. - - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) - -- Learn **Parachains** - - --- - - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. - - [:octicons-arrow-right-24: Reference](/reference/parachains/) - -- Learn **On-Chain Governance** - - --- - - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. - - [:octicons-arrow-right-24: Reference](/reference/governance/) - -- Guide **Glossary** - - --- - - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. - - [:octicons-arrow-right-24: Reference](/reference/glossary/) - -- Guide **Tools** - - --- - - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. - - [:octicons-arrow-right-24: Reference](/reference/tools/) - -
    - - ---- - -Page Title: Transactions - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/ -- Summary: Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. - -# Transactions - -## Introduction - -Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions. - -This guide walks you through the different transaction types and how they're formatted, validated, and processed within the Polkadot ecosystem. You'll also learn how to customize transaction formats and construct transactions for FRAME-based runtimes, ensuring a complete understanding of how transactions are built and executed in Polkadot SDK-based chains. - -## What Is a Transaction? - -In the Polkadot SDK, transactions represent operations that modify the chain's state, bundled into blocks for execution. The term extrinsic is often used to refer to any data that originates outside the runtime and is included in the chain. While other blockchain systems typically refer to these operations as "transactions," the Polkadot SDK adopts the broader term "extrinsic" to capture the wide variety of data types that can be added to a block. - -There are three primary types of transactions (extrinsics) in the Polkadot SDK: - -- **Signed transactions**: Signed by the submitting account, often carrying transaction fees. -- **Unsigned transactions**: Submitted without a signature, often requiring custom validation logic. -- **Inherent transactions**: Typically inserted directly into blocks by block authoring nodes, without gossiping between peers. - -Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. - -### Signed Transactions - -Signed transactions require an account's signature and typically involve submitting a request to execute a runtime call. The signature serves as a form of cryptographic proof that the sender has authorized the action, using their private key. These transactions often involve a transaction fee to cover the cost of execution and incentivize block producers. - -Signed transactions are the most common type of transaction and are integral to user-driven actions, such as token transfers. For instance, when you transfer tokens from one account to another, the sending account must sign the transaction to authorize the operation. - -For example, the [`pallet_balances::Call::transfer_allow_death`](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/pallet/struct.Pallet.html#method.transfer_allow_death){target=\_blank} extrinsic in the Balances pallet allows you to transfer tokens. Since your account initiates this transaction, your account key is used to sign it. You'll also be responsible for paying the associated transaction fee, with the option to include an additional tip to incentivize faster inclusion in the block. - -### Unsigned Transactions - -Unsigned transactions do not require a signature or account-specific data from the sender. Unlike signed transactions, they do not come with any form of economic deterrent, such as fees, which makes them susceptible to spam or replay attacks. Custom validation logic must be implemented to mitigate these risks and ensure these transactions are secure. - -Unsigned transactions typically involve scenarios where including a fee or signature is unnecessary or counterproductive. However, due to the absence of fees, they require careful validation to protect the network. For example, [`pallet_im_online::Call::heartbeat`](https://paritytech.github.io/polkadot-sdk/master/pallet_im_online/pallet/struct.Pallet.html#method.heartbeat){target=\_blank} extrinsic allows validators to send a heartbeat signal, indicating they are active. Since only validators can make this call, the logic embedded in the transaction ensures that the sender is a validator, making the need for a signature or fee redundant. - -Unsigned transactions are more resource-intensive than signed ones because custom validation is required, but they play a crucial role in certain operational scenarios, especially when regular user accounts aren't involved. - -### Inherent Transactions - -Inherent transactions are a specialized type of unsigned transaction that is used primarily for block authoring. Unlike signed or other unsigned transactions, inherent transactions are added directly by block producers and are not broadcasted to the network or stored in the transaction queue. They don't require signatures or the usual validation steps and are generally used to insert system-critical data directly into blocks. - -A key example of an inherent transaction is inserting a timestamp into each block. The [`pallet_timestamp::Call::now`](https://paritytech.github.io/polkadot-sdk/master/pallet_timestamp/pallet/struct.Pallet.html#method.now-1){target=\_blank} extrinsic allows block authors to include the current time in the block they are producing. Since the block producer adds this information, there is no need for transaction validation, like signature verification. The validation in this case is done indirectly by the validators, who check whether the timestamp is within an acceptable range before finalizing the block. - -Another example is the [`paras_inherent::Call::enter`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/paras_inherent/pallet/struct.Pallet.html#method.enter){target=\_blank} extrinsic, which enables parachain collator nodes to send validation data to the relay chain. This inherent transaction ensures that the necessary parachain data is included in each block without the overhead of gossiped transactions. - -Inherent transactions serve a critical role in block authoring by allowing important operational data to be added directly to the chain without needing the validation processes required for standard transactions. - -## Transaction Formats - -Understanding the structure of signed and unsigned transactions is crucial for developers building on Polkadot SDK-based chains. Whether you're optimizing transaction processing, customizing formats, or interacting with the transaction pool, knowing the format of extrinsics, Polkadot's term for transactions, is essential. - -### Types of Transaction Formats - -In Polkadot SDK-based chains, extrinsics can fall into three main categories: - -- **Unchecked extrinsics**: Typically used for signed transactions that require validation. They contain a signature and additional data, such as a nonce and information for fee calculation. Unchecked extrinsics are named as such because they require validation checks before being accepted into the transaction pool. -- **Checked extrinsics**: Typically used for inherent extrinsics (unsigned transactions); these don't require signature verification. Instead, they carry information such as where the extrinsic originates and any additional data required for the block authoring process. -- **Opaque extrinsics**: Used when the format of an extrinsic is not yet fully committed or finalized. They are still decodable, but their structure can be flexible depending on the context. - -### Signed Transaction Data Structure - -A signed transaction typically includes the following components: - -- **Signature**: Verifies the authenticity of the transaction sender. -- **Call**: The actual function or method call the transaction is requesting (for example, transferring funds). -- **Nonce**: Tracks the number of prior transactions sent from the account, helping to prevent replay attacks. -- **Tip**: An optional incentive to prioritize the transaction in block inclusion. -- **Additional data**: Includes details such as spec version, block hash, and genesis hash to ensure the transaction is valid within the correct runtime and chain context. - -Here's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime: - -``` code - + + -``` - -Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. - -### Signed Extensions - -Polkadot SDK also provides the concept of [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}, which allow developers to extend extrinsics with additional data or validation logic before they are included in a block. The [`SignedExtension`](https://paritytech.github.io/try-runtime-cli/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} set helps enforce custom rules or protections, such as ensuring the transaction's validity or calculating priority. - -The transaction queue regularly calls signed extensions to verify a transaction's validity before placing it in the ready queue. This safeguard ensures transactions won't fail in a block. Signed extensions are commonly used to enforce validation logic and protect the transaction pool from spam and replay attacks. - -In FRAME, a signed extension can hold any of the following types by default: - -- **[`AccountId`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/types_common/type.AccountId.html){target=\_blank}**: To encode the sender's identity. -- **[`Call`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Call){target=\_blank}**: To encode the pallet call to be dispatched. This data is used to calculate transaction fees. -- **[`AdditionalSigned`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.AdditionalSigned){target=\_blank}**: To handle any additional data to go into the signed payload allowing you to attach any custom logic prior to dispatching a transaction. -- **[`Pre`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Pre){target=\_blank}**: To encode the information that can be passed from before a call is dispatched to after it gets dispatched. - -Signed extensions can enforce checks like: - -- **[`CheckSpecVersion`](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/extensions/check_spec_version.rs.html){target=\_blank}**: Ensures the transaction is compatible with the runtime's current version. -- **[`CheckWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.CheckWeight.html){target=\_blank}**: Calculates the weight (or computational cost) of the transaction, ensuring the block doesn't exceed the maximum allowed weight. - -These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. - -## Transaction Construction - -Building transactions in the Polkadot SDK involves constructing a payload that can be verified, signed, and submitted for inclusion in a block. Each runtime in the Polkadot SDK has its own rules for validating and executing transactions, but there are common patterns for constructing a signed transaction. - -### Construct a Signed Transaction - -A signed transaction in the Polkadot SDK includes various pieces of data to ensure security, prevent replay attacks, and prioritize processing. Here's an overview of how to construct one: - -1. **Construct the unsigned payload**: Gather the necessary information for the call, including: - - - **Pallet index**: Identifies the pallet where the runtime function resides. - - **Function index**: Specifies the particular function to call in the pallet. - - **Parameters**: Any additional arguments required by the function call. - -2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: - - - **Transaction nonce**: Unique identifier to prevent replay attacks. - - **Era information**: Defines how long the transaction is valid before it's dropped from the pool. - - **Block hash**: Ensures the transaction doesn't execute on the wrong chain or fork. - -3. **Sign the payload**: Using the sender's private key, sign the payload to ensure that the transaction can only be executed by the account holder. -4. **Serialize the signed payload**: Once signed, the transaction must be serialized into a binary format, ensuring the data is compact and easy to transmit over the network. -5. **Submit the serialized transaction**: Finally, submit the serialized transaction to the network, where it will enter the transaction pool and wait for processing by an authoring node. - -The following is an example of how a signed transaction might look: - -``` rust -node_runtime::UncheckedExtrinsic::new_signed( - function.clone(), // some call - sp_runtime::AccountId32::from(sender.public()).into(), // some sending account - node_runtime::Signature::Sr25519(signature.clone()), // the account's signature - extra.clone(), // the signed extensions -) -``` - -### Transaction Encoding - -Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: - -- **`[1]`**: Compact encoded length in bytes of the entire transaction. -- **`[2]`**: A u8 containing 1 byte to indicate whether the transaction is signed or unsigned (1 bit) and the encoded transaction version ID (7 bits). -- **`[3]`**: If signed, this field contains an account ID, an SR25519 signature, and some extra data. -- **`[4]`**: Encoded call data, including pallet and function indices and any required arguments. - -This encoded format ensures consistency and efficiency in processing transactions across the network. By adhering to this format, applications can construct valid transactions and pass them to the network for execution. - -To learn more about how compact encoding works using SCALE, see the [SCALE Codec](https://github.com/paritytech/parity-scale-codec){target=\_blank} README on GitHub. - -### Customize Transaction Construction - -Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: - -- **Custom pallets**: You can define new pallets with custom function calls, each with its own parameters and validation logic. -- **Signed extensions**: Developers can implement custom extensions that modify how transactions are prioritized, validated, or included in blocks. - -By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. +| Title | Difficulty | Tools | Description | +|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| +| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | -## Lifecycle of a Transaction -In the Polkadot SDK, transactions are often referred to as extrinsics because the data in transactions originates outside of the runtime. These transactions contain data that initiates changes to the chain state. The most common type of extrinsic is a signed transaction, which is cryptographically verified and typically incurs a fee. This section focuses on how signed transactions are processed, validated, and ultimately included in a block. +--- -### Define Transaction Properties +Page Title: Smart Contracts Overview -The Polkadot SDK runtime defines key transaction properties, such as: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ +- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. -- **Transaction validity**: Ensures the transaction meets all runtime requirements. -- **Signed or unsigned**: Identifies whether a transaction needs to be signed by an account. -- **State changes**: Determines how the transaction modifies the state of the chain. +# Smart Contracts on Polkadot -Pallets, which compose the runtime's logic, define the specific transactions that your chain supports. When a user submits a transaction, such as a token transfer, it becomes a signed transaction, verified by the user's account signature. If the account has enough funds to cover fees, the transaction is executed, and the chain's state is updated accordingly. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -### Process on a Block Authoring Node +Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. -In Polkadot SDK-based networks, some nodes are authorized to author blocks. These nodes validate and process transactions. When a transaction is sent to a node that can produce blocks, it undergoes a lifecycle that involves several stages, including validation and execution. Non-authoring nodes gossip the transaction across the network until an authoring node receives it. The following diagram illustrates the lifecycle of a transaction that's submitted to a network and processed by an authoring node. +Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. -![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } +These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. -### Validate and Queue +## Native Smart Contracts -Once a transaction reaches an authoring node, it undergoes an initial validation process to ensure it meets specific conditions defined in the runtime. This validation includes checks for: +### Introduction -- **Correct nonce**: Ensures the transaction is sequentially valid for the account. -- **Sufficient funds**: Confirms the account can cover any associated transaction fees. -- **Signature validity**: Verifies that the sender's signature matches the transaction data. +Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. -After these checks, valid transactions are placed in the transaction pool, where they are queued for inclusion in a block. The transaction pool regularly re-validates queued transactions to ensure they remain valid before being processed. To reach consensus, two-thirds of the nodes must agree on the order of the transactions executed and the resulting state change. Transactions are validated and queued on the local node in a transaction pool to prepare for consensus. +### Smart Contract Development -#### Transaction Pool +The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. -The transaction pool is responsible for managing valid transactions. It ensures that only transactions that pass initial validity checks are queued. Transactions that fail validation, expire, or become invalid for other reasons are removed from the pool. +Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. -The transaction pool organizes transactions into two queues: +### Technical Architecture -- **Ready queue**: Transactions that are valid and ready to be included in a block. -- **Future queue**: Transactions that are not yet valid but could be in the future, such as transactions with a nonce too high for the current state. +PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: -Details on how the transaction pool validates transactions, including fee and signature handling, can be found in the [`validate_transaction`](https://paritytech.github.io/polkadot-sdk/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction){target=\_blank} method. +- Enhanced performance for smart contract execution. +- Improved gas efficiency for complex operations. +- Native compatibility with Polkadot's runtime environment. +- Optimized storage and state management. -#### Invalid Transactions +### Development Tools and Resources -If a transaction is invalid, for example, due to an invalid signature or insufficient funds, it is rejected and won't be added to the block. Invalid transactions might be rejected for reasons such as: +Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: -- The transaction has already been included in a block. -- The transaction's signature does not match the sender. -- The transaction is too large to fit in the current block. +- Contract development in Solidity or Rust. +- Support for standard Ethereum development libraries. +- Integration with widely used development environments. +- Access to blockchain explorers and indexing solutions. +- Compatibility with contract monitoring and management tools. -### Transaction Ordering and Priority +### Cross-Chain Capabilities -When a node is selected as the next block author, it prioritizes transactions based on weight, length, and tip amount. The goal is to fill the block with high-priority transactions without exceeding its maximum size or computational limits. Transactions are ordered as follows: +Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. -- **Inherents first**: Inherent transactions, such as block timestamp updates, are always placed first. -- **Nonce-based ordering**: Transactions from the same account are ordered by their nonce. -- **Fee-based ordering**: Among transactions with the same nonce or priority level, those with higher fees are prioritized. +### Use Cases -### Transaction Execution +Polkadot Hub's smart contract platform is suitable for a wide range of applications: -Once a block author selects transactions from the pool, the transactions are executed in priority order. As each transaction is processed, the state changes are written directly to the chain's storage. It's important to note that these changes are not cached, meaning a failed transaction won't revert earlier state changes, which could leave the block in an inconsistent state. +- DeFi protocols leveraging _cross-chain capabilities_. +- NFT platforms utilizing Polkadot's native token standards. +- Governance systems integrated with Polkadot's democracy mechanisms. +- Cross-chain bridges and asset management solutions. -Events are also written to storage. Runtime logic should not emit an event before performing the associated actions. If the associated transaction fails after the event was emitted, the event will not revert. +## Other Smart Contract Environments -## Transaction Mortality +Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: -Transactions in the network can be configured as either mortal (with expiration) or immortal (without expiration). Every transaction payload contains a block checkpoint (reference block number and hash) and an era/validity period that determines how many blocks after the checkpoint the transaction remains valid. +- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). -When a transaction is submitted, the network validates it against these parameters. If the transaction is not included in a block within the specified validity window, it is automatically removed from the transaction queue. +- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. -- **Mortal transactions**: Have a finite lifespan and will expire after a specified number of blocks. For example, a transaction with a block checkpoint of 1000 and a validity period of 64 blocks will be valid from blocks 1000 to 1064. -- **Immortal transactions**: Never expire and remain valid indefinitely. To create an immortal transaction, set the block checkpoint to 0 (genesis block), use the genesis hash as a reference, and set the validity period to 0. +Each environment provides unique advantages based on developer preferences and application requirements. -However, immortal transactions pose significant security risks through replay attacks. If an account is reaped (balance drops to zero, account removed) and later re-funded, malicious actors can replay old immortal transactions. +## Where to Go Next -The blockchain maintains only a limited number of prior block hashes for reference validation, called `BlockHashCount`. If your validity period exceeds `BlockHashCount`, the effective validity period becomes the minimum of your specified period and the block hash count. +Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. -## Unique Identifiers for Extrinsics +Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. -Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. +
    -Key differences from traditional blockchains: +- Guide __Libraries__ -- Transaction hashes serve only as fingerprints of transaction information. -- Multiple valid transactions can share the same hash. -- Hash uniqueness assumptions lead to serious issues. + --- -For example, when an account is reaped (removed due to insufficient balance) and later recreated, it resets to nonce 0, allowing identical transactions to be valid at different points: + Explore essential libraries to optimize smart contract development and interaction. -| Block | Extrinsic Index | Hash | Origin | Nonce | Call | Result | -|-------|----------------|------|-----------|-------|---------------------|-------------------------------| -| 100 | 0 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Account A reaped | -| 150 | 5 | 0x02 | Account B | 4 | Transfer 7 DOT to A | Account A created (nonce = 0) | -| 200 | 2 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Successful transaction | + [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) -Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. +- Guide __Dev Environments__ -Additional complexity comes from Polkadot SDK's origin abstraction. Origins can represent collectives, governance bodies, or other non-account entities that don't maintain nonces like regular accounts and might dispatch identical calls multiple times with the same hash values. Each execution occurs in different chain states with different results. + --- -The correct way to uniquely identify an extrinsic on a Polkadot SDK-based chain is to use the block ID (height or hash) and the extrinsic index. Since the Polkadot SDK defines blocks as headers plus ordered arrays of extrinsics, the index position within a canonical block provides guaranteed uniqueness. + Set up your development environment for seamless contract deployment and testing. -## Additional Resources + [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) -For a video overview of the lifecycle of transactions and the types of transactions that exist, see the [Transaction lifecycle](https://www.youtube.com/watch?v=3pfM0GOp02c){target=\_blank} seminar from Parity Tech. +
    --- @@ -8708,351 +5956,6 @@ The system maintains precise conversion mechanisms between: This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. ---- - -Page Title: Transactions Weights and Fees - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/ -- Summary: Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. - -# Transactions Weights and Fees - -## Introductions - -When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop the network from producing new blocks. To protect blockchain resources from being drained or overloaded, you need to manage how they are made available and how they are consumed. The resources to be aware of include: - -- Memory usage -- Storage input and output -- Computation -- Transaction and block size -- State database size - -The Polkadot SDK provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource. Two of the most important mechanisms available to block authors are weights and transaction fees. - -[Weights](/reference/glossary/#weight){target=\_blank} manage the time it takes to validate a block and characterize the time it takes to execute the calls in the block's body. By controlling the execution time a block can consume, weights set limits on storage input, output, and computation. - -Some of the weight allowed for a block is consumed as part of the block's initialization and finalization. The weight might also be used to execute mandatory inherent extrinsic calls. To help ensure blocks don’t consume too much execution time and prevent malicious users from overloading the system with unnecessary calls, weights are combined with transaction fees. - -[Transaction fees](/reference/parachains/blocks-transactions-fees/transactions/#transaction-fees){target=\_blank} provide an economic incentive to limit execution time, computation, and the number of calls required to perform operations. Transaction fees are also used to make the blockchain economically sustainable because they are typically applied to transactions initiated by users and deducted before a transaction request is executed. - -## How Fees are Calculated - -The final fee for a transaction is calculated using the following parameters: - -- **`base fee`**: This is the minimum amount a user pays for a transaction. It is declared a base weight in the runtime and converted to a fee using the [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} conversion. -- **`weight fee`**: A fee proportional to the execution time (input and output and computation) that a transaction consumes. -- **`length fee`**: A fee proportional to the encoded length of the transaction. -- **`tip`**: An optional tip to increase the transaction’s priority, giving it a higher chance to be included in the transaction queue. - -The base fee and proportional weight and length fees constitute the inclusion fee. The inclusion fee is the minimum fee that must be available for a transaction to be included in a block. - -```text -inclusion fee = base fee + weight fee + length fee -``` - -Transaction fees are withdrawn before the transaction is executed. After the transaction is executed, the weight can be adjusted to reflect the resources used. If a transaction uses fewer resources than expected, the transaction fee is corrected, and the adjusted transaction fee is deposited. - -## Using the Transaction Payment Pallet - -The [Transaction Payment pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/transaction-payment){target=\_blank} provides the basic logic for calculating the inclusion fee. You can also use the Transaction Payment pallet to: - -- Convert a weight value into a deductible fee based on a currency type using [`Config::WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank}. -- Update the fee for the next block by defining a multiplier based on the chain’s final state at the end of the previous block using [`Config::FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank}. -- Manage the withdrawal, refund, and deposit of transaction fees using [`Config::OnChargeTransaction`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.OnChargeTransaction){target=\_blank}. - -You can learn more about these configuration traits in the [Transaction Payment documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_payment/index.html){target=\_blank}. - -### Understanding the Inclusion Fee - -The formula for calculating the inclusion fee is as follows: - -```text -inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] -``` - -And then, for calculating the final fee: - -```text -final_fee = inclusion_fee + tip -``` - -In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. - -- The `base_fee` derived from the base weight covers inclusion overhead like signature verification. -- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic. -- The `weight_fee` fee is calculated using two parameters: - - The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics. - - The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity. - -To convert the weight to `Currency`, the runtime must define a `WeightToFee` struct that implements a conversion function, [`Convert`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/struct.Pallet.html#method.weight_to_fee){target=\_blank}. - -Note that the extrinsic sender is charged the inclusion fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution. - -### Accounts with an Insufficient Balance - -If an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum existential deposit—then you should ensure the transaction is canceled so that no fee is deducted and the transaction does not begin execution. - -The Polkadot SDK doesn't enforce this rollback behavior. However, this scenario would be rare because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block. - -### Fee Multipliers - -The inclusion fee formula always results in the same fee for the same input. However, weight can be dynamic and—based on how [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} is defined—the final fee can include some degree of variability. -The Transaction Payment pallet provides the [`FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank} configurable parameter to account for this variability. - -The Polkadot network inspires the default update function and implements a targeted adjustment in which a target saturation level of block weight is defined. If the previous block is more saturated, the fees increase slightly. Similarly, if the last block has fewer transactions than the target, fees are decreased by a small amount. For more information about fee multiplier adjustments, see the [Web3 Research Page](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank}. - -## Transactions with Special Requirements - -Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: - -- Bonds are a type of fee that might be returned or slashed after some on-chain event. For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior. -- Deposits are fees that might be returned later. For example, you might require users to pay a deposit to execute an operation that uses storage. The user’s deposit could be returned if a subsequent operation frees up storage. -- Burn operations are used to pay for a transaction based on its internal logic. For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased state size. -- Limits enable you to enforce constant or configurable limits on specific operations. For example, the default [Staking pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/staking){target=\_blank} only allows nominators to nominate 16 validators to limit the complexity of the validator election process. - -It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. - -## Default Weight Annotations - -All dispatchable functions in the Polkadot SDK must specify a weight. The way of doing that is using the annotation-based system that lets you combine fixed values for database read/write weight and/or fixed values based on benchmarks. The most basic example would look like this: - -```rust -#[pallet::weight(100_000)] -fn my_dispatchable() { - // ... -} -``` - -Note that the [`ExtrinsicBaseWeight`](https://crates.parity.io/frame_support/weights/constants/struct.ExtrinsicBaseWeight.html){target=\_blank} is automatically added to the declared weight to account for the costs of simply including an empty extrinsic into a block. - -### Weights and Database Read/Write Operations - -To make weight annotations independent of the deployed database backend, they are defined as a constant and then used in the annotations when expressing database accesses performed by the dispatchable: - -```rust -#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] -fn my_dispatchable() { - // ... -} -``` - -This dispatchable allows one database to read and two to write, in addition to other things that add the additional 20,000. Database access is generally every time a value declared inside the [`#[pallet::storage]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} block is accessed. However, unique accesses are counted because after a value is accessed, it is cached, and reaccessing it does not result in a database operation. That is: - -- Multiple reads of the exact value count as one read. -- Multiple writes of the exact value count as one write. -- Multiple reads of the same value, followed by a write to that value, count as one read and one write. -- A write followed by a read-only counts as one write. - -### Dispatch Classes - -Dispatches are broken into three classes: - -- Normal -- Operational -- Mandatory - -If a dispatch is not defined as `Operational` or `Mandatory` in the weight annotation, the dispatch is identified as `Normal` by default. You can specify that the dispatchable uses another class like this: - -```rust -#[pallet::dispatch((DispatchClass::Operational))] -fn my_dispatchable() { - // ... -} -``` - -This tuple notation also allows you to specify a final argument determining whether the user is charged based on the annotated weight. If you don't specify otherwise, `Pays::Yes` is assumed: - -```rust -#[pallet::dispatch(DispatchClass::Normal, Pays::No)] -fn my_dispatchable() { - // ... -} -``` - -#### Normal Dispatches - -Dispatches in this class represent normal user-triggered transactions. These types of dispatches only consume a portion of a block's total weight limit. For information about the maximum portion of a block that can be consumed for normal dispatches, see [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Normal dispatches are sent to the transaction pool. - -#### Operational Dispatches - -Unlike normal dispatches, which represent the usage of network capabilities, operational dispatches are those that provide network capabilities. Operational dispatches can consume the entire weight limit of a block. They are not bound by the [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Dispatches in this class are given maximum priority and are exempt from paying the [`length_fee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/){target=\_blank}. - -#### Mandatory Dispatches - -Mandatory dispatches are included in a block even if they cause the block to surpass its weight limit. You can only use the mandatory dispatch class for inherent transactions that the block author submits. This dispatch class is intended to represent functions in the block validation process. Because these dispatches are always included in a block regardless of the function weight, the validation process must prevent malicious nodes from abusing the function to craft valid but impossibly heavy blocks. You can typically accomplish this by ensuring that: - -- The operation performed is always light. -- The operation can only be included in a block once. - -To make it more difficult for malicious nodes to abuse mandatory dispatches, they cannot be included in blocks that return errors. This dispatch class serves the assumption that it is better to allow an overweight block to be created than not to allow any block to be created at all. - -### Dynamic Weights - -In addition to purely fixed weights and constants, the weight calculation can consider the input arguments of a dispatchable. The weight should be trivially computable from the input arguments with some basic arithmetic: - -```rust -use frame_support:: { - dispatch:: { - DispatchClass::Normal, - Pays::Yes, - }, - weights::Weight, -}; - -#[pallet::weight(FunctionOf( - |args: (&Vec,)| args.0.len().saturating_mul(10_000), - ) -] -fn handle_users(origin, calls: Vec) { - // Do something per user -} -``` - -## Post Dispatch Weight Correction - -Depending on the execution logic, a dispatchable function might consume less weight than was prescribed pre-dispatch. To correct weight, the function declares a different return type and returns its actual weight: - -```rust -#[pallet::weight(10_000 + 500_000_000)] -fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo { - let was_heavy = do_calculation(input); - - if (was_heavy) { - // None means "no correction" from the weight annotation. - Ok(None.into()) - } else { - // Return the actual weight consumed. - Ok(Some(10_000).into()) - } -} -``` - -## Custom Fees - -You can also define custom fee systems through custom weight functions or inclusion fee functions. - -### Custom Weights - -Instead of using the default weight annotations, you can create a custom weight calculation type using the weights module. The custom weight calculation type must implement the following traits: - -- [`WeighData`](https://crates.parity.io/frame_support/weights/trait.WeighData.html){target=\_blank} to determine the weight of the dispatch. -- [`ClassifyDispatch`](https://crates.parity.io/frame_support/weights/trait.ClassifyDispatch.html){target=\_blank} to determine the class of the dispatch. -- [`PaysFee`](https://crates.parity.io/frame_support/weights/trait.PaysFee.html){target=\_blank} to determine whether the sender of the dispatch pays fees. - -The Polkadot SDK then bundles the output information of the three traits into the [`DispatchInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.DispatchInfo.html){target=\_blank} struct and provides it by implementing the [`GetDispatchInfo`](https://docs.rs/frame-support/latest/frame_support/dispatch/trait.GetDispatchInfo.html){target=\_blank} for all `Call` variants and opaque extrinsic types. This is used internally by the System and Executive modules. - -`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over T, which gets resolved into the tuple of all dispatch arguments except for the origin. The following example illustrates a struct that calculates the weight as `m * len(args)`, where `m` is a given multiplier and args is the concatenated tuple of all dispatch arguments. In this example, the dispatch class is `Operational` if the transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length exceeds 10 bytes. - -```rust -struct LenWeight(u32); -impl WeighData for LenWeight { - fn weigh_data(&self, target: T) -> Weight { - let multiplier = self.0; - let encoded_len = target.encode().len() as u32; - multiplier * encoded_len - } -} - -impl ClassifyDispatch for LenWeight { - fn classify_dispatch(&self, target: T) -> DispatchClass { - let encoded_len = target.encode().len() as u32; - if encoded_len > 100 { - DispatchClass::Operational - } else { - DispatchClass::Normal - } - } -} - -impl PaysFee { - fn pays_fee(&self, target: T) -> Pays { - let encoded_len = target.encode().len() as u32; - if encoded_len > 10 { - Pays::Yes - } else { - Pays::No - } - } -} -``` - -A weight calculator function can also be coerced to the final type of the argument instead of defining it as a vague type that can be encoded. The code would roughly look like this: - -```rust -struct CustomWeight; -impl WeighData<(&u32, &u64)> for CustomWeight { - fn weigh_data(&self, target: (&u32, &u64)) -> Weight { - ... - } -} - -// given a dispatch: -#[pallet::call] -impl, I: 'static> Pallet { - #[pallet::weight(CustomWeight)] - fn foo(a: u32, b: u64) { ... } -} -``` - -In this example, the `CustomWeight` can only be used in conjunction with a dispatch with a particular signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because there aren't any assumptions about ``. - -#### Custom Inclusion Fee - -The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. - -```rust -// Assume this is the balance type -type Balance = u64; - -// Assume we want all the weights to have a `100 + 2 * w` conversion to fees -struct CustomWeightToFee; -impl WeightToFee for CustomWeightToFee { - fn convert(w: Weight) -> Balance { - let a = Balance::from(100); - let b = Balance::from(2); - let w = Balance::from(w); - a + b * w - } -} - -parameter_types! { - pub const ExtrinsicBaseWeight: Weight = 10_000_000; -} - -impl frame_system::Config for Runtime { - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; -} - -parameter_types! { - pub const TransactionByteFee: Balance = 10; -} - -impl transaction_payment::Config { - type TransactionByteFee = TransactionByteFee; - type WeightToFee = CustomWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} - -struct TargetedFeeAdjustment(sp_std::marker::PhantomData); -impl> WeightToFee for TargetedFeeAdjustment { - fn convert(multiplier: Fixed128) -> Fixed128 { - // Don't change anything. Put any fee update info here. - multiplier - } -} -``` - -## Additional Resources - -You now know the weight system, how it affects transaction fee computation, and how to specify weights for your dispatchable calls. The next step is determining the correct weight for your dispatchable operations. You can use Substrate benchmarking functions and frame-benchmarking calls to test your functions with different parameters and empirically determine the proper weight in their worst-case scenarios. - -- [Benchmark](/parachains/customize-runtime/pallet-development/benchmark-pallet/) -- [`SignedExtension`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} -- [Custom weights for the Example pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/examples/basic/src/weights.rs){target=\_blank} -- [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} - - --- Page Title: Troubleshooting Remix IDE @@ -11332,91 +8235,3 @@ Now that you have the foundation for using Web3.py with Polkadot Hub, consider e
    - - ---- - -Page Title: XCM Tools - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/xcm-tools/ -- Summary: Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. - -# XCM Tools - -## Introduction - -As described in the [Interoperability](/develop/interoperability){target=\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem. - -As XCM is central to enabling communication between blockchains, developers need robust tools to help interact with, build, and test XCM messages. Several XCM tools simplify working with the protocol by providing libraries, frameworks, and utilities that enhance the development process, ensuring that applications built within the Polkadot ecosystem can efficiently use cross-chain functionalities. - -## Popular XCM Tools - -### Moonsong Labs XCM Tools - -[Moonsong Labs XCM Tools](https://github.com/Moonsong-Labs/xcm-tools){target=\_blank} provides a collection of scripts for managing and testing XCM operations between Polkadot SDK-based runtimes. These tools allow performing tasks like asset registration, channel setup, and XCM initialization. Key features include: - -- **Asset registration**: Registers assets, setting units per second (up-front fees), and configuring error (revert) codes. -- **XCM initializer**: Initializes XCM, sets default XCM versions, and configures revert codes for XCM-related precompiles. -- **HRMP manipulator**: Manages HRMP channel actions, including opening, accepting, or closing channels. -- **XCM-Transactor-Info-Setter**: Configures transactor information, including extra weight and fee settings. -- **Decode XCM**: Decodes XCM messages on the relay chain or parachains to help interpret cross-chain communication. - -To get started, clone the repository and install the required dependencies: - -```bash -git clone https://github.com/Moonsong-Labs/xcm-tools && -cd xcm-tools && -yarn install -``` - -For a full overview of each script, visit the [scripts](https://github.com/Moonsong-Labs/xcm-tools/tree/main/scripts){target=\_blank} directory or refer to the [official documentation](https://github.com/Moonsong-Labs/xcm-tools/blob/main/README.md){target=\_blank} on GitHub. - -### ParaSpell - -[ParaSpell](/reference/tools/paraspell/){target=\_blank} is a collection of open-source XCM tools that streamline cross-chain asset transfers and interactions across the Polkadot and Kusama ecosystems. It provides developers with an intuitive interface to build, test, and deploy interoperable dApps, featuring message composition, decoding, and practical utilities for parachain interactions that simplify debugging and cross-chain communication optimization. - -### Astar XCM Tools - -The [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks: - -- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command. -- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments. -- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs. - -To start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\_blank} and compile the xcm-tools package: - -```bash -git clone https://github.com/AstarNetwork/Astar && -cd Astar && -cargo build --release -p xcm-tools -``` - -After compiling, verify the setup with the following command: - -```bash -./target/release/xcm-tools --help -``` -For more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\_blank}. - -### Chopsticks - -The Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\_blank} about XCM. - -### Moonbeam XCM SDK - -The [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank} of the origin or destination assets or which extrinsics are used on which networks. - -The SDK consists of two main packages: - -- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem. -- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum. - -Key features include: - -- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection. -- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems. -- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality. -- **Comprehensive documentation**: Includes usage guides and API references for both packages. - -For detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\_blank}. diff --git a/.ai/categories/tooling.md b/.ai/categories/tooling.md index f4dd788b0..f9c835d10 100644 --- a/.ai/categories/tooling.md +++ b/.ai/categories/tooling.md @@ -516,440 +516,6 @@ BlockScout is an open-source explorer platform with a user-friendly interface ad ![](/images/smart-contracts/explorers/block-explorers-2.webp) ---- - -Page Title: Blocks - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/ -- Summary: Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. - -# Blocks - -## Introduction - -In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the network. By understanding these concepts, developers can better grasp how blockchains maintain security, consistency, and performance within the Polkadot ecosystem. - -## What is a Block? - -In the Polkadot SDK, a block is a fundamental unit that encapsulates both the header and an array of transactions. The block header includes critical metadata to ensure the integrity and sequence of the blockchain. Here's a breakdown of its components: - -- **Block height**: Indicates the number of blocks created in the chain so far. -- **Parent hash**: The hash of the previous block, providing a link to maintain the blockchain's immutability. -- **Transaction root**: Cryptographic digest summarizing all transactions in the block. -- **State root**: A cryptographic digest representing the post-execution state. -- **Digest**: Additional information that can be attached to a block, such as consensus-related messages. - -Each transaction is part of a series that is executed according to the runtime's rules. The transaction root is a cryptographic digest of this series, which prevents alterations and enables succinct verification by light clients. This verification process allows light clients to confirm whether a transaction exists in a block with only the block header, avoiding downloading the entire block. - -## Block Production - -When an authoring node is authorized to create a new block, it selects transactions from the transaction queue based on priority. This step, known as block production, relies heavily on the executive module to manage the initialization and finalization of blocks. The process is summarized as follows: - -### Initialize Block - -The block initialization process begins with a series of function calls that prepare the block for transaction execution: - -1. **Call `on_initialize`**: The executive module calls the [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hook from the system pallet and other runtime pallets to prepare for the block's transactions. -2. **Coordinate runtime calls**: Coordinates function calls in the order defined by the transaction queue. -3. **Verify information**: Once [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} functions are executed, the executive module checks the parent hash in the block header and the trie root to verify information is consistent. - -### Finalize Block - -Once transactions are processed, the block must be finalized before being broadcast to the network. The finalization steps are as follows: - -1. **Call `on_finalize`**: The executive module calls the [`on_finalize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_finalize){target=\_blank} hooks in each pallet to ensure any remaining state updates or checks are completed before the block is sealed and published. -2. **Verify information**: The block's digest and storage root in the header are checked against the initialized block to ensure consistency. -3. **Call `on_idle`**: The [`on_idle`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_idle){target=\_blank} hook is triggered to process any remaining tasks using the leftover weight from the block. - -## Block Authoring and Import - -Once the block is finalized, it is gossiped to other nodes in the network. Nodes follow this procedure: - -1. **Receive transactions**: The authoring node collects transactions from the network. -2. **Validate**: Transactions are checked for validity. -3. **Queue**: Valid transactions are placed in the transaction pool for execution. -4. **Execute**: State changes are made as the transactions are executed. -5. **Publish**: The finalized block is broadcast to the network. - -### Block Import Queue - -After a block is published, other nodes on the network can import it into their chain state. The block import queue is part of the outer node in every Polkadot SDK-based node and ensures incoming blocks are valid before adding them to the node's state. - -In most cases, you don't need to know details about how transactions are gossiped or how other nodes on the network import blocks. The following traits are relevant, however, if you plan to write any custom consensus logic or want a deeper dive into the block import queue: - -- **[`ImportQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.ImportQueue.html){target=\_blank}**: The trait that defines the block import queue. -- **[`Link`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Link.html){target=\_blank}**: The trait that defines the link between the block import queue and the network. -- **[`BasicQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/struct.BasicQueue.html){target=\_blank}**: A basic implementation of the block import queue. -- **[`Verifier`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Verifier.html){target=\_blank}**: The trait that defines the block verifier. -- **[`BlockImport`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/block_import/trait.BlockImport.html){target=\_blank}**: The trait that defines the block import process. - -These traits govern how blocks are validated and imported across the network, ensuring consistency and security. - -## Additional Resources - -To learn more about the block structure in the Polkadot SDK runtime, see the [`Block` reference](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.Block.html){target=\_blank} entry in the Rust Docs. - - ---- - -Page Title: Chain Data - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/chain-data/ -- Summary: Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. - -# Chain Data - -## Introduction - -Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you can ensure seamless communication between your applications and the blockchain. - -## Application Development - -You might not be directly involved in building frontend applications as a blockchain developer. However, most applications that run on a blockchain require some form of frontend or user-facing client to enable users or other programs to access and modify the data that the blockchain stores. For example, you might develop a browser-based, mobile, or desktop application that allows users to submit transactions, post articles, view their assets, or track previous activity. The backend for that application is configured in the runtime logic for your blockchain, but the frontend client makes the runtime features accessible to your users. - -For your custom chain to be useful to others, you'll need to provide a client application that allows users to view, interact with, or update information that the blockchain keeps track of. In this article, you'll learn how to expose information about your runtime so that client applications can use it, see examples of the information exposed, and explore tools and libraries that use it. - -## Understand Metadata - -Polkadot SDK-based blockchain networks are designed to expose their runtime information, allowing developers to learn granular details regarding pallets, RPC calls, and runtime APIs. The metadata also exposes their related documentation. The chain's metadata is [SCALE-encoded](/reference/parachains/data-encoding/){target=\_blank}, allowing for the development of browser-based, mobile, or desktop applications to support the chain's runtime upgrades seamlessly. It is also possible to develop applications compatible with multiple Polkadot SDK-based chains simultaneously. - -## Expose Runtime Information as Metadata - -To interact with a node or the state of the blockchain, you need to know how to connect to the chain and access the exposed runtime features. This interaction involves a Remote Procedure Call (RPC) through a node endpoint address, commonly through a secure web socket connection. - -An application developer typically needs to know the contents of the runtime logic, including the following details: - -- Version of the runtime the application is connecting to. -- Supported APIs. -- Implemented pallets. -- Defined functions and corresponding type signatures. -- Defined custom types. -- Exposed parameters users can set. - -As the Polkadot SDK is modular and provides a composable framework for building blockchains, there are limitless opportunities to customize the schema of properties. Each runtime can be configured with its properties, including function calls and types, which can be changed over time with runtime upgrades. - -The Polkadot SDK enables you to generate the runtime metadata schema to capture information unique to a runtime. The metadata for a runtime describes the pallets in use and types defined for a specific runtime version. The metadata includes information about each pallet's storage items, functions, events, errors, and constants. The metadata also provides type definitions for any custom types included in the runtime. - -Metadata provides a complete inventory of a chain's runtime. It is key to enabling client applications to interact with the node, parse responses, and correctly format message payloads sent back to that chain. - -## Generate Metadata - -To efficiently use the blockchain's networking resources and minimize the data transmitted over the network, the metadata schema is encoded using the [Parity SCALE Codec](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank}. This encoding is done automatically through the [`scale-info`](https://docs.rs/scale-info/latest/scale_info/){target=\_blank}crate. - -At a high level, generating the metadata involves the following steps: - -1. The pallets in the runtime logic expose callable functions, types, parameters, and documentation that need to be encoded in the metadata. -2. The `scale-info` crate collects type information for the pallets in the runtime, builds a registry of the pallets that exist in a particular runtime, and the relevant types for each pallet in the registry. The type information is detailed enough to enable encoding and decoding for every type. -3. The [`frame-metadata`](https://github.com/paritytech/frame-metadata){target=\_blank} crate describes the structure of the runtime based on the registry provided by the `scale-info` crate. -4. Nodes provide the RPC method `state_getMetadata` to return a complete description of all the types in the current runtime as a hex-encoded vector of SCALE-encoded bytes. - -## Retrieve Runtime Metadata - -The type information provided by the metadata enables applications to communicate with nodes using different runtime versions and across chains that expose different calls, events, types, and storage items. The metadata also allows libraries to generate a substantial portion of the code needed to communicate with a given node, enabling libraries like [`subxt`](https://github.com/paritytech/subxt){target=\_blank} to generate frontend interfaces that are specific to a target chain. - -### Use Polkadot.js - -Visit the [Polkadot.js Portal](https://polkadot.js.org/apps/#/rpc){target=\_blank} and select the **Developer** dropdown in the top banner. Select **RPC Calls** to make the call to request metadata. Follow these steps to make the RPC call: - -1. Select **state** as the endpoint to call. -2. Select **`getMetadata(at)`** as the method to call. -3. Click **Submit RPC call** to submit the call and return the metadata in JSON format. - -### Use Curl - -You can fetch the metadata for the network by calling the node's RPC endpoint. This request returns the metadata in bytes rather than human-readable JSON: - -```sh -curl -H "Content-Type: application/json" \ --d '{"id":1, "jsonrpc":"2.0", "method": "state_getMetadata"}' \ -https://rpc.polkadot.io - -``` - -### Use Subxt - -[`subxt`](https://github.com/paritytech/subxt){target=\_blank} may also be used to fetch the metadata of any data in a human-readable JSON format: - -```sh -subxt metadata --url wss://rpc.polkadot.io --format json > spec.json -``` - -Another option is to use the [`subxt` explorer web UI](https://paritytech.github.io/subxt-explorer/#/){target=\_blank}. - -## Client Applications and Metadata - -The metadata exposes the expected way to decode each type, meaning applications can send, retrieve, and process application information without manual encoding and decoding. Client applications must use the [SCALE codec library](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank} to encode and decode RPC payloads to use the metadata. Client applications use the metadata to interact with the node, parse responses, and format message payloads sent to the node. - -## Metadata Format - -Although the SCALE-encoded bytes can be decoded using the `frame-metadata` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} libraries, there are other tools, such as `subxt` and the Polkadot-JS API, that can convert the raw data to human-readable JSON format. - -The types and type definitions included in the metadata returned by the `state_getMetadata` RPC call depend on the runtime's metadata version. - -In general, the metadata includes the following information: - -- A constant identifying the file as containing metadata. -- The version of the metadata format used in the runtime. -- Type definitions for all types used in the runtime and generated by the `scale-info` crate. -- Pallet information for the pallets included in the runtime in the order that they are defined in the `construct_runtime` macro. - -!!!tip - Depending on the frontend library used (such as the [Polkadot API](https://papi.how/){target=\_blank}), they may format the metadata differently than the raw format shown. - -The following example illustrates a condensed and annotated section of metadata decoded and converted to JSON: - -```json -[ - 1635018093, - { - "V14": { - "types": { - "types": [{}] - }, - "pallets": [{}], - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [{}] - }, - "ty": 141 - } - } -] - -``` - -The constant `1635018093` is a magic number that identifies the file as a metadata file. The rest of the metadata is divided into the `types`, `pallets`, and `extrinsic` sections: - -- The `types` section contains an index of the types and information about each type's type signature. -- The `pallets` section contains information about each pallet in the runtime. -- The `extrinsic` section describes the type identifier and transaction format version that the runtime uses. - -Different extrinsic versions can have varying formats, especially when considering [signed transactions](/reference/parachains/blocks-transactions-fees/transactions/#signed-transactions){target=\_blank}. - -### Pallets - -The following is a condensed and annotated example of metadata for a single element in the `pallets` array (the [`sudo`](https://paritytech.github.io/polkadot-sdk/master/pallet_sudo/index.html){target=\_blank} pallet): - -```json -{ - "name": "Sudo", - "storage": { - "prefix": "Sudo", - "entries": [ - { - "name": "Key", - "modifier": "Optional", - "ty": { - "Plain": 0 - }, - "default": [0], - "docs": ["The `AccountId` of the sudo key."] - } - ] - }, - "calls": { - "ty": 117 - }, - "event": { - "ty": 42 - }, - "constants": [], - "error": { - "ty": 124 - }, - "index": 8 -} - -``` - -Every element metadata contains the name of the pallet it represents and information about its storage, calls, events, and errors. You can look up details about the definition of the calls, events, and errors by viewing the type index identifier. The type index identifier is the `u32` integer used to access the type information for that item. For example, the type index identifier for calls in the Sudo pallet is 117. If you view information for that type identifier in the `types` section of the metadata, it provides information about the available calls, including the documentation for each call. - -For example, the following is a condensed excerpt of the calls for the Sudo pallet: - -```json -{ - "id": 117, - "type": { - "path": ["pallet_sudo", "pallet", "Call"], - "params": [ - { - "name": "T", - "type": null - } - ], - "def": { - "variant": { - "variants": [ - { - "name": "sudo", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 0, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "sudo_unchecked_weight", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - }, - { - "name": "weight", - "type": 8, - "typeName": "Weight" - } - ], - "index": 1, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "set_key", - "fields": [ - { - "name": "new", - "type": 103, - "typeName": "AccountIdLookupOf" - } - ], - "index": 2, - "docs": [ - "Authenticates current sudo key, sets the given AccountId (`new`) as the new sudo" - ] - }, - { - "name": "sudo_as", - "fields": [ - { - "name": "who", - "type": 103, - "typeName": "AccountIdLookupOf" - }, - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 3, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Signed` origin from a given account" - ] - } - ] - } - } - } -} - -``` - -For each field, you can access type information and metadata for the following: - -- **Storage metadata**: Provides the information required to enable applications to get information for specific storage items. -- **Call metadata**: Includes information about the runtime calls defined by the `#[pallet]` macro including call names, arguments and documentation. -- **Event metadata**: Provides the metadata generated by the `#[pallet::event]` macro, including the name, arguments, and documentation for each pallet event. -- **Constants metadata**: Provides metadata generated by the `#[pallet::constant]` macro, including the name, type, and hex-encoded value of the constant. -- **Error metadata**: Provides metadata generated by the `#[pallet::error]` macro, including the name and documentation for each pallet error. - -!!!tip - Type identifiers change from time to time, so you should avoid relying on specific type identifiers in your applications. - -### Extrinsic - -The runtime generates extrinsic metadata and provides useful information about transaction format. When decoded, the metadata contains the transaction version and the list of signed extensions. - -For example: - -```json -{ - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [ - { - "identifier": "CheckNonZeroSender", - "ty": 132, - "additional_signed": 41 - }, - { - "identifier": "CheckSpecVersion", - "ty": 133, - "additional_signed": 4 - }, - { - "identifier": "CheckTxVersion", - "ty": 134, - "additional_signed": 4 - }, - { - "identifier": "CheckGenesis", - "ty": 135, - "additional_signed": 11 - }, - { - "identifier": "CheckMortality", - "ty": 136, - "additional_signed": 11 - }, - { - "identifier": "CheckNonce", - "ty": 138, - "additional_signed": 41 - }, - { - "identifier": "CheckWeight", - "ty": 139, - "additional_signed": 41 - }, - { - "identifier": "ChargeTransactionPayment", - "ty": 140, - "additional_signed": 41 - } - ] - }, - "ty": 141 -} - -``` - -The type system is [composite](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank}, meaning each type identifier contains a reference to a specific type or to another type identifier that provides information about the associated primitive types. - -For example, you can encode the `BitVec` type, but to decode it properly, you must know the types used for the `Order` and `Store` types. To find type information for `Order` and `Store`, you can use the path in the decoded JSON to locate their type identifiers. - -## Included RPC APIs - -A standard node comes with the following APIs to interact with a node: - -- **[`AuthorApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/author/trait.AuthorApiServer.html){target=\_blank}**: Make calls into a full node, including authoring extrinsics and verifying session keys. -- **[`ChainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/chain/trait.ChainApiServer.html){target=\_blank}**: Retrieve block header and finality information. -- **[`OffchainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/offchain/trait.OffchainApiServer.html){target=\_blank}**: Make RPC calls for off-chain workers. -- **[`StateApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/state/trait.StateApiServer.html){target=\_blank}**: Query information about on-chain state such as runtime version, storage items, and proofs. -- **[`SystemApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/system/trait.SystemApiServer.html){target=\_blank}**: Retrieve information about network state, such as connected peers and node roles. - -## Additional Resources - -The following tools can help you locate and decode metadata: - -- [Subxt Explorer](https://paritytech.github.io/subxt-explorer/#/){target=\_blank} -- [Metadata Portal 🌗](https://github.com/paritytech/metadata-portal){target=\_blank} -- [De[code] Sub[strate]](https://github.com/paritytech/desub){target=\_blank} - - --- Page Title: Contract Deployment @@ -1063,9552 +629,5345 @@ Both backends support contract deployment effectively, with REVM offering drop-i --- -Page Title: Cryptography +Page Title: Deploy an ERC-20 to Polkadot Hub -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/cryptography/ -- Summary: A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/ +- Summary: Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Hardhat. -# Cryptography +# Deploy an ERC-20 to Polkadot Hub ## Introduction -Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem. - -## Hash Functions - -Hash functions are fundamental to blockchain technology, creating a unique digital fingerprint for any piece of data, including simple text, images, or any other form of file. They map input data of any size to a fixed-size output (typically 32 bytes) using complex mathematical operations. Hashing is used to verify data integrity, create digital signatures, and provide a secure way to store passwords. This form of mapping is known as the ["pigeonhole principle,"](https://en.wikipedia.org/wiki/Pigeonhole_principle){target=\_blank} it is primarily implemented to efficiently and verifiably identify data from large sets. - -### Key Properties of Hash Functions - -- **Deterministic**: The same input always produces the same output. -- **Quick computation**: It's easy to calculate the hash value for any given input. -- **Pre-image resistance**: It's infeasible to generate the input data from its hash. -- **Small changes in input yield large changes in output**: Known as the ["avalanche effect"](https://en.wikipedia.org/wiki/Avalanche_effect){target=\_blank}. -- **Collision resistance**: The probabilities are extremely low to find two different inputs with the same hash. - -### Blake2 - -The Polkadot SDK utilizes Blake2, a state-of-the-art hashing method that offers: - -- Equal or greater security compared to [SHA-2](https://en.wikipedia.org/wiki/SHA-2){target=\_blank}. -- Significantly faster performance than other algorithms. - -These properties make Blake2 ideal for blockchain systems, reducing sync times for new nodes and lowering the resources required for validation. For detailed technical specifications about Blake2, see the [official Blake2 paper](https://www.blake2.net/blake2.pdf){target=\_blank}. - -## Types of Cryptography - -There are two different ways that cryptographic algorithms are implemented: symmetric cryptography and asymmetric cryptography. - -### Symmetric Cryptography - -Symmetric encryption is a branch of cryptography that isn't based on one-way functions, unlike asymmetric cryptography. It uses the same cryptographic key to encrypt plain text and decrypt the resulting ciphertext. - -Symmetric cryptography is a type of encryption that has been used throughout history, such as the Enigma Cipher and the Caesar Cipher. It is still widely used today and can be found in Web2 and Web3 applications alike. There is only one single key, and a recipient must also have access to it to access the contained information. +[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. -#### Advantages {: #symmetric-advantages } +This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Hardhat](https://hardhat.org/){target=\_blank}, an Ethereum development environment. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. -- Fast and efficient for large amounts of data. -- Requires less computational power. +## Prerequisites -#### Disadvantages {: #symmetric-disadvantages } +Before starting, make sure you have: -- Key distribution can be challenging. -- Scalability issues in systems with many users. +- Basic understanding of Solidity programming and fungible tokens. +- Node.js v22.13.1 or later. +- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -### Asymmetric Cryptography +## Set Up Your Project -Asymmetric encryption is a type of cryptography that uses two different keys, known as a keypair: a public key, used to encrypt plain text, and a private counterpart, used to decrypt the ciphertext. +This tutorial uses a [Hardhat ERC-20 template](https://github.com/polkadot-developers/revm-hardhat-examples/tree/master/erc20-hardhat){target=\_blank} that contains all the necessary files. To get started, take the following steps: -The public key encrypts a fixed-length message that can only be decrypted with the recipient's private key and, sometimes, a set password. The public key can be used to cryptographically verify that the corresponding private key was used to create a piece of data without compromising the private key, such as with digital signatures. This has obvious implications for identity, ownership, and properties and is used in many different protocols across Web2 and Web3. +1. Clone the GitHub repository locally: -#### Advantages {: #asymmetric-advantages } + ```bash + git clone https://github.com/polkadot-developers/revm-hardhat-examples/ + cd revm-hardhat-examples/erc20-hardhat + ``` -- Solves the key distribution problem. -- Enables digital signatures and secure key exchange. +2. Install the dependencies: -#### Disadvantages {: #asymmetric-disadvantages } + ```bash + npm i + ``` -- Slower than symmetric encryption. -- Requires more computational resources. +This will fetch all the necessary packages to help you deploy an ERC-20 with Hardhat to Polkadot. -### Trade-offs and Compromises +## Configure Hardhat -Symmetric cryptography is faster and requires fewer bits in the key to achieve the same level of security that asymmetric cryptography provides. However, it requires a shared secret before communication can occur, which poses issues to its integrity and a potential compromise point. On the other hand, asymmetric cryptography doesn't require the secret to be shared ahead of time, allowing for far better end-user security. +Once you've [setup your project](#set-up-your-project), you can configure the `hardhat.config.ts` to your needs. This tutorial has the file prepared to deploy to the Polkadot TestNet. -Hybrid symmetric and asymmetric cryptography is often used to overcome the engineering issues of asymmetric cryptography, as it is slower and requires more bits in the key to achieve the same level of security. It encrypts a key and then uses the comparatively lightweight symmetric cipher to do the "heavy lifting" with the message. +To store and use private keys or network URLs, you can use Hardhat's configuration variables. This can be set via tasks in the **vars** scope. For example, to store the private key to deploy to the Polkadot TestNet, run the following command: -## Digital Signatures +```bash +npx hardhat vars set TESTNET_PRIVATE_KEY +``` -Digital signatures are a way of verifying the authenticity of a document or message using asymmetric keypairs. They are used to ensure that a sender or signer's document or message hasn't been tampered with in transit, and for recipients to verify that the data is accurate and from the expected sender. +The command will initiate a wizard in which you'll have to enter the value to be stored: -Signing digital signatures only requires a low-level understanding of mathematics and cryptography. For a conceptual example -- when signing a check, it is expected that it cannot be cashed multiple times. This isn't a feature of the signature system but rather the check serialization system. The bank will check that the serial number on the check hasn't already been used. Digital signatures essentially combine these two concepts, allowing the signature to provide the serialization via a unique cryptographic fingerprint that cannot be reproduced. +
    + npx hardhat vars set TESTNET_PRIVATE_KEY + ✔ Enter value: · ••••••••• + The configuration variable has been stored in /Users/albertoviera/Library/Preferences/hardhat-nodejs/vars.json +
    -Unlike pen-and-paper signatures, knowledge of a digital signature cannot be used to create other signatures. Digital signatures are often used in bureaucratic processes, as they are more secure than simply scanning in a signature and pasting it onto a document. +??? warning "Key Encryption" + This solution just prevents variables to be included in the code repository. You should find a solution that encrypts private keys and access them securely. -Polkadot SDK provides multiple different cryptographic schemes and is generic so that it can support anything that implements the [`Pair` trait](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Pair.html){target=\_blank}. +You can now use the account related to this private key by importing it into the Hardhat configuration file: -### Example of Creating a Digital Signature +```ts title="hardhat.config.ts" hl_lines="1 17" -The process of creating and verifying a digital signature involves several steps: +const config: HardhatUserConfig = { + solidity: { + version: "0.8.28", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + networks: { + polkadotTestnet: { + url: vars.get("TESTNET_URL", "http://127.0.0.1:8545"), + accounts: vars.has("TESTNET_PRIVATE_KEY") ? [vars.get("TESTNET_PRIVATE_KEY")] : [], + }, + }, + mocha: { + timeout: 40000, + }, +}; -1. The sender creates a hash of the message. -2. The hash is encrypted using the sender's private key, creating the signature. -3. The message and signature are sent to the recipient. -4. The recipient decrypts the signature using the sender's public key. -5. The recipient hashes the received message and compares it to the decrypted hash. +export default config; +``` -If the hashes match, the signature is valid, confirming the message's integrity and the sender's identity. +## Compile your Contract -## Elliptic Curve +Once you've configured Hardhat, you can compile the contract. -Blockchain technology requires the ability to have multiple keys creating a signature for block proposal and validation. To this end, Elliptic Curve Digital Signature Algorithm (ECDSA) and Schnorr signatures are two of the most commonly used methods. While ECDSA is a far simpler implementation, Schnorr signatures are more efficient when it comes to multi-signatures. +In this tutorial, a simple ERC-20 is provided. Therefore, to compile the contract you can run the following command: -Schnorr signatures bring some noticeable features over the ECDSA/EdDSA schemes: +```bash +npx hardhat compile +``` -- It is better for hierarchical deterministic key derivations. -- It allows for native multi-signature through [signature aggregation](https://bitcoincore.org/en/2017/03/23/schnorr-signature-aggregation/){target=\_blank}. -- It is generally more resistant to misuse. +If everything compiles successfully, you should see the following output: -One sacrifice that is made when using Schnorr signatures over ECDSA is that both require 64 bytes, but only ECDSA signatures communicate their public key. +
    + npx hardhat compile + Generating typings for: 23 artifacts in dir: typechain-types for target: ethers-v6 + Successfully generated 62 typings! + Compiled 21 Solidity files successfully (evm target: paris). +
    -### Various Implementations +## Test your Contract -- **[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm){target=\_blank}**: Polkadot SDK provides an ECDSA signature scheme using the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1){target=\_blank} curve. This is the same cryptographic algorithm used to secure [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin){target=\_blank} and [Ethereum](https://en.wikipedia.org/wiki/Ethereum){target=\_blank}. +Hardhat has a native feature to test contracts. You can run tests against the local Hardhat development node, but it could have some technical differences to Polkadot. Therefore, in this tutorial, you'll be testing against the Polkadot TestNet -- **[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519){target=\_blank}**: An EdDSA signature scheme using [Curve25519](https://en.wikipedia.org/wiki/Curve25519){target=\_blank}. It is carefully engineered at several levels of design and implementation to achieve very high speeds without compromising security. +This example has a predefined test file located in [`test/Token.test.js`](https://github.com/polkadot-developers/revm-hardhat-examples/blob/master/erc20-hardhat/test/MyToken.test.ts){target=\_blank}, that runs the following tests: -- **[SR25519](https://research.web3.foundation/Polkadot/security/keys/accounts-more){target=\_blank}**: Based on the same underlying curve as Ed25519. However, it uses Schnorr signatures instead of the EdDSA scheme. +1. The token was deployed by verifying its **name** and **symbol**. +2. The token has the right owner configured. +3. The token has an initial supply of zero. +4. The owner can mint tokens. +5. The total supply is increased after a mint. +6. Perform multiple mints to different addresses and checks the balance of each address and the new total supply. +To run the test, you can execute the following command: ---- +```bash +npx hardhat test --network polkadotTestnet +``` -Page Title: Data Encoding +If tests are successful, you should see the following logs: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/data-encoding/ -- Summary: SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. - -# Data Encoding +
    + npx hardhat test --network polkadotTestnet + +   MyToken +     Deployment +       ✔ Should have correct name and symbol +       ✔ Should set the right owner +       ✔ Should have zero initial supply +     Minting +       ✔ Should allow owner to mint tokens +       ✔ Should increase total supply on mint +     Multiple mints +       ✔ Should correctly track balance after multiple mints + +   6 passing (369ms) +
    -## Introduction +## Deploy your Contract -The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data. +With the Hardhat configuration file ready, the private key stored as a variable under **vars**, and the contract compiled, you can proceed to deploy the contract to a given network. In this tutorial, you are deploying it to the Polkadot TestNet. -The SCALE codec enables communication between the runtime and the outer node. This mechanism is designed for high-performance, copy-free data encoding and decoding in resource-constrained environments like the Polkadot SDK [Wasm runtime](/develop/parachains/deployment/build-deterministic-runtime/#introduction){target=\_blank}. +To deploy the contract, run the following command: -It is not self-describing, meaning the decoding context must fully know the encoded data types. +```bash +npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet +``` -Parity's libraries utilize the [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} crate (a Rust implementation of the SCALE codec) to handle encoding and decoding for interactions between RPCs and the runtime. +You'll need to confirm the target network (by chain ID): -The `codec` mechanism is ideal for Polkadot SDK-based chains because: +
    + npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet + ✔ Confirm deploy to network polkadotTestnet (420420420)? … yes +   + Hardhat Ignition 🚀 +   + Deploying [ TokenModule ] +   + Batch #1 + Executed TokenModule#MyToken +   + Batch #2 + Executed TokenModule#MyToken.mint +   + [ TokenModule ] successfully deployed 🚀 +   + Deployed Addresses +   + TokenModule#MyToken - 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3 +
    -- It is lightweight compared to generic serialization frameworks like [`serde`](https://serde.rs/){target=\_blank}, which add unnecessary bulk to binaries. -- It doesn’t rely on Rust’s `libstd`, making it compatible with `no_std` environments like Wasm runtime. -- It integrates seamlessly with Rust, allowing easy derivation of encoding and decoding logic for new types using `#[derive(Encode, Decode)]`. +And that is it! You've successfully deployed an ERC-20 token contract to the Polkadot TestNet using Hardhat. -Defining a custom encoding scheme in the Polkadot SDK-based chains, rather than using an existing Rust codec library, is crucial for enabling cross-platform and multi-language support. +## Where to Go Next -## SCALE Codec +
    -The codec is implemented using the following traits: +- Guide __Deploy an NFT with Remix__ -- [`Encode`](#encode) -- [`Decode`](#decode) -- [`CompactAs`](#compactas) -- [`HasCompact`](#hascompact) -- [`EncodeLike`](#encodelike) + --- -### Encode + Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. -The [`Encode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Encode.html){target=\_blank} trait handles data encoding into SCALE format and includes the following key functions: + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) -- **`size_hint(&self) -> usize`**: Estimates the number of bytes required for encoding to prevent multiple memory allocations. This should be inexpensive and avoid complex operations. Optional if the size isn’t known. -- **`encode_to(&self, dest: &mut T)`**: Encodes the data, appending it to a destination buffer. -- **`encode(&self) -> Vec`**: Encodes the data and returns it as a byte vector. -- **`using_encoded R>(&self, f: F) -> R`**: Encodes the data and passes it to a closure, returning the result. -- **`encoded_size(&self) -> usize`**: Calculates the encoded size. Should be used when the encoded data isn’t required. +
    -!!!tip - For best performance, value types should override `using_encoded`, and allocating types should override `encode_to`. It's recommended to implement `size_hint` for all types where possible. -### Decode +--- -The [`Decode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Decode.html){target=\_blank} trait handles decoding SCALE-encoded data back into the appropriate types: +Page Title: Deploy an ERC-20 to Polkadot Hub -- **`fn decode(value: &mut I) -> Result`**: Decodes data from the SCALE format, returning an error if decoding fails. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/ +- Summary: Deploy an ERC-20 token contract on Polkadot Hub. This guide covers contract creation, compilation, deployment, and interaction via the Remix IDE. -### CompactAs +# Deploy an ERC-20 to Polkadot Hub -The [`CompactAs`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.CompactAs.html){target=\_blank} trait wraps custom types for compact encoding: +## Introduction -- **`encode_as(&self) -> &Self::As`**: Encodes the type as a compact type. -- **`decode_from(_: Self::As) -> Result`**: decodes from a compact encoded type. +[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. -### HasCompact +This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Remix IDE](https://remix.ethereum.org/){target=\_blank}, a web-based development tool. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. -The [`HasCompact`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.HasCompact.html){target=\_blank} trait indicates a type supports compact encoding. +## Prerequisites -### EncodeLike +Before starting, make sure you have: -The [`EncodeLike`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.EncodeLike.html){target=\_blank} trait is used to ensure multiple types that encode similarly are accepted by the same function. When using `derive`, it is automatically implemented. +- Basic understanding of Solidity programming and fungible tokens. +- An EVM-compatible wallet [connected to Polkadot Hub](/smart-contracts/integrations/wallets){target=\_blank}. This example utilizes [MetaMask](https://metamask.io/){target=\_blank}. +- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -### Data Types +## Create Your Contract -The table below outlines how the Rust implementation of the Parity SCALE codec encodes different data types. +To create the ERC-20 contract, you can follow the steps below: -| Type | Description | Example SCALE Decoded Value | SCALE Encoded Value | -|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| -| Boolean | Boolean values are encoded using the least significant bit of a single byte. | `false` / `true` | `0x00` / `0x01` | -| Compact/general integers | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2^536) and is more efficient at encoding most values than the fixed-width version. | `unsigned integer 0` / `unsigned integer 1` / `unsigned integer 42` / `unsigned integer 69` / `unsigned integer 65535` / `BigInt(100000000000000)` | `0x00` / `0x04` / `0xa8` / `0x1501` / `0xfeff0300` / `0x0b00407a10f35a` | -| Enumerations (tagged-unions) | A fixed number of variants, each mutually exclusive and potentially implying a further value or series of values. Encoded as the first byte identifying the index of the variant that the value is. Any further bytes are used to encode any data that the variant implies. Thus, no more than 256 variants are supported. | `Int(42)` and `Bool(true)` where `enum IntOrBool { Int(u8), Bool(bool) }` | `0x002a` and `0x0101` | -| Fixed-width integers | Basic integers are encoded using a fixed-width little-endian (LE) format. | `signed 8-bit integer 69` / `unsigned 16-bit integer 42` / `unsigned 32-bit integer 16777215` | `0x45` / `0x2a00` / `0xffffff00` | -| Options | One or zero values of a particular type. | `Some` / `None` | `0x01` followed by the encoded value / `0x00` | -| Results | Results are commonly used enumerations which indicate whether certain operations were successful or unsuccessful. | `Ok(42)` / `Err(false)` | `0x002a` / `0x0100` | -| Strings | Strings are Vectors of bytes (Vec) containing a valid UTF8 sequence. | | | -| Structs | For structures, the values are named, but that is irrelevant for the encoding (names are ignored - only order matters). | `SortedVecAsc::from([3, 5, 2, 8])` | `[3, 2, 5, 8] ` | -| Tuples | A fixed-size series of values, each with a possibly different but predetermined and fixed type. This is simply the concatenation of each encoded value. | Tuple of compact unsigned integer and boolean: `(3, false)` | `0x0c00` | -| Vectors (lists, series, sets) | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. | Vector of unsigned `16`-bit integers: `[4, 8, 15, 16, 23, 42]` | `0x18040008000f00100017002a00` | +1. Navigate to the [Polkadot Remix IDE](https://remix.polkadot.io){target=\_blank}. +2. Click in the **Create new file** button under the **contracts** folder, and name your contract as `MyToken.sol`. -## Encode and Decode Rust Trait Implementations + ![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-1.webp) -Here's how the `Encode` and `Decode` traits are implemented: +3. Now, paste the following ERC-20 contract code into the editor: + ```solidity title="MyToken.sol" + // SPDX-License-Identifier: MIT + // Compatible with OpenZeppelin Contracts ^5.4.0 + pragma solidity ^0.8.27; -```rust -use parity_scale_codec::{Encode, Decode}; - -[derive(Debug, PartialEq, Encode, Decode)] -enum EnumType { - #[codec(index = 15)] - A, - B(u32, u64), - C { - a: u32, - b: u64, - }, -} + import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; + import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -let a = EnumType::A; -let b = EnumType::B(1, 2); -let c = EnumType::C { a: 1, b: 2 }; + contract MyToken is ERC20, Ownable, ERC20Permit { + constructor(address initialOwner) + ERC20("MyToken", "MTK") + Ownable(initialOwner) + ERC20Permit("MyToken") + {} -a.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x0f"); -}); + function mint(address to, uint256 amount) public onlyOwner { + _mint(to, amount); + } + } + ``` -b.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); + The key components of the code above are: -c.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); + - Contract imports: -let mut da: &[u8] = b"\x0f"; -assert_eq!(EnumType::decode(&mut da).ok(), Some(a)); + - **[`ERC20.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/ERC20.sol){target=\_blank}**: The base contract for fungible tokens, implementing core functionality like transfers, approvals, and balance tracking. + - **[`ERC20Permit.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/extensions/ERC20Permit.sol){target=\_blank}**: [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612){target=\_blank} extension for ERC-20 that adds the [permit function](https://docs.openzeppelin.com/contracts/5.x/api/token/erc20#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-){target=\_blank}, allowing approvals via off-chain signatures (no on-chain tx from the holder). Manages nonces and EIP-712 domain separator and updates allowances when a valid signature is presented. + - **[`Ownable.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/access/Ownable.sol){target=\_blank}**: Provides basic authorization control, ensuring only the contract owner can mint new tokens. + + - Constructor parameters: -let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut db).ok(), Some(b)); + - **`initialOwner`**: Sets the address that will have administrative rights over the contract. + - **`"MyToken"`**: The full name of your token. + - **`"MTK"`**: The symbol representing your token in wallets and exchanges. -let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut dc).ok(), Some(c)); + - Key functions: -let mut dz: &[u8] = &[0]; -assert_eq!(EnumType::decode(&mut dz).ok(), None); -``` + - **`mint(address to, uint256 amount)`**: Allows the contract owner to create new tokens for any address. The amount should include 18 decimals (e.g., 1 token = 1000000000000000000). + - Inherited [Standard ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/){target=\_blank} functions: + - **`transfer(address recipient, uint256 amount)`**: Sends a specified amount of tokens to another address. + - **`approve(address spender, uint256 amount)`**: Grants permission for another address to spend a specific number of tokens on behalf of the token owner. + - **`transferFrom(address sender, address recipient, uint256 amount)`**: Transfers tokens from one address to another, if previously approved. + - **`balanceOf(address account)`**: Returns the token balance of a specific address. + - **`allowance(address owner, address spender)`**: Checks how many tokens an address is allowed to spend on behalf of another address. -## SCALE Codec Libraries + !!! tip + Use the [OpenZeppelin Contracts Wizard](https://wizard.openzeppelin.com/){target=\_blank} to generate customized smart contracts quickly. Simply configure your contract, copy the generated code, and paste it into the Remix IDE for deployment. Below is an example of an ERC-20 token contract created with it: -Several SCALE codec implementations are available in various languages. Here's a list of them: + ![Screenshot of the OpenZeppelin Contracts Wizard showing an ERC-20 contract configuration.](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-2.webp) + -- **AssemblyScript**: [`LimeChain/as-scale-codec`](https://github.com/LimeChain/as-scale-codec){target=\_blank} -- **C**: [`MatthewDarnell/cScale`](https://github.com/MatthewDarnell/cScale){target=\_blank} -- **C++**: [`qdrvm/scale-codec-cpp`](https://github.com/qdrvm/scale-codec-cpp){target=\_blank} -- **JavaScript**: [`polkadot-js/api`](https://github.com/polkadot-js/api){target=\_blank} -- **Dart**: [`leonardocustodio/polkadart`](https://github.com/leonardocustodio/polkadart){target=\_blank} -- **Haskell**: [`airalab/hs-web3`](https://github.com/airalab/hs-web3/tree/master/packages/scale){target=\_blank} -- **Golang**: [`itering/scale.go`](https://github.com/itering/scale.go){target=\_blank} -- **Java**: [`splix/polkaj`](https://github.com/splix/polkaj){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **Ruby**: [` wuminzhe/scale_rb`](https://github.com/wuminzhe/scale_rb){target=\_blank} -- **TypeScript**: [`parity-scale-codec-ts`](https://github.com/tjjfvi/subshape){target=\_blank}, [`scale-ts`](https://github.com/unstoppablejs/unstoppablejs/tree/main/packages/scale-ts#scale-ts){target=\_blank}, [`soramitsu/scale-codec-js-library`](https://github.com/soramitsu/scale-codec-js-library){target=\_blank}, [`subsquid/scale-codec`](https://github.com/subsquid/squid-sdk/tree/master/substrate/scale-codec){target=\_blank} +## Compile +The compilation transforms your Solidity source code into bytecode that can be deployed on the blockchain. During this process, the compiler checks your contract for syntax errors, ensures type safety, and generates the machine-readable instructions needed for blockchain execution. ---- +To compile your contract, ensure you have it opened in the Remix IDE Editor, and follow the instructions below: -Page Title: Dedot +1. Select the **Solidity Compiler** plugin from the left panel. +2. Click the **Compile MyToken.sol** button. +3. If the compilation succeeded, you'll see a green checkmark indicating success in the **Solidity Compiler** icon. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/dedot/ -- Summary: Dedot is a next-gen JavaScript client for Polkadot and Polkadot SDK-based blockchains, offering lightweight, tree-shakable APIs with strong TypeScript support. +![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-3.gif) -# Dedot +## Deploy -## Introduction +Deployment is the process of publishing your compiled smart contract to the blockchain, making it permanently available for interaction. During deployment, you'll create a new instance of your contract on the blockchain, which involves: -[Dedot](https://github.com/dedotdev/dedot){target=\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\_blank}. +1. Select the **Deploy & Run Transactions** plugin from the left panel. +2. Configure the deployment settings: + 1. From the **ENVIRONMENT** dropdown, select **Injected Provider - MetaMask** (check the [Deploying Contracts](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} section of the Remix IDE guide for more details). + 2. (Optional) From the **ACCOUNT** dropdown, select the acccount you want to use for the deploy. -### Key Features +3. Configure the contract parameters: + 1. Enter the address that will own the deployed token contract. + 2. Click the **Deploy** button to initiate the deployment. -- **Lightweight and tree-shakable**: No more bn.js or WebAssembly blobs, optimized for dapps bundle size. -- **Fully typed API**: Comprehensive TypeScript support for seamless on-chain interaction and ink! smart contract integration. -- **Multi-version JSON-RPC support**: Compatible with both [legacy](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md){target=\_blank} and [new](https://paritytech.github.io/json-rpc-interface-spec/introduction.html){target=\_blank} JSON-RPC APIs for broad ecosystem interoperability. -- **Light client support**: Designed to work with light clients such as [Smoldot](https://github.com/smol-dot/smoldot){target=\_blank}. -- **Native TypeScript for scale codec**: Implements scale codec parsing directly in TypeScript without relying on custom wrappers. -- **Wallet integration**: Works out-of-the-box with [@polkadot/extension-based](https://github.com/polkadot-js/extension?tab=readme-ov-file#api-interface){target=\_blank} wallets. -- **Familiar API design**: Similar API style to Polkadot.js for easy and fast migration. +4. **MetaMask will pop up**: Review the transaction details. Click **Confirm** to deploy your contract. +5. If the deployment process succeeded, you will see the transaction details in the terminal, including the contract address and deployment transaction hash. -## Installation +![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-4.gif) -To add Dedot to your project, use the following command: +## Interact with Your Contract -=== "npm" +Once deployed, you can interact with your contract through Remix. Find your contract under **Deployed/Unpinned Contracts**, and click it to expand the available methods. In this example, you'll mint some tokens to a given address: - ```bash - npm i dedot - ``` +1. Expand the **mint** function: + 1. Enter the recipient address and the amount (remember to add 18 zeros for 1 whole token). + 2. Click **transact**. -=== "pnpm" +2. Click **Approve** to confirm the transaction in the MetaMask popup. - ```bash - pnpm add dedot - ``` +3. If the transaction succeeds, you will see a green check mark in the terminal. -=== "yarn" +4. You can also call the **balanceOf** function by passing the address of the **mint** call to confirm the new balance. - ```bash - yarn add dedot - ``` +![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-5.gif) -To enable auto-completion/IntelliSense for individual chains, install the [`@dedot/chaintypes`](https://www.npmjs.com/package/@dedot/chaintypes){target=\_blank} package as a development dependency: -=== "npm" +Other standard functions you can use: - ```bash - npm i -D @dedot/chaintypes - ``` +- **`transfer(address to, uint256 amount)`**: Send tokens to another address. +- **`approve(address spender, uint256 amount)`**: Allow another address to spend your tokens. -=== "pnpm" +Feel free to explore and interact with the contract's other functions using the same approach: select the method, provide any required parameters, and confirm the transaction in MetaMask when needed. - ```bash - pnpm add -D @dedot/chaintypes - ``` +## Where to Go Next -=== "yarn" +
    - ```bash - yarn add -D @dedot/chaintypes - ``` +- Guide __Deploy an NFT with Remix__ -## Get Started + --- -### Initialize a Client Instance + Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. -To connect to and interact with different networks, Dedot provides two client options depending on your needs: + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) -- **[`DedotClient`](https://docs.dedot.dev/clients-and-providers/clients#dedotclient){target=\_blank}**: Interacts with chains via the [new JSON-RPC APIs](https://paritytech.github.io/json-rpc-interface-spec/introduction.html){target=\_blank}. -- **[`LegacyClient`](https://docs.dedot.dev/clients-and-providers/clients#legacyclient){target=\_blank}**: Interacts with chains via the [legacy JSON-RPC APIs](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md){target=\_blank}. +
    -Use the following snippets to connect to Polkadot using `DedotClient`: -=== "WebSocket" +--- - ```typescript - import { DedotClient, WsProvider } from 'dedot'; - import type { PolkadotApi } from '@dedot/chaintypes'; +Page Title: Deploy an NFT to Polkadot Hub with Foundry - // Initialize providers & clients - const provider = new WsProvider('wss://rpc.polkadot.io'); - const client = await DedotClient.new(provider); +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/.foundry/ +- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Foundry, a Rust toolkit with high-performance compilation. - ``` +# Deploy an NFT with Foundry -=== "Light Client (Smoldot)" +## Introduction - ```typescript - import { DedotClient, SmoldotProvider } from 'dedot'; - import type { PolkadotApi } from '@dedot/chaintypes'; - import * as smoldot from 'smoldot'; +Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. - // import `polkadot` chain spec to connect to Polkadot - import { polkadot } from '@substrate/connect-known-chains'; +This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. It showcases a secure approach using [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and the [Foundry](https://getfoundry.sh/){target=\_blank} toolchain. Foundry, a fast, Rust-written toolkit, ensures high-performance compilation and is fully compatible with the Hub’s EVM environment via standard Solidity compilation. - // Start smoldot instance & initialize a chain - const client = smoldot.start(); - const chain = await client.addChain({ chainSpec: polkadot }); +## Prerequisites - // Initialize providers & clients - const provider = new SmoldotProvider(chain); - const client = await DedotClient.new(provider); +- Basic understanding of Solidity programming and NFT standards. +- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank}. +- A wallet with a private key for signing transactions. - ``` +## Set Up Your Project -If the node doesn't support new JSON-RPC APIs yet, you can connect to the network using the `LegacyClient`, which is built on top of the legacy JSON-RPC APIs. +To get started, take the following steps: -```typescript -import { LegacyClient, WsProvider } from 'dedot'; -import type { PolkadotApi } from '@dedot/chaintypes'; +1. Install Foundry: -const provider = new WsProvider('wss://rpc.polkadot.io'); -const client = await LegacyClient.new(provider); + ```bash + curl -L https://foundry.paradigm.xyz | bash + foundryup + ``` -``` +2. Initialize your project: -### Enable Type and API Suggestions + ```bash + forge init foundry-nft-deployment + cd foundry-nft-deployment + ``` -It is recommended to specify the `ChainApi` interface (e.g., `PolkadotApi` in the example in the previous section) of the chain you want to interact with. This enables type and API suggestions/autocompletion for that particular chain (via IntelliSense). If you don't specify a `ChainApi` interface, a default `SubstrateApi` interface will be used. +3. Install OpenZeppelin contracts: -```typescript -import { DedotClient, WsProvider } from 'dedot'; -import type { PolkadotApi, KusamaApi } from '@dedot/chaintypes'; + ```bash + forge install OpenZeppelin/openzeppelin-contracts + ``` -const polkadotClient = await DedotClient.new( - new WsProvider('wss://rpc.polkadot.io') -); -const kusamaClient = await DedotClient.new( - new WsProvider('wss://kusama-rpc.polkadot.io') -); -const genericClient = await DedotClient.new( - new WsProvider('ws://localhost:9944') -); +## Configure Foundry -``` +Edit `foundry.toml`: -If you don't find the `ChainApi` for the network you're working with in [the list](https://github.com/dedotdev/chaintypes?tab=readme-ov-file#supported-networks){target=\_blank}, you can generate the `ChainApi` (types and APIs) using the built-in [`dedot` cli](https://docs.dedot.dev/cli){target=\_blank}. +```toml title="foundry.toml" +[profile.default] +src = "src" +out = "out" +libs = ["lib"] +remappings = ['@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/'] -```bash -# Generate ChainApi interface for Polkadot network via rpc endpoint: wss://rpc.polkadot.io -npx dedot chaintypes -w wss://rpc.polkadot.io +[rpc_endpoints] +polkadot_hub_testnet = "https://testnet-passet-hub-eth-rpc.polkadot.io" ``` -Or open a pull request to add your favorite network to the [`@dedot/chaintypes`](https://github.com/dedotdev/chaintypes){target=\_blank} repo. - -### Read On-Chain Data +## Create Your Contract -Dedot provides several ways to read data from the chain: +Create `src/MyNFT.sol`: -- **Access runtime constants**: Use the syntax `client.consts..` to inspect runtime constants (parameter types). +```solidity title="src/MyNFT.sol" +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; - ```typescript - const ss58Prefix = client.consts.system.ss58Prefix; - console.log('Polkadot ss58Prefix:', ss58Prefix); +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; - ``` +contract MyNFT is ERC721, Ownable { + uint256 private _nextTokenId; -- **Storage queries**: Use the syntax `client.query..` to query on-chain storage. + constructor(address initialOwner) + ERC721("MyToken", "MTK") + Ownable(initialOwner) + {} - ```typescript - const balance = await client.query.system.account('INSERT_ADDRESS'); - console.log('Balance:', balance.data.free); + function safeMint(address to) public onlyOwner { + uint256 tokenId = _nextTokenId++; + _safeMint(to, tokenId); + } +} +``` - ``` +## Compile -- **Subscribe to storage changes**: +```bash +forge build +``` - ```typescript - const unsub = await client.query.system.number((blockNumber) => { - console.log(`Current block number: ${blockNumber}`); - }); +Verify the compilation by inspecting the bytecode: - ``` +```bash +forge inspect MyNFT bytecode +``` -- **Call Runtime APIs**: Use the syntax `client.call..` to execute Runtime APIs. +## Deploy - ```typescript - const metadata = await client.call.metadata.metadataAtVersion(15); - console.log('Metadata V15', metadata); +Deploy to Polkadot Hub TestNet: - ``` +```bash +forge create MyNFT \ + --rpc-url polkadot_hub_testnet \ + --private-key YOUR_PRIVATE_KEY \ + --constructor-args YOUR_OWNER_ADDRESS \ + --broadcast +``` -- **Watch on-chain events**: Use the syntax `client.events..` to access pallet events. - - ```typescript - const unsub = await client.events.system.NewAccount.watch((events) => { - console.log('New Account Created', events); - }); +Replace `YOUR_PRIVATE_KEY` with your private key and `YOUR_OWNER_ADDRESS` with the address that will own the NFT contract. - ``` +## Where to Go Next -### Sign and Send Transactions - -Sign the transaction using `IKeyringPair` from Keyring ([`@polkadot/keyring`](https://polkadot.js.org/docs/keyring/start/sign-verify/){target=\_blank}) and send the transaction. - -```typescript -import { cryptoWaitReady } from '@polkadot/util-crypto'; -import { Keyring } from '@polkadot/keyring'; -// Setup keyring -await cryptoWaitReady(); -const keyring = new Keyring({ type: 'sr25519' }); -const alice = keyring.addFromUri('//Alice'); -// Send transaction -const unsub = await client.tx.balances - .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n) - .signAndSend(alice, async ({ status }) => { - console.log('Transaction status', status.type); - if (status.type === 'BestChainBlockIncluded') { - console.log(`Transaction is included in best block`); - } - if (status.type === 'Finalized') { - console.log( - `Transaction completed at block hash ${status.value.blockHash}` - ); - await unsub(); - } - }); +
    -``` +- Guide __Verify Your Contract__ -You can also use `Signer` from wallet extensions: + --- -```typescript -const injected = await window.injectedWeb3['polkadot-js'].enable('My dApp'); -const account = (await injected.accounts.get())[0]; -const signer = injected.signer; -const unsub = await client.tx.balances - .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n) - .signAndSend(account.address, { signer }, async ({ status }) => { - console.log('Transaction status', status.type); - if (status.type === 'BestChainBlockIncluded') { - console.log(`Transaction is included in best block`); - } - if (status.type === 'Finalized') { - console.log( - `Transaction completed at block hash ${status.value.blockHash}` - ); - await unsub(); - } - }); + Now that you've deployed an NFT contract, learn how to verify it with Foundry. -``` + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/foundry/verify-a-contract/) -## Where to Go Next +- Guide __Deploy an ERC-20__ + + --- + + Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Foundry. + + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/foundry/) -For more detailed information about Dedot, check the [official documentation](https://dedot.dev/){target=\_blank}. +
    --- -Page Title: Deploy an ERC-20 to Polkadot Hub +Page Title: Deploy an NFT to Polkadot Hub with Hardhat -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-hardhat/ -- Summary: Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Hardhat. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/ +- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub with Hardhat, a comprehenive development environment with built-in deployment capabilities. -# Deploy an ERC-20 to Polkadot Hub +# Deploy an NFT with Hardhat ## Introduction -[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. +Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. -This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Hardhat](https://hardhat.org/){target=\_blank}, an Ethereum development environment. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. +This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Hardhat](https://hardhat.org/docs/getting-started){target=\_blank}, a comprehensive development environment with built-in testing, debugging, and deployment capabilities. Hardhat uses standard Solidity compilation to generate EVM bytecode, making it fully compatible with Polkadot Hub's EVM environment. ## Prerequisites -Before starting, make sure you have: - -- Basic understanding of Solidity programming and fungible tokens. +- Basic understanding of Solidity programming and NFT standards. - Node.js v22.13.1 or later. - A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. +- A wallet with a private key for signing transactions. ## Set Up Your Project -This tutorial uses a [Hardhat ERC-20 template](https://github.com/polkadot-developers/revm-hardhat-examples/tree/master/erc20-hardhat){target=\_blank} that contains all the necessary files. To get started, take the following steps: +Take the following steps to get started: -1. Clone the GitHub repository locally: +1. Initialize your Hardhat project: ```bash - git clone https://github.com/polkadot-developers/revm-hardhat-examples/ - cd revm-hardhat-examples/erc20-hardhat + mkdir hardhat-nft-deployment + cd hardhat-nft-deployment + npx hardhat --init ``` -2. Install the dependencies: +2. Install OpenZeppelin contracts: ```bash - npm i + npm install @openzeppelin/contracts ``` -This will fetch all the necessary packages to help you deploy an ERC-20 with Hardhat to Polkadot. - ## Configure Hardhat -Once you've [setup your project](#set-up-your-project), you can configure the `hardhat.config.ts` to your needs. This tutorial has the file prepared to deploy to the Polkadot TestNet. - -To store and use private keys or network URLs, you can use Hardhat's configuration variables. This can be set via tasks in the **vars** scope. For example, to store the private key to deploy to the Polkadot TestNet, run the following command: - -```bash -npx hardhat vars set TESTNET_PRIVATE_KEY -``` - -The command will initiate a wizard in which you'll have to enter the value to be stored: - -
    - npx hardhat vars set TESTNET_PRIVATE_KEY - ✔ Enter value: · ••••••••• - The configuration variable has been stored in /Users/albertoviera/Library/Preferences/hardhat-nodejs/vars.json -
    - -??? warning "Key Encryption" - This solution just prevents variables to be included in the code repository. You should find a solution that encrypts private keys and access them securely. +Edit `hardhat.config.ts`: -You can now use the account related to this private key by importing it into the Hardhat configuration file: +```typescript title="hardhat.config.ts" +import type { HardhatUserConfig } from 'hardhat/config'; -```ts title="hardhat.config.ts" hl_lines="1 17" +import hardhatToolboxViemPlugin from '@nomicfoundation/hardhat-toolbox-viem'; +import { configVariable } from 'hardhat/config'; const config: HardhatUserConfig = { + plugins: [hardhatToolboxViemPlugin], solidity: { - version: "0.8.28", - settings: { - optimizer: { - enabled: true, - runs: 200, + profiles: { + default: { + version: '0.8.28', + }, + production: { + version: '0.8.28', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, }, }, }, networks: { - polkadotTestnet: { - url: vars.get("TESTNET_URL", "http://127.0.0.1:8545"), - accounts: vars.has("TESTNET_PRIVATE_KEY") ? [vars.get("TESTNET_PRIVATE_KEY")] : [], + hardhatMainnet: { + type: 'edr-simulated', + chainType: 'l1', + }, + hardhatOp: { + type: 'edr-simulated', + chainType: 'op', + }, + sepolia: { + type: 'http', + chainType: 'l1', + url: configVariable('SEPOLIA_RPC_URL'), + accounts: [configVariable('SEPOLIA_PRIVATE_KEY')], + }, + polkadotHubTestnet: { + type: 'http', + url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + accounts: [configVariable('PRIVATE_KEY')], }, - }, - mocha: { - timeout: 40000, }, }; export default config; ``` -## Compile your Contract - -Once you've configured Hardhat, you can compile the contract. - -In this tutorial, a simple ERC-20 is provided. Therefore, to compile the contract you can run the following command: +!!! tip + Learn how to use Hardhat's [Config Variables](https://hardhat.org/docs/learn-more/configuration-variables){target=\_blank} to handle your private keys in a secure way. -```bash -npx hardhat compile -``` +## Create Your Contract -If everything compiles successfully, you should see the following output: +Create `contracts/MyNFT.sol`: -
    - npx hardhat compile - Generating typings for: 23 artifacts in dir: typechain-types for target: ethers-v6 - Successfully generated 62 typings! - Compiled 21 Solidity files successfully (evm target: paris). -
    +```solidity title="contracts/MyNFT.sol" +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; -## Test your Contract +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; -Hardhat has a native feature to test contracts. You can run tests against the local Hardhat development node, but it could have some technical differences to Polkadot. Therefore, in this tutorial, you'll be testing against the Polkadot TestNet +contract MyNFT is ERC721, Ownable { + uint256 private _nextTokenId; -This example has a predefined test file located in [`test/Token.test.js`](https://github.com/polkadot-developers/revm-hardhat-examples/blob/master/erc20-hardhat/test/MyToken.test.ts){target=\_blank}, that runs the following tests: + constructor(address initialOwner) + ERC721("MyToken", "MTK") + Ownable(initialOwner) + {} -1. The token was deployed by verifying its **name** and **symbol**. -2. The token has the right owner configured. -3. The token has an initial supply of zero. -4. The owner can mint tokens. -5. The total supply is increased after a mint. -6. Perform multiple mints to different addresses and checks the balance of each address and the new total supply. + function safeMint(address to) public onlyOwner { + uint256 tokenId = _nextTokenId++; + _safeMint(to, tokenId); + } +} +``` -To run the test, you can execute the following command: +## Compile ```bash -npx hardhat test --network polkadotTestnet +npx hardhat compile ``` -If tests are successful, you should see the following logs: - -
    - npx hardhat test --network polkadotTestnet - -   MyToken -     Deployment -       ✔ Should have correct name and symbol -       ✔ Should set the right owner -       ✔ Should have zero initial supply -     Minting -       ✔ Should allow owner to mint tokens -       ✔ Should increase total supply on mint -     Multiple mints -       ✔ Should correctly track balance after multiple mints - -   6 passing (369ms) -
    - -## Deploy your Contract +## Set Up Deployment -With the Hardhat configuration file ready, the private key stored as a variable under **vars**, and the contract compiled, you can proceed to deploy the contract to a given network. In this tutorial, you are deploying it to the Polkadot TestNet. +Create a deployment module in `ignition/modules/MyNFT.ts`: -To deploy the contract, run the following command: +```typescript title="ignition/modules/MyNFT.ts" +import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; -```bash -npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet +export default buildModule('MyNFTModule', (m) => { + const initialOwner = m.getParameter('initialOwner', 'INSERT_OWNER_ADDRESS'); + const myNFT = m.contract('MyNFT', [initialOwner]); + return { myNFT }; +}); ``` -You'll need to confirm the target network (by chain ID): +Replace `INSERT_OWNER_ADDRESS` with your desired owner address. -
    - npx hardhat ignition deploy ./ignition/modules/MyToken.ts --network polkadotTestnet - ✔ Confirm deploy to network polkadotTestnet (420420420)? … yes -   - Hardhat Ignition 🚀 -   - Deploying [ TokenModule ] -   - Batch #1 - Executed TokenModule#MyToken -   - Batch #2 - Executed TokenModule#MyToken.mint -   - [ TokenModule ] successfully deployed 🚀 -   - Deployed Addresses -   - TokenModule#MyToken - 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3 -
    +## Deploy -And that is it! You've successfully deployed an ERC-20 token contract to the Polkadot TestNet using Hardhat. +Deploy to Polkadot Hub TestNet: + +```bash +npx hardhat ignition deploy ignition/modules/MyNFT.ts --network polkadotHubTestnet +``` ## Where to Go Next
    -- Guide __Deploy an NFT with Remix__ +- Guide __Verify Your Contract__ --- - Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. + Now that you've deployed an NFT contract, learn how to verify it with Hardhat. - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/verify-a-contract/) -
    + +- Guide __Deploy an ERC-20__ + + --- + + Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Hardhat. + + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/hardhat/) + +
    --- -Page Title: Deploy an ERC-20 to Polkadot Hub +Page Title: Deploy an NFT to Polkadot Hub with Remix -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix/ -- Summary: Deploy an ERC-20 token contract on Polkadot Hub. This guide covers contract creation, compilation, deployment, and interaction via the Remix IDE. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/ +- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Remix, a browser-based IDE for quick prototyping and learning. -# Deploy an ERC-20 to Polkadot Hub +# Deploy an NFT with Remix ## Introduction -[ERC-20](https://eips.ethereum.org/EIPS/eip-20){target=\_blank} tokens are fungible tokens commonly used for creating cryptocurrencies, governance tokens, and staking mechanisms. Polkadot Hub enables easy token deployment with Ethereum-compatible smart contracts and tools via the EVM backend. +Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. -This tutorial covers deploying an ERC-20 contract on the Polkadot Hub TestNet using [Remix IDE](https://remix.ethereum.org/){target=\_blank}, a web-based development tool. The ERC-20 contract can be retrieved from OpenZeppelin's [GitHub repository](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20){target=\_blank} or their [Contract Wizard](https://wizard.openzeppelin.com/){target=\_blank}. +This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Remix](https://remix.ethereum.org/){target=\_blank}, a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development. ## Prerequisites -Before starting, make sure you have: - -- Basic understanding of Solidity programming and fungible tokens. -- An EVM-compatible wallet [connected to Polkadot Hub](/smart-contracts/integrations/wallets){target=\_blank}. This example utilizes [MetaMask](https://metamask.io/){target=\_blank}. -- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. +- Basic understanding of Solidity programming and NFT standards. +- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank} +- A wallet with a private key for signing transactions. -## Create Your Contract +## Access Remix -To create the ERC-20 contract, you can follow the steps below: +Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. -1. Navigate to the [Polkadot Remix IDE](https://remix.polkadot.io){target=\_blank}. -2. Click in the **Create new file** button under the **contracts** folder, and name your contract as `MyToken.sol`. +The interface will load with a default workspace containing sample contracts. In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. - ![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-1.webp) +## Create Your Contract -3. Now, paste the following ERC-20 contract code into the editor: +1. Create a new file `contracts/MyNFT.sol`. +2. Paste the following code: - ```solidity title="MyToken.sol" + ```solidity title="contracts/MyNFT.sol" // SPDX-License-Identifier: MIT - // Compatible with OpenZeppelin Contracts ^5.4.0 - pragma solidity ^0.8.27; + pragma solidity ^0.8.20; - import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; - import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + import "@openzeppelin/contracts/access/Ownable.sol"; + + contract MyNFT is ERC721, Ownable { + uint256 private _nextTokenId; - contract MyToken is ERC20, Ownable, ERC20Permit { constructor(address initialOwner) - ERC20("MyToken", "MTK") + ERC721("MyToken", "MTK") Ownable(initialOwner) - ERC20Permit("MyToken") {} - function mint(address to, uint256 amount) public onlyOwner { - _mint(to, amount); + function safeMint(address to) public onlyOwner { + uint256 tokenId = _nextTokenId++; + _safeMint(to, tokenId); } } ``` - The key components of the code above are: +![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-01.webp) - - Contract imports: +## Compile - - **[`ERC20.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/ERC20.sol){target=\_blank}**: The base contract for fungible tokens, implementing core functionality like transfers, approvals, and balance tracking. - - **[`ERC20Permit.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/token/ERC20/extensions/ERC20Permit.sol){target=\_blank}**: [EIP-2612](https://eips.ethereum.org/EIPS/eip-2612){target=\_blank} extension for ERC-20 that adds the [permit function](https://docs.openzeppelin.com/contracts/5.x/api/token/erc20#ERC20Permit-permit-address-address-uint256-uint256-uint8-bytes32-bytes32-){target=\_blank}, allowing approvals via off-chain signatures (no on-chain tx from the holder). Manages nonces and EIP-712 domain separator and updates allowances when a valid signature is presented. - - **[`Ownable.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v5.4.0/contracts/access/Ownable.sol){target=\_blank}**: Provides basic authorization control, ensuring only the contract owner can mint new tokens. - - - Constructor parameters: +1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). +2. Click **Compile MyNFT.sol** or press `Ctrl+S`. - - **`initialOwner`**: Sets the address that will have administrative rights over the contract. - - **`"MyToken"`**: The full name of your token. - - **`"MTK"`**: The symbol representing your token in wallets and exchanges. +![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-02.webp) - - Key functions: +Compilation errors and warnings appear in the terminal panel at the bottom of the screen. - - **`mint(address to, uint256 amount)`**: Allows the contract owner to create new tokens for any address. The amount should include 18 decimals (e.g., 1 token = 1000000000000000000). - - Inherited [Standard ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/){target=\_blank} functions: - - **`transfer(address recipient, uint256 amount)`**: Sends a specified amount of tokens to another address. - - **`approve(address spender, uint256 amount)`**: Grants permission for another address to spend a specific number of tokens on behalf of the token owner. - - **`transferFrom(address sender, address recipient, uint256 amount)`**: Transfers tokens from one address to another, if previously approved. - - **`balanceOf(address account)`**: Returns the token balance of a specific address. - - **`allowance(address owner, address spender)`**: Checks how many tokens an address is allowed to spend on behalf of another address. +## Deploy - !!! tip - Use the [OpenZeppelin Contracts Wizard](https://wizard.openzeppelin.com/){target=\_blank} to generate customized smart contracts quickly. Simply configure your contract, copy the generated code, and paste it into the Remix IDE for deployment. Below is an example of an ERC-20 token contract created with it: +1. Navigate to the **Deploy & Run Transactions** tab. +2. Click the **Environment** dropdown, select **Browser Extension**, and click on **Injected Provider - MetaMask**. - ![Screenshot of the OpenZeppelin Contracts Wizard showing an ERC-20 contract configuration.](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-2.webp) - + ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-03.webp) -## Compile +3. In the deploy section, enter the initial owner address in the constructor parameter field. +4. Click **Deploy**. -The compilation transforms your Solidity source code into bytecode that can be deployed on the blockchain. During this process, the compiler checks your contract for syntax errors, ensures type safety, and generates the machine-readable instructions needed for blockchain execution. + ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-04.webp) -To compile your contract, ensure you have it opened in the Remix IDE Editor, and follow the instructions below: +5. Approve the transaction in your MetaMask wallet. -1. Select the **Solidity Compiler** plugin from the left panel. -2. Click the **Compile MyToken.sol** button. -3. If the compilation succeeded, you'll see a green checkmark indicating success in the **Solidity Compiler** icon. +Your deployed contract will appear in the **Deployed Contracts** section, ready for interaction. -![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-3.gif) +## Where to Go Next -## Deploy +
    -Deployment is the process of publishing your compiled smart contract to the blockchain, making it permanently available for interaction. During deployment, you'll create a new instance of your contract on the blockchain, which involves: +- Guide __Verify Your Contract__ -1. Select the **Deploy & Run Transactions** plugin from the left panel. -2. Configure the deployment settings: - 1. From the **ENVIRONMENT** dropdown, select **Injected Provider - MetaMask** (check the [Deploying Contracts](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} section of the Remix IDE guide for more details). - 2. (Optional) From the **ACCOUNT** dropdown, select the acccount you want to use for the deploy. + --- -3. Configure the contract parameters: - 1. Enter the address that will own the deployed token contract. - 2. Click the **Deploy** button to initiate the deployment. + Now that you've deployed an NFT contract, learn how to verify it with Remix. -4. **MetaMask will pop up**: Review the transaction details. Click **Confirm** to deploy your contract. -5. If the deployment process succeeded, you will see the transaction details in the terminal, including the contract address and deployment transaction hash. + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/verify-a-contract/) -![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-4.gif) +- Guide __Deploy an ERC-20__ -## Interact with Your Contract + --- -Once deployed, you can interact with your contract through Remix. Find your contract under **Deployed/Unpinned Contracts**, and click it to expand the available methods. In this example, you'll mint some tokens to a given address: + Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Remix. -1. Expand the **mint** function: - 1. Enter the recipient address and the amount (remember to add 18 zeros for 1 whole token). - 2. Click **transact**. + [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) -2. Click **Approve** to confirm the transaction in the MetaMask popup. +
    -3. If the transaction succeeds, you will see a green check mark in the terminal. -4. You can also call the **balanceOf** function by passing the address of the **mint** call to confirm the new balance. +--- -![](/images/smart-contracts/cookbook/smart-contracts/deploy-erc20/erc20-remix-5.gif) +Page Title: Deploy Contracts to Polkadot Hub with Ethers.js +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-ethers-js.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/ethers-js/ +- Summary: Learn how to interact with Polkadot Hub using Ethers.js, from compiling and deploying Solidity contracts to interacting with deployed smart contracts. -Other standard functions you can use: +# Ethers.js -- **`transfer(address to, uint256 amount)`**: Send tokens to another address. -- **`approve(address spender, uint256 amount)`**: Allow another address to spend your tokens. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -Feel free to explore and interact with the contract's other functions using the same approach: select the method, provide any required parameters, and confirm the transaction in MetaMask when needed. +[Ethers.js](https://docs.ethers.org/v6/){target=\_blank} is a lightweight library that enables interaction with Ethereum Virtual Machine (EVM)-compatible blockchains through JavaScript. Ethers is widely used as a toolkit to establish connections and read and write blockchain data. This article demonstrates using Ethers.js to interact and deploy smart contracts to Polkadot Hub. -## Where to Go Next +This guide is intended for developers who are familiar with JavaScript and want to interact with Polkadot Hub using Ethers.js. -
    +## Prerequisites -- Guide __Deploy an NFT with Remix__ +Before getting started, ensure you have the following installed: - --- +- **Node.js**: v22.13.1 or later, check the [Node.js installation guide](https://nodejs.org/en/download/current/){target=\_blank}. +- **npm**: v6.13.4 or later (comes bundled with Node.js). +- **Solidity**: This guide uses Solidity `^0.8.9` for smart contract development. - Walk through deploying an ERC-721 Non-Fungible Token (NFT) using OpenZeppelin's battle-tested NFT implementation and Remix. +## Project Structure - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) +This project organizes contracts, scripts, and compiled artifacts for easy development and deployment. -
    +```text title="Ethers.js Polkadot Hub" +ethers-project +├── contracts +│ ├── Storage.sol +├── scripts +│ ├── connectToProvider.js +│ ├── fetchLastBlock.js +│ ├── compile.js +│ ├── deploy.js +│ ├── checkStorage.js +├── abis +│ ├── Storage.json +├── artifacts +│ ├── Storage.polkavm +├── contract-address.json +├── node_modules/ +├── package.json +├── package-lock.json +└── README.md +``` + +## Set Up the Project +To start working with Ethers.js, create a new folder and initialize your project by running the following commands in your terminal: ---- +```bash +mkdir ethers-project +cd ethers-project +npm init -y +``` -Page Title: Deploy an NFT to Polkadot Hub with Foundry +## Install Dependencies -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/.foundry/ -- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Foundry, a Rust toolkit with high-performance compilation. +Next, run the following command to install the Ethers.js library: -# Deploy an NFT with Foundry +```bash +npm install ethers +``` -## Introduction +## Set Up the Ethers.js Provider -Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. +A [`Provider`](https://docs.ethers.org/v6/api/providers/#Provider){target=\_blank} is an abstraction of a connection to the Ethereum network, allowing you to query blockchain data and send transactions. It serves as a bridge between your application and the blockchain. -This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. It showcases a secure approach using [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and the [Foundry](https://getfoundry.sh/){target=\_blank} toolchain. Foundry, a fast, Rust-written toolkit, ensures high-performance compilation and is fully compatible with the Hub’s EVM environment via standard Solidity compilation. +To interact with Polkadot Hub, you must set up an Ethers.js provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. In the root of your project, create a file named `connectToProvider.js` and add the following code: -## Prerequisites +```js title="scripts/connectToProvider.js" +const { JsonRpcProvider } = require('ethers'); -- Basic understanding of Solidity programming and NFT standards. -- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank}. -- A wallet with a private key for signing transactions. +const createProvider = (rpcUrl, chainId, chainName) => { + const provider = new JsonRpcProvider(rpcUrl, { + chainId: chainId, + name: chainName, + }); -## Set Up Your Project + return provider; +}; -To get started, take the following steps: +const PROVIDER_RPC = { + rpc: 'INSERT_RPC_URL', + chainId: 'INSERT_CHAIN_ID', + name: 'INSERT_CHAIN_NAME', +}; -1. Install Foundry: +createProvider(PROVIDER_RPC.rpc, PROVIDER_RPC.chainId, PROVIDER_RPC.name); - ```bash - curl -L https://foundry.paradigm.xyz | bash - foundryup - ``` +``` -2. Initialize your project: +!!! note + Replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, and `INSERT_CHAIN_NAME` with the appropriate values. For example, to connect to Polkadot Hub TestNet's Ethereum RPC instance, you can use the following parameters: - ```bash - forge init foundry-nft-deployment - cd foundry-nft-deployment + ```js + const PROVIDER_RPC = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + name: 'polkadot-hub-testnet' + }; ``` -3. Install OpenZeppelin contracts: +To connect to the provider, execute: - ```bash - forge install OpenZeppelin/openzeppelin-contracts - ``` +```bash +node connectToProvider +``` -## Configure Foundry +With the provider set up, you can start querying the blockchain. For instance, to fetch the latest block number: -Edit `foundry.toml`: +??? code "Fetch Last Block code" -```toml title="foundry.toml" -[profile.default] -src = "src" -out = "out" -libs = ["lib"] -remappings = ['@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/'] + ```js title="scripts/fetchLastBlock.js" + const { JsonRpcProvider } = require('ethers'); -[rpc_endpoints] -polkadot_hub_testnet = "https://testnet-passet-hub-eth-rpc.polkadot.io" -``` + const createProvider = (rpcUrl, chainId, chainName) => { + const provider = new JsonRpcProvider(rpcUrl, { + chainId: chainId, + name: chainName, + }); -## Create Your Contract + return provider; + }; -Create `src/MyNFT.sol`: + const PROVIDER_RPC = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; -```solidity title="src/MyNFT.sol" -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; + const main = async () => { + try { + const provider = createProvider( + PROVIDER_RPC.rpc, + PROVIDER_RPC.chainId, + PROVIDER_RPC.name, + ); + const latestBlock = await provider.getBlockNumber(); + console.log(`Latest block: ${latestBlock}`); + } catch (error) { + console.error('Error connecting to Polkadot Hub TestNet: ' + error.message); + } + }; -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; + main(); -contract MyNFT is ERC721, Ownable { - uint256 private _nextTokenId; + ``` - constructor(address initialOwner) - ERC721("MyToken", "MTK") - Ownable(initialOwner) - {} +## Compile Contracts - function safeMint(address to) public onlyOwner { - uint256 tokenId = _nextTokenId++; - _safeMint(to, tokenId); - } -} -``` +!!! note "Contracts Code Blob Size Disclaimer" + The maximum contract code blob size on Polkadot Hub networks is _100 kilobytes_, significantly larger than Ethereum’s EVM limit of 24 kilobytes. -## Compile + For detailed comparisons and migration guidelines, see the [EVM vs. PolkaVM](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#current-memory-limits){target=\_blank} documentation page. -```bash -forge build -``` +The `revive` compiler transforms Solidity smart contracts into [PolkaVM](/smart-contracts/overview/#native-smart-contracts){target=\_blank} bytecode for deployment on Polkadot Hub. Revive's Ethereum RPC interface allows you to use familiar tools like Ethers.js and MetaMask to interact with contracts. -Verify the compilation by inspecting the bytecode: +### Install the Revive Library + +The [`@parity/resolc`](https://www.npmjs.com/package/@parity/resolc){target=\_blank} library will compile your Solidity code for deployment on Polkadot Hub. Run the following command in your terminal to install the library: ```bash -forge inspect MyNFT bytecode +npm install --save-dev @parity/resolc ``` -## Deploy +This guide uses `@parity/resolc` version `0.2.0`. -Deploy to Polkadot Hub TestNet: +### Sample Storage Smart Contract -```bash -forge create MyNFT \ - --rpc-url polkadot_hub_testnet \ - --private-key YOUR_PRIVATE_KEY \ - --constructor-args YOUR_OWNER_ADDRESS \ - --broadcast -``` +This example demonstrates compiling a `Storage.sol` Solidity contract for deployment to Polkadot Hub. The contract's functionality stores a number and permits users to update it with a new value. -Replace `YOUR_PRIVATE_KEY` with your private key and `YOUR_OWNER_ADDRESS` with the address that will own the NFT contract. +```solidity title="contracts/Storage.sol" +//SPDX-License-Identifier: MIT -## Where to Go Next +// Solidity files have to start with this pragma. +// It will be used by the Solidity compiler to validate its version. +pragma solidity ^0.8.9; -
    +contract Storage { + // Public state variable to store a number + uint256 public storedNumber; -- Guide __Verify Your Contract__ + /** + * Updates the stored number. + * + * The `public` modifier allows anyone to call this function. + * + * @param _newNumber - The new value to store. + */ + function setNumber(uint256 _newNumber) public { + storedNumber = _newNumber; + } +} +``` - --- +### Compile the Smart Contract - Now that you've deployed an NFT contract, learn how to verify it with Foundry. +To compile this contract, use the following script: - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/foundry/verify-a-contract/) +```js title="scripts/compile.js" +const { compile } = require('@parity/resolc'); +const { readFileSync, writeFileSync } = require('fs'); +const { basename, join } = require('path'); -- Guide __Deploy an ERC-20__ +const compileContract = async (solidityFilePath, outputDir) => { + try { + // Read the Solidity file + const source = readFileSync(solidityFilePath, 'utf8'); - --- + // Construct the input object for the compiler + const input = { + [basename(solidityFilePath)]: { content: source }, + }; - Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Foundry. + console.log(`Compiling contract: ${basename(solidityFilePath)}...`); - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/foundry/) + // Compile the contract + const out = await compile(input); -
    + for (const contracts of Object.values(out.contracts)) { + for (const [name, contract] of Object.entries(contracts)) { + console.log(`Compiled contract: ${name}`); + // Write the ABI + const abiPath = join(outputDir, `${name}.json`); + writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); + console.log(`ABI saved to ${abiPath}`); ---- + // Write the bytecode + const bytecodePath = join(outputDir, `${name}.polkavm`); + writeFileSync( + bytecodePath, + Buffer.from(contract.evm.bytecode.object, 'hex'), + ); + console.log(`Bytecode saved to ${bytecodePath}`); + } + } + } catch (error) { + console.error('Error compiling contracts:', error); + } +}; -Page Title: Deploy an NFT to Polkadot Hub with Hardhat +const solidityFilePath = join(__dirname, '../contracts/Storage.sol'); +const outputDir = join(__dirname, '../contracts'); -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-hardhat.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/hardhat/ -- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub with Hardhat, a comprehenive development environment with built-in deployment capabilities. +compileContract(solidityFilePath, outputDir); -# Deploy an NFT with Hardhat +``` -## Introduction +!!! note + The script above is tailored to the `Storage.sol` contract. It can be adjusted for other contracts by changing the file name or modifying the ABI and bytecode paths. -Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. +The ABI (Application Binary Interface) is a JSON representation of your contract's functions, events, and their parameters. It serves as the interface between your JavaScript code and the deployed smart contract, allowing your application to know how to format function calls and interpret returned data. -This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Hardhat](https://hardhat.org/docs/getting-started){target=\_blank}, a comprehensive development environment with built-in testing, debugging, and deployment capabilities. Hardhat uses standard Solidity compilation to generate EVM bytecode, making it fully compatible with Polkadot Hub's EVM environment. +Execute the script above by running: -## Prerequisites +```bash +node compile +``` -- Basic understanding of Solidity programming and NFT standards. -- Node.js v22.13.1 or later. -- A funded account with tokens for transaction fees. This example will deploy the contract to the Polkadot TestNet, so you'll [need some TestNet tokens](/smart-contracts/faucet/#get-test-tokens){target=\_blank} from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}. -- A wallet with a private key for signing transactions. +After executing the script, the Solidity contract will be compiled into the required PolkaVM bytecode format. The ABI and bytecode will be saved into files with `.json` and `.polkavm` extensions, respectively. You can now proceed with deploying the contract to Polkadot Hub, as outlined in the next section. -## Set Up Your Project +## Deploy the Compiled Contract -Take the following steps to get started: +To deploy your compiled contract to Polkadot Hub, you'll need a wallet with a private key to sign the deployment transaction. -1. Initialize your Hardhat project: +You can create a `deploy.js` script in the root of your project to achieve this. The deployment script can be divided into key components: - ```bash - mkdir hardhat-nft-deployment - cd hardhat-nft-deployment - npx hardhat --init - ``` +1. Set up the required imports and utilities: -2. Install OpenZeppelin contracts: + ```js title="scripts/deploy.js" + // Deploy an EVM-compatible smart contract using ethers.js + const { writeFileSync, existsSync, readFileSync } = require('fs'); + const { join } = require('path'); + const { ethers, JsonRpcProvider } = require('ethers'); - ```bash - npm install @openzeppelin/contracts + const codegenDir = join(__dirname); ``` -## Configure Hardhat +2. Create a provider to connect to Polkadot Hub: -Edit `hardhat.config.ts`: + ```js title="scripts/deploy.js" -```typescript title="hardhat.config.ts" -import type { HardhatUserConfig } from 'hardhat/config'; + // Creates an Ethereum provider with specified RPC URL and chain details + const createProvider = (rpcUrl, chainId, chainName) => { + const provider = new JsonRpcProvider(rpcUrl, { + chainId: chainId, + name: chainName, + }); + return provider; + }; + ``` + +3. Set up functions to read contract artifacts: -import hardhatToolboxViemPlugin from '@nomicfoundation/hardhat-toolbox-viem'; -import { configVariable } from 'hardhat/config'; + ```js title="scripts/deploy.js" + // Reads and parses the ABI file for a given contract + const getAbi = (contractName) => { + try { + return JSON.parse( + readFileSync(join(codegenDir, `${contractName}.json`), 'utf8'), + ); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; -const config: HardhatUserConfig = { - plugins: [hardhatToolboxViemPlugin], - solidity: { - profiles: { - default: { - version: '0.8.28', - }, - production: { - version: '0.8.28', - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - }, - }, - networks: { - hardhatMainnet: { - type: 'edr-simulated', - chainType: 'l1', - }, - hardhatOp: { - type: 'edr-simulated', - chainType: 'op', - }, - sepolia: { - type: 'http', - chainType: 'l1', - url: configVariable('SEPOLIA_RPC_URL'), - accounts: [configVariable('SEPOLIA_PRIVATE_KEY')], - }, - polkadotHubTestnet: { - type: 'http', - url: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - accounts: [configVariable('PRIVATE_KEY')], - }, - }, -}; - -export default config; -``` - -!!! tip - Learn how to use Hardhat's [Config Variables](https://hardhat.org/docs/learn-more/configuration-variables){target=\_blank} to handle your private keys in a secure way. - -## Create Your Contract - -Create `contracts/MyNFT.sol`: - -```solidity title="contracts/MyNFT.sol" -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract MyNFT is ERC721, Ownable { - uint256 private _nextTokenId; - - constructor(address initialOwner) - ERC721("MyToken", "MTK") - Ownable(initialOwner) - {} - - function safeMint(address to) public onlyOwner { - uint256 tokenId = _nextTokenId++; - _safeMint(to, tokenId); - } -} -``` - -## Compile - -```bash -npx hardhat compile -``` - -## Set Up Deployment - -Create a deployment module in `ignition/modules/MyNFT.ts`: - -```typescript title="ignition/modules/MyNFT.ts" -import { buildModule } from '@nomicfoundation/hardhat-ignition/modules'; - -export default buildModule('MyNFTModule', (m) => { - const initialOwner = m.getParameter('initialOwner', 'INSERT_OWNER_ADDRESS'); - const myNFT = m.contract('MyNFT', [initialOwner]); - return { myNFT }; -}); -``` - -Replace `INSERT_OWNER_ADDRESS` with your desired owner address. - -## Deploy - -Deploy to Polkadot Hub TestNet: - -```bash -npx hardhat ignition deploy ignition/modules/MyNFT.ts --network polkadotHubTestnet -``` - -## Where to Go Next - -
    - -- Guide __Verify Your Contract__ - - --- - - Now that you've deployed an NFT contract, learn how to verify it with Hardhat. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/hardhat/verify-a-contract/) - - -- Guide __Deploy an ERC-20__ - - --- - - Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Hardhat. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/hardhat/) - -
    - - ---- - -Page Title: Deploy an NFT to Polkadot Hub with Remix - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-remix.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/ -- Summary: Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Remix, a browser-based IDE for quick prototyping and learning. - -# Deploy an NFT with Remix - -## Introduction - -Non-Fungible Tokens (NFTs) represent unique digital assets commonly used for digital art, collectibles, gaming, and identity verification. - -This guide demonstrates how to deploy an [ERC-721](https://eips.ethereum.org/EIPS/eip-721){target=\_blank} NFT contract to [Polkadot Hub](/smart-contracts/overview/#smart-contract-development){target=\_blank}. You'll use [OpenZeppelin's battle-tested NFT implementation](https://github.com/OpenZeppelin/openzeppelin-contracts){target=\_blank} and [Remix](https://remix.ethereum.org/){target=\_blank}, a visual, browser-based environment perfect for rapid prototyping and learning. It requires no local installation and provides an intuitive interface for contract development. - -## Prerequisites - -- Basic understanding of Solidity programming and NFT standards. -- Test tokens for gas fees (available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}). See the [step-by-step instructions](/smart-contracts/faucet/#get-test-tokens){target=\_blank} -- A wallet with a private key for signing transactions. - -## Access Remix - -Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. - -The interface will load with a default workspace containing sample contracts. In this interface, you can access a file explorer, edit your code, interact with various plugins for development, and use a terminal. - -## Create Your Contract - -1. Create a new file `contracts/MyNFT.sol`. -2. Paste the following code: - - ```solidity title="contracts/MyNFT.sol" - // SPDX-License-Identifier: MIT - pragma solidity ^0.8.20; - - import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; - import "@openzeppelin/contracts/access/Ownable.sol"; - - contract MyNFT is ERC721, Ownable { - uint256 private _nextTokenId; - - constructor(address initialOwner) - ERC721("MyToken", "MTK") - Ownable(initialOwner) - {} - - function safeMint(address to) public onlyOwner { - uint256 tokenId = _nextTokenId++; - _safeMint(to, tokenId); - } - } + // Reads the compiled bytecode for a given contract + const getByteCode = (contractName) => { + try { + const bytecodePath = join( + codegenDir, + '../contracts', + `${contractName}.polkavm`, + ); + return `0x${readFileSync(bytecodePath).toString('hex')}`; + } catch (error) { + console.error( + `Could not find bytecode for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; ``` -![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-01.webp) - -## Compile - -1. Navigate to the **Solidity Compiler** tab (third icon in the left sidebar). -2. Click **Compile MyNFT.sol** or press `Ctrl+S`. - -![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-02.webp) - -Compilation errors and warnings appear in the terminal panel at the bottom of the screen. - -## Deploy - -1. Navigate to the **Deploy & Run Transactions** tab. -2. Click the **Environment** dropdown, select **Browser Extension**, and click on **Injected Provider - MetaMask**. - - ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-03.webp) - -3. In the deploy section, enter the initial owner address in the constructor parameter field. -4. Click **Deploy**. - - ![](/images/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/remix-04.webp) - -5. Approve the transaction in your MetaMask wallet. - -Your deployed contract will appear in the **Deployed Contracts** section, ready for interaction. - -## Where to Go Next +4. Create the main deployment function: -
    + ```js title="scripts/deploy.js" -- Guide __Verify Your Contract__ + const deployContract = async (contractName, mnemonic, providerConfig) => { + console.log(`Deploying ${contractName}...`); - --- + try { + // Step 1: Set up provider and wallet + const provider = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); + const walletMnemonic = ethers.Wallet.fromPhrase(mnemonic); + const wallet = walletMnemonic.connect(provider); - Now that you've deployed an NFT contract, learn how to verify it with Remix. + // Step 2: Create and deploy the contract + const factory = new ethers.ContractFactory( + getAbi(contractName), + getByteCode(contractName), + wallet, + ); + const contract = await factory.deploy(); + await contract.waitForDeployment(); - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/verify-a-contract/) + // Step 3: Save deployment information + const address = await contract.getAddress(); + console.log(`Contract ${contractName} deployed at: ${address}`); -- Guide __Deploy an ERC-20__ + const addressesFile = join(codegenDir, 'contract-address.json'); + const addresses = existsSync(addressesFile) + ? JSON.parse(readFileSync(addressesFile, 'utf8')) + : {}; + addresses[contractName] = address; + writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8'); + } catch (error) { + console.error(`Failed to deploy contract ${contractName}:`, error); + } + }; + ``` - --- - - Walk through deploying a fully-functional ERC-20 to the Polkadot Hub using Remix. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) - -
    - - ---- - -Page Title: Deploy Contracts to Polkadot Hub with Ethers.js - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-ethers-js.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/libraries/ethers-js/ -- Summary: Learn how to interact with Polkadot Hub using Ethers.js, from compiling and deploying Solidity contracts to interacting with deployed smart contracts. - -# Ethers.js - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -[Ethers.js](https://docs.ethers.org/v6/){target=\_blank} is a lightweight library that enables interaction with Ethereum Virtual Machine (EVM)-compatible blockchains through JavaScript. Ethers is widely used as a toolkit to establish connections and read and write blockchain data. This article demonstrates using Ethers.js to interact and deploy smart contracts to Polkadot Hub. - -This guide is intended for developers who are familiar with JavaScript and want to interact with Polkadot Hub using Ethers.js. - -## Prerequisites - -Before getting started, ensure you have the following installed: - -- **Node.js**: v22.13.1 or later, check the [Node.js installation guide](https://nodejs.org/en/download/current/){target=\_blank}. -- **npm**: v6.13.4 or later (comes bundled with Node.js). -- **Solidity**: This guide uses Solidity `^0.8.9` for smart contract development. - -## Project Structure - -This project organizes contracts, scripts, and compiled artifacts for easy development and deployment. - -```text title="Ethers.js Polkadot Hub" -ethers-project -├── contracts -│ ├── Storage.sol -├── scripts -│ ├── connectToProvider.js -│ ├── fetchLastBlock.js -│ ├── compile.js -│ ├── deploy.js -│ ├── checkStorage.js -├── abis -│ ├── Storage.json -├── artifacts -│ ├── Storage.polkavm -├── contract-address.json -├── node_modules/ -├── package.json -├── package-lock.json -└── README.md -``` - -## Set Up the Project - -To start working with Ethers.js, create a new folder and initialize your project by running the following commands in your terminal: - -```bash -mkdir ethers-project -cd ethers-project -npm init -y -``` - -## Install Dependencies - -Next, run the following command to install the Ethers.js library: - -```bash -npm install ethers -``` - -## Set Up the Ethers.js Provider - -A [`Provider`](https://docs.ethers.org/v6/api/providers/#Provider){target=\_blank} is an abstraction of a connection to the Ethereum network, allowing you to query blockchain data and send transactions. It serves as a bridge between your application and the blockchain. - -To interact with Polkadot Hub, you must set up an Ethers.js provider. This provider connects to a blockchain node, allowing you to query blockchain data and interact with smart contracts. In the root of your project, create a file named `connectToProvider.js` and add the following code: - -```js title="scripts/connectToProvider.js" -const { JsonRpcProvider } = require('ethers'); - -const createProvider = (rpcUrl, chainId, chainName) => { - const provider = new JsonRpcProvider(rpcUrl, { - chainId: chainId, - name: chainName, - }); - - return provider; -}; - -const PROVIDER_RPC = { - rpc: 'INSERT_RPC_URL', - chainId: 'INSERT_CHAIN_ID', - name: 'INSERT_CHAIN_NAME', -}; - -createProvider(PROVIDER_RPC.rpc, PROVIDER_RPC.chainId, PROVIDER_RPC.name); - -``` - -!!! note - Replace `INSERT_RPC_URL`, `INSERT_CHAIN_ID`, and `INSERT_CHAIN_NAME` with the appropriate values. For example, to connect to Polkadot Hub TestNet's Ethereum RPC instance, you can use the following parameters: - - ```js - const PROVIDER_RPC = { - rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - name: 'polkadot-hub-testnet' - }; - ``` - -To connect to the provider, execute: - -```bash -node connectToProvider -``` - -With the provider set up, you can start querying the blockchain. For instance, to fetch the latest block number: - -??? code "Fetch Last Block code" - - ```js title="scripts/fetchLastBlock.js" - const { JsonRpcProvider } = require('ethers'); - - const createProvider = (rpcUrl, chainId, chainName) => { - const provider = new JsonRpcProvider(rpcUrl, { - chainId: chainId, - name: chainName, - }); - - return provider; - }; - - const PROVIDER_RPC = { - rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - name: 'polkadot-hub-testnet', - }; - - const main = async () => { - try { - const provider = createProvider( - PROVIDER_RPC.rpc, - PROVIDER_RPC.chainId, - PROVIDER_RPC.name, - ); - const latestBlock = await provider.getBlockNumber(); - console.log(`Latest block: ${latestBlock}`); - } catch (error) { - console.error('Error connecting to Polkadot Hub TestNet: ' + error.message); - } - }; - - main(); - - ``` - -## Compile Contracts - -!!! note "Contracts Code Blob Size Disclaimer" - The maximum contract code blob size on Polkadot Hub networks is _100 kilobytes_, significantly larger than Ethereum’s EVM limit of 24 kilobytes. - - For detailed comparisons and migration guidelines, see the [EVM vs. PolkaVM](/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#current-memory-limits){target=\_blank} documentation page. - -The `revive` compiler transforms Solidity smart contracts into [PolkaVM](/smart-contracts/overview/#native-smart-contracts){target=\_blank} bytecode for deployment on Polkadot Hub. Revive's Ethereum RPC interface allows you to use familiar tools like Ethers.js and MetaMask to interact with contracts. - -### Install the Revive Library - -The [`@parity/resolc`](https://www.npmjs.com/package/@parity/resolc){target=\_blank} library will compile your Solidity code for deployment on Polkadot Hub. Run the following command in your terminal to install the library: - -```bash -npm install --save-dev @parity/resolc -``` - -This guide uses `@parity/resolc` version `0.2.0`. - -### Sample Storage Smart Contract - -This example demonstrates compiling a `Storage.sol` Solidity contract for deployment to Polkadot Hub. The contract's functionality stores a number and permits users to update it with a new value. - -```solidity title="contracts/Storage.sol" -//SPDX-License-Identifier: MIT - -// Solidity files have to start with this pragma. -// It will be used by the Solidity compiler to validate its version. -pragma solidity ^0.8.9; - -contract Storage { - // Public state variable to store a number - uint256 public storedNumber; - - /** - * Updates the stored number. - * - * The `public` modifier allows anyone to call this function. - * - * @param _newNumber - The new value to store. - */ - function setNumber(uint256 _newNumber) public { - storedNumber = _newNumber; - } -} -``` - -### Compile the Smart Contract - -To compile this contract, use the following script: - -```js title="scripts/compile.js" -const { compile } = require('@parity/resolc'); -const { readFileSync, writeFileSync } = require('fs'); -const { basename, join } = require('path'); - -const compileContract = async (solidityFilePath, outputDir) => { - try { - // Read the Solidity file - const source = readFileSync(solidityFilePath, 'utf8'); - - // Construct the input object for the compiler - const input = { - [basename(solidityFilePath)]: { content: source }, - }; - - console.log(`Compiling contract: ${basename(solidityFilePath)}...`); - - // Compile the contract - const out = await compile(input); - - for (const contracts of Object.values(out.contracts)) { - for (const [name, contract] of Object.entries(contracts)) { - console.log(`Compiled contract: ${name}`); - - // Write the ABI - const abiPath = join(outputDir, `${name}.json`); - writeFileSync(abiPath, JSON.stringify(contract.abi, null, 2)); - console.log(`ABI saved to ${abiPath}`); - - // Write the bytecode - const bytecodePath = join(outputDir, `${name}.polkavm`); - writeFileSync( - bytecodePath, - Buffer.from(contract.evm.bytecode.object, 'hex'), - ); - console.log(`Bytecode saved to ${bytecodePath}`); - } - } - } catch (error) { - console.error('Error compiling contracts:', error); - } -}; - -const solidityFilePath = join(__dirname, '../contracts/Storage.sol'); -const outputDir = join(__dirname, '../contracts'); - -compileContract(solidityFilePath, outputDir); - -``` - -!!! note - The script above is tailored to the `Storage.sol` contract. It can be adjusted for other contracts by changing the file name or modifying the ABI and bytecode paths. - -The ABI (Application Binary Interface) is a JSON representation of your contract's functions, events, and their parameters. It serves as the interface between your JavaScript code and the deployed smart contract, allowing your application to know how to format function calls and interpret returned data. - -Execute the script above by running: - -```bash -node compile -``` - -After executing the script, the Solidity contract will be compiled into the required PolkaVM bytecode format. The ABI and bytecode will be saved into files with `.json` and `.polkavm` extensions, respectively. You can now proceed with deploying the contract to Polkadot Hub, as outlined in the next section. - -## Deploy the Compiled Contract - -To deploy your compiled contract to Polkadot Hub, you'll need a wallet with a private key to sign the deployment transaction. - -You can create a `deploy.js` script in the root of your project to achieve this. The deployment script can be divided into key components: - -1. Set up the required imports and utilities: - - ```js title="scripts/deploy.js" - // Deploy an EVM-compatible smart contract using ethers.js - const { writeFileSync, existsSync, readFileSync } = require('fs'); - const { join } = require('path'); - const { ethers, JsonRpcProvider } = require('ethers'); - - const codegenDir = join(__dirname); - ``` - -2. Create a provider to connect to Polkadot Hub: - - ```js title="scripts/deploy.js" - - // Creates an Ethereum provider with specified RPC URL and chain details - const createProvider = (rpcUrl, chainId, chainName) => { - const provider = new JsonRpcProvider(rpcUrl, { - chainId: chainId, - name: chainName, - }); - return provider; - }; - ``` - -3. Set up functions to read contract artifacts: - - ```js title="scripts/deploy.js" - // Reads and parses the ABI file for a given contract - const getAbi = (contractName) => { - try { - return JSON.parse( - readFileSync(join(codegenDir, `${contractName}.json`), 'utf8'), - ); - } catch (error) { - console.error( - `Could not find ABI for contract ${contractName}:`, - error.message, - ); - throw error; - } - }; - - // Reads the compiled bytecode for a given contract - const getByteCode = (contractName) => { - try { - const bytecodePath = join( - codegenDir, - '../contracts', - `${contractName}.polkavm`, - ); - return `0x${readFileSync(bytecodePath).toString('hex')}`; - } catch (error) { - console.error( - `Could not find bytecode for contract ${contractName}:`, - error.message, - ); - throw error; - } - }; - ``` - -4. Create the main deployment function: - - ```js title="scripts/deploy.js" - - const deployContract = async (contractName, mnemonic, providerConfig) => { - console.log(`Deploying ${contractName}...`); - - try { - // Step 1: Set up provider and wallet - const provider = createProvider( - providerConfig.rpc, - providerConfig.chainId, - providerConfig.name, - ); - const walletMnemonic = ethers.Wallet.fromPhrase(mnemonic); - const wallet = walletMnemonic.connect(provider); - - // Step 2: Create and deploy the contract - const factory = new ethers.ContractFactory( - getAbi(contractName), - getByteCode(contractName), - wallet, - ); - const contract = await factory.deploy(); - await contract.waitForDeployment(); - - // Step 3: Save deployment information - const address = await contract.getAddress(); - console.log(`Contract ${contractName} deployed at: ${address}`); - - const addressesFile = join(codegenDir, 'contract-address.json'); - const addresses = existsSync(addressesFile) - ? JSON.parse(readFileSync(addressesFile, 'utf8')) - : {}; - addresses[contractName] = address; - writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8'); - } catch (error) { - console.error(`Failed to deploy contract ${contractName}:`, error); - } - }; - ``` - -5. Configure and execute the deployment: - - ```js title="scripts/deploy.js" - const providerConfig = { - rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - name: 'polkadot-hub-testnet', - }; - - const mnemonic = 'INSERT_MNEMONIC'; - - deployContract('Storage', mnemonic, providerConfig); - ``` - - !!! note - A mnemonic (seed phrase) is a series of words that can generate multiple private keys and their corresponding addresses. It's used here to derive the wallet that will sign and pay for the deployment transaction. **Always keep your mnemonic secure and never share it publicly**. - - Ensure to replace the `INSERT_MNEMONIC` placeholder with your actual mnemonic. - -??? code "View complete script" - - ```js title="scripts/deploy.js" - // Deploy an EVM-compatible smart contract using ethers.js - const { writeFileSync, existsSync, readFileSync } = require('fs'); - const { join } = require('path'); - const { ethers, JsonRpcProvider } = require('ethers'); - - const codegenDir = join(__dirname); - - // Creates an Ethereum provider with specified RPC URL and chain details - const createProvider = (rpcUrl, chainId, chainName) => { - const provider = new JsonRpcProvider(rpcUrl, { - chainId: chainId, - name: chainName, - }); - return provider; - }; - - // Reads and parses the ABI file for a given contract - const getAbi = (contractName) => { - try { - return JSON.parse( - readFileSync(join(codegenDir, `${contractName}.json`), 'utf8'), - ); - } catch (error) { - console.error( - `Could not find ABI for contract ${contractName}:`, - error.message, - ); - throw error; - } - }; - - // Reads the compiled bytecode for a given contract - const getByteCode = (contractName) => { - try { - const bytecodePath = join( - codegenDir, - '../contracts', - `${contractName}.polkavm`, - ); - return `0x${readFileSync(bytecodePath).toString('hex')}`; - } catch (error) { - console.error( - `Could not find bytecode for contract ${contractName}:`, - error.message, - ); - throw error; - } - }; - - const deployContract = async (contractName, mnemonic, providerConfig) => { - console.log(`Deploying ${contractName}...`); - - try { - // Step 1: Set up provider and wallet - const provider = createProvider( - providerConfig.rpc, - providerConfig.chainId, - providerConfig.name, - ); - const walletMnemonic = ethers.Wallet.fromPhrase(mnemonic); - const wallet = walletMnemonic.connect(provider); - - // Step 2: Create and deploy the contract - const factory = new ethers.ContractFactory( - getAbi(contractName), - getByteCode(contractName), - wallet, - ); - const contract = await factory.deploy(); - await contract.waitForDeployment(); - - // Step 3: Save deployment information - const address = await contract.getAddress(); - console.log(`Contract ${contractName} deployed at: ${address}`); - - const addressesFile = join(codegenDir, 'contract-address.json'); - const addresses = existsSync(addressesFile) - ? JSON.parse(readFileSync(addressesFile, 'utf8')) - : {}; - addresses[contractName] = address; - writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8'); - } catch (error) { - console.error(`Failed to deploy contract ${contractName}:`, error); - } - }; - - const providerConfig = { - rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, - name: 'polkadot-hub-testnet', - }; - - const mnemonic = 'INSERT_MNEMONIC'; - - deployContract('Storage', mnemonic, providerConfig); - - ``` - -To run the script, execute the following command: - -```bash -node deploy -``` - -After running this script, your contract will be deployed to Polkadot Hub, and its address will be saved in `contract-address.json` within your project directory. You can use this address for future contract interactions. - -## Interact with the Contract - -Once the contract is deployed, you can interact with it by calling its functions. For example, to set a number, read it and then modify that number by its double, you can create a file named `checkStorage.js` in the root of your project and add the following code: - -```js title="scripts/checkStorage.js" -const { ethers } = require('ethers'); -const { readFileSync } = require('fs'); -const { join } = require('path'); - -const createProvider = (providerConfig) => { - return new ethers.JsonRpcProvider(providerConfig.rpc, { - chainId: providerConfig.chainId, - name: providerConfig.name, - }); -}; - -const createWallet = (mnemonic, provider) => { - return ethers.Wallet.fromPhrase(mnemonic).connect(provider); -}; - -const loadContractAbi = (contractName, directory = __dirname) => { - const contractPath = join(directory, `${contractName}.json`); - const contractJson = JSON.parse(readFileSync(contractPath, 'utf8')); - return contractJson.abi || contractJson; // Depending on JSON structure -}; - -const createContract = (contractAddress, abi, wallet) => { - return new ethers.Contract(contractAddress, abi, wallet); -}; - -const interactWithStorageContract = async ( - contractName, - contractAddress, - mnemonic, - providerConfig, - numberToSet, -) => { - try { - console.log(`Setting new number in Storage contract: ${numberToSet}`); - - // Create provider and wallet - const provider = createProvider(providerConfig); - const wallet = createWallet(mnemonic, provider); - - // Load the contract ABI and create the contract instance - const abi = loadContractAbi(contractName); - const contract = createContract(contractAddress, abi, wallet); - - // Send a transaction to set the stored number - const tx1 = await contract.setNumber(numberToSet); - await tx1.wait(); // Wait for the transaction to be mined - console.log(`Number successfully set to ${numberToSet}`); - - // Retrieve the updated number - const storedNumber = await contract.storedNumber(); - console.log(`Retrieved stored number:`, storedNumber.toString()); - - // Send a transaction to set the stored number - const tx2 = await contract.setNumber(numberToSet * 2); - await tx2.wait(); // Wait for the transaction to be mined - console.log(`Number successfully set to ${numberToSet * 2}`); - - // Retrieve the updated number - const updatedNumber = await contract.storedNumber(); - console.log(`Retrieved stored number:`, updatedNumber.toString()); - } catch (error) { - console.error('Error interacting with Storage contract:', error.message); - } -}; - -const providerConfig = { - name: 'asset-hub-smart-contracts', - rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', - chainId: 420420422, -}; - -const mnemonic = 'INSERT_MNEMONIC'; -const contractName = 'Storage'; -const contractAddress = 'INSERT_CONTRACT_ADDRESS'; -const newNumber = 42; - -interactWithStorageContract( - contractName, - contractAddress, - mnemonic, - providerConfig, - newNumber, -); - -``` - -Ensure you replace the `INSERT_MNEMONIC`, `INSERT_CONTRACT_ADDRESS`, and `INSERT_ADDRESS_TO_CHECK` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. - -To interact with the contract, run: - -```bash -node checkStorage -``` - -## Where to Go Next - -Now that you have the foundational knowledge to use Ethers.js with Polkadot Hub, you can: - -- **Dive into Ethers.js utilities**: Discover additional Ethers.js features, such as wallet management, signing messages, etc. -- **Implement batch transactions**: Use Ethers.js to execute batch transactions for efficient multi-step contract interactions. -- **Build scalable applications**: Combine Ethers.js with frameworks like [`Next.js`](https://nextjs.org/docs){target=\_blank} or [`Node.js`](https://nodejs.org/en){target=\_blank} to create full-stack decentralized applications (dApps). - - ---- - -Page Title: Deploy Contracts Using Remix IDE - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/ -- Summary: Learn how to deploy smart contracts to the Polkadot Hub network and interact with them using the Remix IDE and wallet providers, covering deployment and state. - -# Deploy Smart Contracts Using Remix IDE - -## Overview - -After compiling your smart contract in Remix IDE, the next step is to deploy it to the Polkadot Hub network. This guide will walk you through the deployment process using a wallet provider and show you how to interact with your deployed contracts directly from the Remix interface. - -## Prerequisites - -Before deploying your contract, ensure you have: - -- Completed the [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} and have a compiled contract ready. -- A compatible wallet extension installed (e.g., [MetaMask](https://metamask.io/){target=\_blank} or [Talisman](https://www.talisman.xyz/){target=\_blank}). -- Your wallet connected to the Polkadot Hub network. Check the [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} guide for more information. -- Test tokens in your wallet to cover deployment and transaction fees (available from the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank}). - -## Deploy Contracts - -The steps to use Remix IDE to deploy a contract to Polkadot Hub are as follows: - -1. Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. -2. Locate the **Deploy & Run Transactions** tab. -3. Select the **Environment** dropdown. -4. Select **Browser Extension**. -5. Select the **Injected Provider - MetaMask** option. -6. Click the **Deploy** button and then click **Confirm** in the wallet popup. - -Once your contract is deployed successfully, you will see the deployment confirmation in the Remix terminal. - -![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-1.gif) - -## Interact with Contracts - -Deployed contracts appear in the **Deployed/Unpinned Contracts** section. Follow these steps to interact with the deployed contract: - -1. Expand the contract to view available methods. - - !!! tip - Pin your frequently used contracts to the **Pinned Contracts** section for easy access. - -2. Select any of the exposed methods to interact with the contract. - - You can use these methods to interact with your deployed contract by reading or writing to its state. Remix IDE uses a color-coding scheme for method buttons to help differentiate between types of available methods as follows: - - - **Blue buttons**: indicate `view` or `pure` functions which read state only. Interactions do not create a new transaction and do not incur gas fees. - - **Orange buttons**: label `non-payable` functions which change contract state but don't accept any value (ETH or other tokens) being sent with the transaction. - - **Red buttons**: designate `payable` functions which create a transaction and can accept a value (ETH or other tokens) to send with the transaction. - -If you deployed the `Counter.sol` contract from [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank}, you can try interacting with the exposed methods as follows: - -1. Select the **GetCount** button to read the current count value. - -2. Select the **Increment** button to increment the count value. - -3. Submit the transaction and click the **Confirm** button in the wallet pop-up. - -Once the transaction is confirmed, you will see the updated count value in the Remix terminal. - -![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-2.gif) - -## Where to Go Next - -You've successfully deployed and interacted with your smart contract on Polkadot Hub using Remix IDE. Continue enhancing your development workflow with these resources: - -
    - - - -- Guide __Troubleshooting__ - - --- - - Find solutions to common issues when working with Remix IDE. - - [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/troubleshooting-faq/) - -
    - - ---- - -Page Title: Deploying Uniswap V2 on Polkadot - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/ -- Summary: Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. - -# Deploy Uniswap V2 - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Decentralized exchanges (DEXs) are a cornerstone of the DeFi ecosystem, allowing for permissionless token swaps without intermediaries. [Uniswap V2](https://docs.uniswap.org/contracts/v2/overview){target=\_blank}, with its Automated Market Maker (AMM) model, revolutionized DEXs by enabling liquidity provision for any ERC-20 token pair. - -This tutorial will guide you through how Uniswap V2 works so you can take advantage of it in your projects deployed to Polkadot Hub. By understanding these contracts, you'll gain hands-on experience with one of the most influential DeFi protocols and understand how it functions across blockchain ecosystems. - -## Prerequisites - -Before starting, make sure you have: - -- Node.js (v16.0.0 or later) and npm installed. -- Basic understanding of Solidity and JavaScript. -- Familiarity with [`hardhat-polkadot`](/smart-contracts/dev-environments/hardhat/get-started/){target=\_blank} development environment. -- Some PAS test tokens to cover transaction fees (obtained from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}). -- Basic understanding of how AMMs and liquidity pools work. - -## Set Up the Project - -Let's start by cloning the Uniswap V2 project: - -1. Clone the Uniswap V2 repository: - - ``` - git clone https://github.com/polkadot-developers/polkavm-hardhat-examples.git -b v0.0.6 - cd polkavm-hardhat-examples/uniswap-v2-polkadot/ - ``` - -2. Install the required dependencies: - - ```bash - npm install - ``` - -3. Update the `hardhat.config.js` file so the paths for the Substrate node and the ETH-RPC adapter match with the paths on your machine. For more info, check the [Testing your Contract](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} section in the Hardhat guide. - - ```js title="hardhat.config.js" - hardhat: { - polkavm: true, - nodeConfig: { - nodeBinaryPath: '../bin/substrate-node', - rpcPort: 8000, - dev: true, - }, - adapterConfig: { - adapterBinaryPath: '../bin/eth-rpc', - dev: true, - }, - }, - ``` - -4. Create a `.env` file in your project root to store your private keys (you can use as an example the `env.example` file): - - ```text title=".env" - LOCAL_PRIV_KEY="INSERT_LOCAL_PRIVATE_KEY" - AH_PRIV_KEY="INSERT_AH_PRIVATE_KEY" - ``` - - Ensure to replace `"INSERT_LOCAL_PRIVATE_KEY"` with a private key available in the local environment (you can get them from this [file](https://github.com/paritytech/hardhat-polkadot/blob/main/packages/hardhat-polkadot-node/src/constants.ts#L22){target=\_blank}). And `"INSERT_AH_PRIVATE_KEY"` with the account's private key you want to use to deploy the contracts. You can get this by exporting the private key from your wallet (e.g., MetaMask). - - !!!warning - Keep your private key safe, and never share it with anyone. If it is compromised, your funds can be stolen. - -5. Compile the contracts: - - ```bash - npx hardhat compile - ``` - -If the compilation is successful, you should see the following output: - -
    - npx hardhat compile - Compiling 12 Solidity files - Successfully compiled 12 Solidity files -
    - -After running the above command, you should see the compiled contracts in the `artifacts-pvm` directory. This directory contains the ABI and bytecode of your contracts. - -## Understanding Uniswap V2 Architecture - -Before interacting with the contracts, it's essential to understand the core architecture that powers Uniswap V2. This model forms the basis of nearly every modern DEX implementation and operates under automated market making, token pair liquidity pools, and deterministic pricing principles. - -At the heart of Uniswap V2 lies a simple but powerful system composed of two major smart contracts: - -- **Factory contract**: The factory acts as a registry and creator of new trading pairs. When two ERC-20 tokens are to be traded, the Factory contract is responsible for generating a new Pair contract that will manage that specific token pair’s liquidity pool. It keeps track of all deployed pairs and ensures uniqueness—no duplicate pools can exist for the same token combination. -- **Pair contract**: Each pair contract is a decentralized liquidity pool that holds reserves of two ERC-20 tokens. These contracts implement the core logic of the AMM, maintaining a constant product invariant (x \* y = k) to facilitate swaps and price determination. Users can contribute tokens to these pools in return for LP (liquidity provider) tokens, which represent their proportional share of the reserves. - -This minimal architecture enables Uniswap to be highly modular, trustless, and extensible. By distributing responsibilities across these components, developers, and users can engage with the protocol in a composable and predictable manner, making it an ideal foundation for DEX functionality across ecosystems, including Polkadot Hub. - -The project scaffolding is as follows: - -```bash -uniswap-V2-polkadot -├── bin/ -├── contracts/ -│ ├── interfaces/ -│ │ ├── IERC20.sol -│ │ ├── IUniswapV2Callee.sol -│ │ ├── IUniswapV2ERC20.sol -│ │ ├── IUniswapV2Factory.sol -│ │ └── IUniswapV2Pair.sol -│ ├── libraries/ -│ │ ├── Math.sol -│ │ ├── SafeMath.sol -│ │ └── UQ112x112.sol -│ ├── test/ -│ │ └── ERC20.sol -│ ├── UniswapV2ERC20.sol -│ ├── UniswapV2Factory.sol -│ └── UniswapV2Pair.sol -├── ignition/ -├── scripts/ -│ └── deploy.js -├── node_modules/ -├── test/ -│ ├── shared/ -│ │ ├── fixtures.js -│ │ └── utilities.js -│ ├── UniswapV2ERC20.js -│ ├── UniswapV2Factory.js -│ └── UniswapV2Pair.js -├── .env.example -├── .gitignore -├── hardhat.config.js -├── package.json -└── README.md -``` - -## Test the Contracts - -You can run the provided test suite to ensure the contracts are working as expected. The tests cover various scenarios, including creating pairs, adding liquidity, and executing swaps. - -To test it locally, you can run the following commands: - -1. Spawn a local node for testing: - - ```bash - npx hardhat node - ``` - - This command will spawn a local Substrate node along with the ETH-RPC adapter. The node will be available at `ws://127.0.0.1:8000` and the ETH-RPC adapter at `http://localhost:8545`. - -2. In a new terminal, run the tests: - - ```bash - npx hardhat test --network localNode - ``` - -The result should look like this: - -
    - npx hardhat test --network localNode - Compiling 12 Solidity files - Successfully compiled 12 Solidity files - - UniswapV2ERC20 - ✔ name, symbol, decimals, totalSupply, balanceOf, DOMAIN_SEPARATOR, PERMIT_TYPEHASH (44ms) - ✔ approve (5128ms) - ✔ transfer (5133ms) - ✔ transfer:fail - ✔ transferFrom (6270ms) - ✔ transferFrom:max (6306ms) - - UniswapV2Factory - ✔ feeTo, feeToSetter, allPairsLength - ✔ createPair (176ms) - ✔ createPair:reverse (1224ms) - ✔ setFeeTo (1138ms) - ✔ setFeeToSetter (1125ms) - - UniswapV2Pair - ✔ mint (11425ms) - ✔ getInputPrice:0 (12590ms) - ✔ getInputPrice:1 (17600ms) - ✔ getInputPrice:2 (17618ms) - ✔ getInputPrice:3 (17704ms) - ✔ getInputPrice:4 (17649ms) - ✔ getInputPrice:5 (17594ms) - ✔ getInputPrice:6 (13643ms) - ✔ optimistic:0 (17647ms) - ✔ optimistic:1 (17946ms) - ✔ optimistic:2 (17657ms) - ✔ optimistic:3 (21625ms) - ✔ swap:token0 (12665ms) - ✔ swap:token1 (17631ms) - ✔ burn (17690ms) - ✔ feeTo:off (23900ms) - ✔ feeTo:on (24991ms) - - 28 passing (12m) -
    - -## Deploy the Contracts - -After successfully testing the contracts, you can deploy them to the local node or Polkadot Hub. The deployment script is located in the `scripts` directory and is named `deploy.js`. This script deploys the `Factory` and `Pair` contracts to the network. - -To deploy the contracts, run the following command: - -```bash -npx hardhat run scripts/deploy.js --network localNode -``` - -This command deploys the contracts to your local blockchain for development and testing. If you want to deploy to Polkadot Hub, you can use the following command: - -```bash -npx hardhat run scripts/deploy.js --network passetHub -``` - -The command above deploys to the actual Polkadot TestNet. It requires PAS test tokens, persists on the network, and operates under real network conditions. - -The deployment script will output the addresses of the deployed contracts. Save these addresses, as you will need them to interact with the contracts. For example, the output should look like this: - -
    - npx hardhat run scripts/deploy.js --network localNode - Successfully compiled 12 Solidity files - Deploying contracts using 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac - Deploying UniswapV2ERC20... - ETH deployed to : 0x7acc1aC65892CF3547b1b0590066FB93199b430D - Deploying UniswapV2Factory... - Factory deployed to : 0x85b108660f47caDfAB9e0503104C08C1c96e0DA9 - Deploying UniswapV2Pair with JsonRpcProvider workaround... - Pair deployed to : 0xF0e46847c8bFD122C4b5EEE1D4494FF7C5FC5104 -
    - -## Conclusion - -This tutorial guided you through deploying Uniswap V2 contracts to Polkadot Hub. This implementation brings the powerful AMM architecture to the Polkadot ecosystem, laying the foundation for the decentralized trading of ERC-20 token pairs. - -By following this guide, you've gained practical experience with: - -- Setting up a Hardhat project for deploying to Polkadot Hub. -- Understanding the Uniswap V2 architecture. -- Testing Uniswap V2 contracts in a local environment. -- Deploying contracts to both local and testnet environments. - -To build on this foundation, you could extend this project by implementing functionality to create liquidity pools, execute token swaps, and build a user interface for interacting with your deployment. - -This knowledge can be leveraged to build more complex DeFi applications or to integrate Uniswap V2 functionality into your existing projects on Polkadot. - - ---- - -Page Title: Dual Virtual Machine Stack - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/ -- Summary: Compare Polkadot’s dual smart contract VMs—REVM for EVM compatibility and PolkaVM for RISC-V performance, flexibility, and efficiency. - -# Dual Virtual Machine Stack - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot's smart contract platform supports two distinct virtual machine (VM) architectures, providing developers with flexibility in selecting the optimal execution backend for their specific needs. This approach strikes a balance between immediate Ethereum compatibility and long-term innovation, enabling developers to deploy either unmodified (Ethereum Virtual Machine) EVM contracts using Rust Ethereum Virtual Machine (REVM) or optimize for higher performance using PolkaVM (PVM). - -Both VM options share common infrastructure, including RPC interfaces, tooling support, and precompiles. The following sections compare architectures and guide you in selecting the best VM for your project's needs. - -## Migrate from EVM - -The [REVM backend](https://github.com/bluealloy/revm){target=\_blank} integrates a complete Rust implementation of the EVM, enabling Solidity contracts to run unchanged on Polkadot's smart contract platform. - -REVM allows developers to use their existing Ethereum tooling and infrastructure to build on Polkadot. Choose REVM to: - -- Migrate existing Ethereum contracts without modifications. -- Retain exact EVM behavior for audit tools. -- Use developer tools that rely upon inspecting EVM bytecode. -- Prioritize rapid deployment over optimization. -- Work with established Ethereum infrastructure and tooling to build on Polkadot. - -REVM enables Ethereum developers to seamlessly migrate to Polkadot, achieving performance and fee improvements without modifying their existing contracts or developer tooling stack. - -## Upgrade to PolkaVM - -[**PolkaVM**](https://github.com/paritytech/polkavm){target=\_blank} is a custom virtual machine optimized for performance with [RISC-V-based](https://en.wikipedia.org/wiki/RISC-V){target=\_blank} architecture, supporting Solidity and additional high-performance languages. It serves as the core execution environment, integrated directly within the runtime. Choose the PolkaVM for: - -- An efficient interpreter for immediate code execution. -- A planned [Just In Time (JIT)](https://en.wikipedia.org/wiki/Just-in-time_compilation){target=\_blank} compiler for optimized performance. -- Dual-mode execution capability, allowing selection of the most appropriate backend for specific workloads. -- Optimized performance for short-running contract calls through the interpreter. - -The interpreter remains particularly beneficial for contracts with minimal code execution, as it enables immediate code execution through lazy interpretation. - -## Architecture - -The following key components of PolkaVM work together to enable Ethereum compatibility on Polkadot-based chains. - -### Revive Pallet - -[**`pallet_revive`**](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/index.html){target=\_blank} is a runtime module that executes smart contracts by adding extrinsics, runtime APIs, and logic to convert Ethereum-style transactions into formats compatible with Polkadot SDK-based blockchains. It processes Ethereum-style transactions through the following workflow: - -```mermaid -sequenceDiagram - participant User as User/dApp - participant Proxy as Ethereum JSON RPC Proxy - participant Chain as Blockchain Node - participant Pallet as pallet_revive - - User->>Proxy: Submit Ethereum Transaction - Proxy->>Chain: Repackage as Polkadot Compatible Transaction - Chain->>Pallet: Process Transaction - Pallet->>Pallet: Decode Ethereum Transaction - Pallet->>Pallet: Execute Contract via PolkaVM - Pallet->>Chain: Return Results - Chain->>Proxy: Forward Results - Proxy->>User: Return Ethereum-compatible Response -``` - -This proxy-based approach eliminates the need for node binary modifications, maintaining compatibility across different client implementations. Preserving the original Ethereum transaction payload simplifies the adaptation of existing tools, which can continue processing familiar transaction formats. - -### PolkaVM Design Fundamentals - -PolkaVM differs from the EVM in two key ways that make it faster, more hardware-efficient, and easier to extend: - -- **Register-based design**: Instead of a stack machine, PolkaVM uses a RISC-V–style register model. This design: - - - Uses a fixed set of registers to pass arguments, not an infinite stack. - - Maps cleanly to real hardware like x86-64. - - Simplifies compilation and boosts runtime efficiency. - - Enables tighter control over register allocation and performance tuning. - -- **64-bit word size**: PolkaVM runs on a native 64-bit word size, aligning directly with modern CPUs. This design: - - - Executes arithmetic operations with direct hardware support. - - Maintains compatibility with Solidity’s 256-bit types via YUL translation. - - Accelerates computation-heavy workloads through native word alignment. - - Integrates easily with low-level, performance-focused components. - -## Where To Go Next - -
    - -- Learn __Contract Deployment__ - - --- - - Learn how REVM and PVM compare for compiling and deploying smart contracts. - - [:octicons-arrow-right-24: Reference](/smart-contracts/for-eth-devs/contract-deployment/) - -
    - - ---- - -Page Title: E2E Testing with Moonwall - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/moonwall/ -- Summary: Enhance blockchain end-to-end testing with Moonwall's standardized environment setup, comprehensive configuration management, and simple network interactions. - -# E2E Testing with Moonwall - -## Introduction - -Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations. - -Moonwall consolidates this complexity by providing the following: - -- A centralized configuration management system that explicitly defines all network parameters. -- A standardized approach to environment setup across different Substrate-based chains. -- Built-in utilities for common testing scenarios and network interactions. - -Developers can focus on writing meaningful tests rather than managing infrastructure complexities or searching through documentation for configuration options. - -## Prerequisites - -Before you begin, ensure you have the following installed: - -- [Node.js](https://nodejs.org/en/){target=\_blank} (version 20.10 or higher). -- A package manager such as [npm](https://www.npmjs.com/){target=\_blank}, [yarn](https://yarnpkg.com/){target=\_blank}, or [pnpm](https://pnpm.io/){target=\_blank}. - -## Install Moonwall - -Moonwall can be installed globally for system-wide access or locally within specific projects. This section covers both installation methods. - -!!! tip - This documentation corresponds to Moonwall version `5.15.0`. To avoid compatibility issues with the documented features, ensure you're using the matching version. - -### Global Installation - -Global installation provides system-wide access to the Moonwall CLI, making it ideal for developers working across multiple blockchain projects. Install it by running one of the following commands: - -=== "npm" - - ```bash - npm install -g @moonwall/cli@5.15.0 - ``` - -=== "pnpm" - - ```bash - pnpm -g install @moonwall/cli@5.15.0 - ``` - -=== "yarn" - - ```bash - yarn global add @moonwall/cli@5.15.0 - ``` - -Now, you can run the `moonwall` command from your terminal. - -### Local Installation - -Local installation is recommended for better dependency management and version control within a specific project. First, initialize your project: - -```bash -mkdir my-moonwall-project -cd my-moonwall-project -npm init -y -``` - -Then, install it as a local dependency: - -=== "npm" - - ```bash - npm install @moonwall/cli@5.15.0 - ``` - -=== "pnpm" - - ```bash - pnpm install @moonwall/cli@5.15.0 - ``` - -=== "yarn" - - ```bash - yarn add @moonwall/cli@5.15.0 - ``` - -## Initialize Moonwall - -The `moonwall init` command launches an interactive wizard to create your configuration file: - -```bash -moonwall init -``` - -During setup, you will see prompts for the following parameters: - -- **`label`**: Identifies your test configuration. -- **`global timeout`**: Maximum time (ms) for test execution. -- **`environment name`**: Name for your testing environment. -- **`network foundation`**: Type of blockchain environment to use. -- **`tests directory`**: Location of your test files. - -Select `Enter` to accept defaults or input custom values. You should see something like this: - -
    - moonwall init - ✔ Provide a label for the config file moonwall_config - ✔ Provide a global timeout value 30000 - ✔ Provide a name for this environment default_env - ✔ What type of network foundation is this? dev - ✔ Provide the path for where tests for this environment are kept tests/ - ? Would you like to generate this config? (no to restart from beginning) (Y/n) -
    - -The wizard generates a `moonwall.config` file: - -```json -{ - "label": "moonwall_config", - "defaultTestTimeout": 30000, - "environments": [ - { - "name": "default_env", - "testFileDir": ["tests/"], - "foundation": { - "type": "dev" - } - } - ] -} - -``` - -The default configuration requires specific details about your blockchain node and test requirements: - -- The `foundation` object defines how your test blockchain node will be launched and managed. The dev foundation, which runs a local node binary, is used for local development. - - For more information about available options, check the [Foundations](https://moonsong-labs.github.io/moonwall/guide/intro/foundations.html){target=\_blank} section. - -- The `connections` array specifies how your tests will interact with the blockchain node. This typically includes provider configuration and endpoint details. - - A provider is a tool that allows you or your application to connect to a blockchain network and simplifies the low-level details of the process. A provider handles submitting transactions, reading state, and more. For more information on available providers, check the [Providers supported](https://moonsong-labs.github.io/moonwall/guide/intro/providers.html#providers-supported){target=\_blank} page in the Moonwall documentation. - -Here's a complete configuration example for testing a local node using Polkadot.js as a provider: - -```json -{ - "label": "moonwall_config", - "defaultTestTimeout": 30000, - "environments": [ - { - "name": "default_env", - "testFileDir": ["tests/"], - "foundation": { - "launchSpec": [ - { - "binPath": "./node-template", - "newRpcBehaviour": true, - "ports": { "rpcPort": 9944 } - } - ], - "type": "dev" - }, - "connections": [ - { - "name": "myconnection", - "type": "polkadotJs", - "endpoints": ["ws://127.0.0.1:9944"] - } - ] - } - ] -} - -``` - -## Writing Tests - -Moonwall uses the [`describeSuite`](https://github.com/Moonsong-Labs/moonwall/blob/7568048c52e9f7844f38fb4796ae9e1b9205fdaa/packages/cli/src/lib/runnerContext.ts#L65){target=\_blank} function to define test suites, like using [Mocha](https://mochajs.org/){target=\_blank}. Each test suite requires the following: - -- **`id`**: Unique identifier for the suite. -- **`title`**: Descriptive name for the suite. -- **`foundationMethods`**: Specifies the testing environment (e.g., `dev` for local node testing). -- **`testCases`**: A callback function that houses the individual test cases of this suite. - -The following example shows how to test a balance transfer between two accounts: - -```ts -import '@polkadot/api-augment'; -import { describeSuite, expect } from '@moonwall/cli'; -import { Keyring } from '@polkadot/api'; - -describeSuite({ - id: 'D1', - title: 'Demo suite', - foundationMethods: 'dev', - testCases: ({ it, context, log }) => { - it({ - id: 'T1', - title: 'Test Case', - test: async () => { - // Set up polkadot.js API and testing accounts - let api = context.polkadotJs(); - let alice = new Keyring({ type: 'sr25519' }).addFromUri('//Alice'); - let charlie = new Keyring({ type: 'sr25519' }).addFromUri('//Charlie'); - - // Query Charlie's account balance before transfer - const balanceBefore = (await api.query.system.account(charlie.address)) - .data.free; - - // Before transfer, Charlie's account balance should be 0 - expect(balanceBefore.toString()).toEqual('0'); - log('Balance before: ' + balanceBefore.toString()); - - // Transfer from Alice to Charlie - const amount = 1000000000000000; - await api.tx.balances - .transferAllowDeath(charlie.address, amount) - .signAndSend(alice); - - // Wait for the transaction to be included in a block. - // This is necessary because the balance is not updated immediately. - // Block time is 6 seconds. - await new Promise((resolve) => setTimeout(resolve, 6000)); - - // Query Charlie's account balance after transfer - const balanceAfter = (await api.query.system.account(charlie.address)) - .data.free; - - // After transfer, Charlie's account balance should be 1000000000000000 - expect(balanceAfter.toString()).toEqual(amount.toString()); - log('Balance after: ' + balanceAfter.toString()); - }, - }); - }, -}); - -``` - -This test demonstrates several key concepts: - -- Initializing the Polkadot.js API through Moonwall's context and setting up test accounts. -- Querying on-chain state. -- Executing transactions. -- Waiting for block inclusion. -- Verifying results using assertions. - -## Running the Tests - -Execute your tests using the `test` Moonwall CLI command. For the default environment setup run: - -```bash -moonwall test default_env -c moonwall.config -``` - -The test runner will output detailed results showing: - -- Test suite execution status. -- Individual test case results. -- Execution time. -- Detailed logs and error messages (if any). - -Example output: -
    - moonwall test default_env -c moonwall.config - stdout | tests/test1.ts > 🗃️ D1 Demo suite > 📁 D1T1 Test Case - 2025-01-21T19:27:55.624Z test:default_env Balance before: 0 - - stdout | tests/test1.ts > 🗃️ D1 Demo suite > 📁 D1T1 Test Case - 2025-01-21T19:28:01.637Z test:default_env Balance after: 1000000000000000 - - ✓ default_env tests/test1.ts (1 test) 6443ms - ✓ 🗃️ D1 Demo suite > 📁 D1T1 Test Case 6028ms - - Test Files 1 passed (1) - Tests 1 passed (1) - Start at 16:27:53 - Duration 7.95s (transform 72ms, setup 0ms, collect 1.31s, tests 6.44s, environment 0ms, prepare 46ms) - - ✅ All tests passed -
    - -## Where to Go Next - -For a comprehensive guide to Moonwall's full capabilities, available configurations, and advanced usage, see the official [Moonwall](https://moonsong-labs.github.io/moonwall/){target=\_blank} documentation. - - ---- - -Page Title: Get Started - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md -- Canonical (HTML): https://docs.polkadot.com/parachains/testing/fork-a-parachain/ -- Summary: Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. - -# Get Started - -## Introduction - -[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network. - -This guide walks you through installing Chopsticks and provides information on configuring a local blockchain fork. By streamlining testing and experimentation, Chopsticks empowers developers to innovate and accelerate their blockchain projects within the Polkadot ecosystem. - -For additional support and information, please reach out through [GitHub Issues](https://github.com/AcalaNetwork/chopsticks/issues){target=_blank}. - -!!! warning - Chopsticks uses [Smoldot](https://github.com/smol-dot/smoldot){target=_blank} light client, which only supports the native Polkadot SDK API. Consequently, a Chopsticks-based fork doesn't support Ethereum JSON-RPC calls, meaning you cannot use it to fork your chain and connect Metamask. - -## Prerequisites - -Before you begin, ensure you have the following installed: - -- [Node.js](https://nodejs.org/en/){target=\_blank}. -- A package manager such as [npm](https://www.npmjs.com/){target=\_blank}, which should be installed with Node.js by default, or [Yarn](https://yarnpkg.com/){target=\_blank}. - -## Install Chopsticks - -You can install Chopsticks globally or locally in your project. Choose the option that best fits your development workflow. This documentation explains the features of Chopsticks version `1.2.2`. Make sure you're using the correct version to match these instructions. - -### Global Installation - -To install Chopsticks globally, allowing you to use it across multiple projects, run: - -```bash -npm i -g @acala-network/chopsticks@1.2.2 -``` - -Now, you should be able to run the `chopsticks` command from your terminal. - -### Local Installation - -To use Chopsticks in a specific project, first create a new directory and initialize a Node.js project: - -```bash -mkdir my-chopsticks-project -cd my-chopsticks-project -npm init -y -``` - -Then, install Chopsticks as a local dependency: - -```bash -npm i @acala-network/chopsticks@1.2.2 -``` - -Finally, you can run Chopsticks using the `npx` command. To see all available options and commands, run it with the `--help` flag: - -```bash -npx @acala-network/chopsticks --help -``` - -## Configure Chopsticks - -To run Chopsticks, you need to configure some parameters. This can be set either through using a configuration file or the command line interface (CLI). The parameters that can be configured are as follows: - -- **`genesis`**: The link to a parachain's raw genesis file to build the fork from, instead of an endpoint. -- **`timestamp`**: Timestamp of the block to fork from. -- **`endpoint`**: The endpoint of the parachain to fork. -- **`block`**: Use to specify at which block hash or number to replay the fork. -- **`wasm-override`**: Path of the Wasm to use as the parachain runtime, instead of an endpoint's runtime. -- **`db`**: Path to the name of the file that stores or will store the parachain's database. -- **`config`**: Path or URL of the config file. -- **`port`**: The port to expose an endpoint on. -- **`build-block-mode`**: How blocks should be built in the fork: batch, manual, instant. -- **`import-storage`**: A pre-defined JSON/YAML storage path to override in the parachain's storage. -- **`allow-unresolved-imports`**: Whether to allow Wasm unresolved imports when using a Wasm to build the parachain. -- **`html`**: Include to generate storage diff preview between blocks. -- **`mock-signature-host`**: Mock signature host so that any signature starts with `0xdeadbeef` and filled by `0xcd` is considered valid. - -### Configuration File - -The Chopsticks source repository includes a collection of [YAML](https://yaml.org/){target=\_blank} files that can be used to set up various Polkadot SDK chains locally. You can download these configuration files from the [repository's `configs` folder](https://github.com/AcalaNetwork/chopsticks/tree/master/configs){target=\_blank}. - -An example of a configuration file for Polkadot is as follows: - -{% raw %} -```yaml -endpoint: - - wss://rpc.ibp.network/polkadot - - wss://polkadot-rpc.dwellir.com -mock-signature-host: true -block: ${env.POLKADOT_BLOCK_NUMBER} -db: ./db.sqlite -runtime-log-level: 5 - -import-storage: - System: - Account: - - - - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY - - providers: 1 - data: - free: '10000000000000000000' - ParasDisputes: - $removePrefix: ['disputes'] # those can makes block building super slow - -``` -{% endraw %} - -The configuration file allows you to modify the storage of the forked network by rewriting the pallet, state component and value that you want to change. For example, Polkadot's file rewrites Alice's `system.Account` storage so that the free balance is set to `10000000000000000000`. - -### CLI Flags - -Alternatively, all settings (except for genesis and timestamp) can be configured via command-line flags, providing a comprehensive method to set up the environment. - -## WebSocket Commands - -Chopstick's internal WebSocket server has special endpoints that allow the manipulation of the local Polkadot SDK chain. - -These are the methods that can be invoked and their parameters: - -- **dev_newBlock** (newBlockParams): Generates one or more new blocks. - - === "Parameters" - - - **`newBlockParams` ++"NewBlockParams"++**: The parameters to build the new block with. Where the `NewBlockParams` interface includes the following properties. - - - **`count` ++"number"++**: The number of blocks to build. - - **`dmp` ++"{ msg: string, sentAt: number }[]"++**: The downward messages to include in the block. - - **`hrmp` ++"Record"++**: The horizontal messages to include in the block. - - **`to` ++"number"++**: The block number to build to. - - **`transactions` ++"string[]"++**: The transactions to include in the block. - - **`ump` ++"Record"++**: The upward messages to include in the block. - - **`unsafeBlockHeight` ++"number"++**: Build block using a specific block height (unsafe). - - === "Example" - - ```js - import { ApiPromise, WsProvider } from '@polkadot/api'; - - async function main() { - const wsProvider = new WsProvider('ws://localhost:8000'); - const api = await ApiPromise.create({ provider: wsProvider }); - await api.isReady; - await api.rpc('dev_newBlock', { count: 1 }); - } - - main(); - - ``` - -- **dev_setBlockBuildMode** (buildBlockMode): Sets block build mode. - - === "Parameter" - - - **`buildBlockMode` ++"BuildBlockMode"++**: The build mode. Can be any of the following modes: - - ```ts - export enum BuildBlockMode { - Batch = 'Batch', /** One block per batch (default) */ - Instant = 'Instant', /** One block per transaction */ - Manual = 'Manual', /** Only build when triggered */ - } - ``` - - === "Example" - - ```js - import { ApiPromise, WsProvider } from '@polkadot/api'; - - async function main() { - const wsProvider = new WsProvider('ws://localhost:8000'); - const api = await ApiPromise.create({ provider: wsProvider }); - await api.isReady; - await api.rpc('dev_setBlockBuildMode', 'Instant'); - } - - main(); - - ``` - -- **dev_setHead** (hashOrNumber): Sets the head of the blockchain to a specific hash or number. - - === "Parameter" - - - **`hashOrNumber` ++"string | number"++**: The block hash or number to set as head. - - === "Example" - - ```js - import { ApiPromise, WsProvider } from '@polkadot/api'; - - async function main() { - const wsProvider = new WsProvider('ws://localhost:8000'); - const api = await ApiPromise.create({ provider: wsProvider }); - await api.isReady; - await api.rpc('dev_setHead', 500); - } - - main(); - - ``` - -- **dev_setRuntimeLogLevel** (runtimeLogLevel): Sets the runtime log level. - - === "Parameter" - - - **`runtimeLogLevel` ++"number"++**: The runtime log level to set. - - === "Example" - - ```js - import { ApiPromise, WsProvider } from '@polkadot/api'; - - async function main() { - const wsProvider = new WsProvider('ws://localhost:8000'); - const api = await ApiPromise.create({ provider: wsProvider }); - await api.isReady; - await api.rpc('dev_setRuntimeLogLevel', 1); - } - - main(); - - ``` - -- **dev_setStorage** (values, blockHash): Creates or overwrites the value of any storage. - - === "Parameters" - - - **`values` ++"object"++**: JSON object resembling the path to a storage value. - - **`blockHash` ++"string"++**: The block hash to set the storage value. - - === "Example" - - ```js - import { ApiPromise, WsProvider } from '@polkadot/api'; - - import { Keyring } from '@polkadot/keyring'; - async function main() { - const wsProvider = new WsProvider('ws://localhost:8000'); - const api = await ApiPromise.create({ provider: wsProvider }); - await api.isReady; - const keyring = new Keyring({ type: 'ed25519' }); - const bob = keyring.addFromUri('//Bob'); - const storage = { - System: { - Account: [[[bob.address], { data: { free: 100000 }, nonce: 1 }]], - }, - }; - await api.rpc('dev_setStorage', storage); - } - - main(); - - ``` - -- **dev_timeTravel** (date): Sets the timestamp of the block to a specific date". - - === "Parameter" - - - **`date` ++"string"++**: Timestamp or date string to set. All future blocks will be sequentially created after this point in time. - - === "Example" - - ```js - import { ApiPromise, WsProvider } from '@polkadot/api'; - - async function main() { - const wsProvider = new WsProvider('ws://localhost:8000'); - const api = await ApiPromise.create({ provider: wsProvider }); - await api.isReady; - await api.rpc('dev_timeTravel', '2030-08-15T00:00:00'); - } - - main(); - - ``` - -## Where to Go Next - -
    - -- Tutorial __Fork a Chain with Chopsticks__ - - --- - - Visit this guide for step-by-step instructions for configuring and interacting with your forked chain. - - [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/fork-live-chains/) - -
    - - ---- - -Page Title: Get Started - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md -- Canonical (HTML): https://docs.polkadot.com/parachains/testing/run-a-parachain-network/ -- Summary: Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. - -# Get Started - -## Introduction - -Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance. - -This guide will outline the different installation methods for Zombienet, provide step-by-step instructions for setting up on various platforms, and highlight essential provider-specific features and requirements. - -By following this guide, Zombienet will be up and running quickly, ready to streamline your blockchain testing and development workflows. - -## Install Zombienet - -Zombienet releases are available on the [Zombienet repository](https://github.com/paritytech/zombienet){target=\_blank}. - -Multiple options are available for installing Zombienet, depending on the user's preferences and the environment where it will be used. The following section will guide you through the installation process for each option. - -=== "Use the executable" - - Install Zombienet using executables by visiting the [latest release](https://github.com/paritytech/zombienet/releases){target=\_blank} page and selecting the appropriate asset for your operating system. You can download the executable and move it to a directory in your PATH. - - Each release includes executables for Linux and macOS. Executables are generated using [pkg](https://github.com/vercel/pkg){target=\_blank}, which allows the Zombienet CLI to operate without requiring Node.js to be installed. - - Then, ensure the downloaded file is executable: - - ```bash - chmod +x zombienet-macos-arm64 - ``` - - Finally, you can run the following command to check if the installation was successful. If so, it will display the version of the installed Zombienet: - - ```bash - ./zombienet-macos-arm64 version - ``` - - If you want to add the `zombienet` executable to your PATH, you can move it to a directory in your PATH, such as `/usr/local/bin`: - - ```bash - mv zombienet-macos-arm64 /usr/local/bin/zombienet - ``` - - Now you can refer to the `zombienet` executable directly. - - ```bash - zombienet version - ``` - -=== "Use Nix" - - For Nix users, the Zombienet repository provides a [`flake.nix`](https://github.com/paritytech/zombienet/blob/main/flake.nix){target=\_blank} file to install Zombienet making it easy to incorporate Zombienet into Nix-based projects. - - To install Zombienet utilizing Nix, users can run the following command, triggering the fetching of the flake and subsequently installing the Zombienet package: - - ```bash - nix run github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION -- \ - spawn INSERT_ZOMBIENET_CONFIG_FILE_NAME.toml - ``` - - Replace the `INSERT_ZOMBIENET_VERSION` with the desired version of Zombienet and the `INSERT_ZOMBIENET_CONFIG_FILE_NAME` with the name of the configuration file you want to use. - - To run the command above, you need to have [Flakes](https://nixos.wiki/wiki/Flakes#Enable_flakes){target=\_blank} enabled. - - Alternatively, you can also include the Zombienet binary in the PATH for the current shell using the following command: - - ```bash - nix shell github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION - ``` - -=== "Use Docker" - - Zombienet can also be run using Docker. The Zombienet repository provides a Docker image that can be used to run the Zombienet CLI. To run Zombienet using Docker, you can use the following command: - - ```bash - docker run -it --rm \ - -v $(pwd):/home/nonroot/zombie-net/host-current-files \ - paritytech/zombienet - ``` - - The command above will run the Zombienet CLI inside a Docker container and mount the current directory to the `/home/nonroot/zombie-net/host-current-files` directory. This allows Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path. - - Inside the Docker container, you can run the Zombienet CLI commands. First, you need to set up Zombienet to download the necessary binaries: - - ```bash - npm run zombie -- setup polkadot polkadot-parachain - ``` - - After that, you need to add those binaries to the PATH: - - ```bash - export PATH=/home/nonroot/zombie-net:$PATH - ``` - - Finally, you can run the Zombienet CLI commands. For example, to spawn a network using a specific configuration file, you can run the following command: - - ```bash - npm run zombie -- -p native spawn host-current-files/minimal.toml - ``` - - The command above mounts the current directory to the `/workspace` directory inside the Docker container, allowing Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path. - -## Providers - -Zombienet supports different backend providers for running the nodes. At this moment, [Kubernetes](https://kubernetes.io/){target=\_blank}, [Podman](https://podman.io/){target=\_blank}, and local providers are supported, which can be declared as `kubernetes`, `podman`, or `native`, respectively. - -To use a particular provider, you can specify it in the network file or use the `--provider` flag in the CLI: - -```bash -zombienet spawn network.toml --provider INSERT_PROVIDER -``` - -Alternatively, you can set the provider in the network file: - -```toml -[settings] -provider = "INSERT_PROVIDER" -... -``` - -It's important to note that each provider has specific requirements and associated features. The following sections cover each provider's requirements and added features. - -### Kubernetes - -Kubernetes is a portable, extensible, open-source platform for managing containerized workloads and services. Zombienet is designed to be compatible with a variety of Kubernetes clusters, including: - -- [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine){target=\_blank} -- [Docker Desktop](https://docs.docker.com/desktop/features/kubernetes/){target=\_blank} -- [kind](https://kind.sigs.k8s.io/){target=\_blank} - -#### Requirements - -To effectively interact with your cluster, you'll need to ensure that [`kubectl`](https://kubernetes.io/docs/reference/kubectl/){target=\_blank} is installed on your system. This Kubernetes command-line tool allows you to run commands against Kubernetes clusters. If you don't have `kubectl` installed, you can follow the instructions provided in the [Kubernetes documentation](https://kubernetes.io/docs/tasks/tools/#kubectl){target=\_blank}. - -To create resources such as namespaces, pods, and CronJobs within the target cluster, you must grant your user or service account the appropriate permissions. These permissions are essential for managing and deploying applications effectively within Kubernetes. - -#### Features - -If available, Zombienet uses the Prometheus operator to oversee monitoring and visibility. This configuration ensures that only essential networking-related pods are deployed. Using the Prometheus operator, Zombienet improves its ability to monitor and manage network activities within the Kubernetes cluster efficiently. - -### Podman - -Podman is a daemonless container engine for developing, managing, and running Open Container Initiative (OCI) containers and container images on Linux-based systems. Zombienet supports Podman rootless as a provider on Linux machines. Although Podman has support for macOS through an internal virtual machine (VM), the Zombienet provider code requires Podman to run natively on Linux. - -#### Requirements - -To use Podman as a provider, you need to have Podman installed on your system. You can install Podman by following the instructions provided on the [Podman website](https://podman.io/getting-started/installation){target=\_blank}. - -#### Features - -Using Podman, Zombienet deploys additional pods to enhance the monitoring and visibility of the active network. Specifically, pods for [Prometheus](https://prometheus.io/){target=\_blank}, [Tempo](https://grafana.com/docs/tempo/latest/operations/monitor/){target=\_blank}, and [Grafana](https://grafana.com/){target=\_blank} are included in the deployment. Grafana is configured with Prometheus and Tempo as data sources. - -Upon launching Zombienet, access to these monitoring services is facilitated through specific URLs provided in the output: - -- **Prometheus**: `http://127.0.0.1:34123` -- **Tempo**: `http://127.0.0.1:34125` -- **Grafana**: `http://127.0.0.1:41461` - -It's important to note that Grafana is deployed with default administrator access. - -When network operations cease, either from halting a running spawn with the `Ctrl+C` command or test completion, Zombienet automatically removes all associated pods. - -### Local Provider - -The Zombienet local provider, also called native, enables you to run nodes as local processes in your environment. - -#### Requirements - -You must have the necessary binaries for your network (such as `polkadot` and `polkadot-parachain`). These binaries should be available in your PATH, allowing Zombienet to spawn the nodes as local processes. - -To install the necessary binaries, you can use the Zombienet CLI command: - -```bash -zombienet setup polkadot polkadot-parachain -``` - -This command will download and prepare the necessary binaries for Zombienet's use. - -If you need to use a custom binary, ensure the binary is available in your PATH. You can also specify the binary path in the network configuration file. The following example uses the custom [OpenZeppelin template](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}: - -First, clone the OpenZeppelin template repository using the following command: - -```bash -git clone https://github.com/OpenZeppelin/polkadot-runtime-templates \ -&& cd polkadot-runtime-templates/generic-template -``` - -Next, run the command to build the custom binary: - -```bash -cargo build --release -``` - -Finally, add the custom binary to your PATH as follows: - -```bash -export PATH=$PATH:INSERT_PATH_TO_RUNTIME_TEMPLATES/parachain-template-node/target/release -``` - -Alternatively, you can specify the binary path in the network configuration file. The local provider exclusively utilizes the command configuration for nodes, which supports both relative and absolute paths. You can employ the `default_command` configuration to specify the binary for spawning all nodes in the relay chain. - -```toml -[relaychain] -chain = "rococo-local" -default_command = "./bin-v1.6.0/polkadot" - -[parachain] -id = 1000 - - [parachain.collators] - name = "collator01" - command = "./target/release/parachain-template-node" -``` - -#### Features - -The local provider does not offer any additional features. - -## Configure Zombienet - -Effective network configuration is crucial for deploying and managing blockchain systems. Zombienet simplifies this process by offering versatile configuration options in both JSON and TOML formats. Whether setting up a simple test network or a complex multi-node system, Zombienet's tools provide the flexibility to customize every aspect of your network's setup. - -The following sections will explore the structure and usage of Zombienet configuration files, explain key settings for network customization, and walk through CLI commands and flags to optimize your development workflow. - -### Configuration Files - -The network configuration file can be either JSON or TOML format. The Zombienet repository also provides a collection of [example configuration files](https://github.com/paritytech/zombienet/tree/main/examples){target=\_blank} that can be used as a reference. - -Each section may include provider-specific keys that aren't recognized by other providers. For example, if you use the local provider, any references to images for nodes will be disregarded. - -### CLI Usage - -Zombienet provides a CLI that allows interaction with the tool. The CLI can receive commands and flags to perform different kinds of operations. These operations use the following syntax: - -```bash -zombienet -``` - -The following sections will guide you through the primary usage of the Zombienet CLI and the available commands and flags. - -#### CLI Commands - -- **`spawn `**: Spawn the network defined in the [configuration file](#configuration-files). -- **`test `**: Run tests on the spawned network using the assertions and tests defined in the [test file](/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/#the-test-file){target=\_blank}. -- **`setup `**: Set up the Zombienet development environment to download and use the `polkadot` or `polkadot-parachain` executable. -- **`convert `**: Transforms a [polkadot-launch](https://github.com/paritytech/polkadot-launch){target=\_blank} configuration file with a `.js` or `.json` extension into a Zombienet configuration file. -- **`version`**: Prints Zombienet version. -- **`help`**: Prints help information. - -#### CLI Flags - -You can use the following flags to customize the behavior of the CLI: - -- **`-p`, `--provider`**: Override the [provider](#providers) to use. -- **`-d`, `--dir`**: Specify a directory path for placing the network files instead of using the default temporary path. -- **`-f`, `--force`**: Force override all prompt commands. -- **`-l`, `--logType`**: Type of logging on the console. Defaults to `table`. -- **`-m`, `--monitor`**: Start as monitor and don't auto clean up network. -- **`-c`, `--spawn-concurrency`**: Number of concurrent spawning processes to launch. Defaults to `1`. -- **`-h`, `--help`**: Display help for command. - -### Settings - -Through the keyword `settings`, it's possible to define the general settings for the network. The available keys are: - -- **`global_volumes?`** ++"GlobalVolume[]"++: A list of global volumes to use. - - ??? child "`GlobalVolume` interface definition" - ```js - export interface GlobalVolume { - name: string; - fs_type: string; - mount_path: string; - } - ``` - -- **`bootnode`** ++"boolean"++: Add bootnode to network. Defaults to `true`. -- **`bootnode_domain?`** ++"string"++: Domain to use for bootnode. -- **`timeout`** ++"number"++: Global timeout to use for spawning the whole network. -- **`node_spawn_timeout?`** ++"number"++: Timeout to spawn pod/process. -- **`grafana?`** ++"boolean"++: Deploy an instance of Grafana. -- **`prometheus?`** ++"boolean"++: Deploy an instance of Prometheus. -- **`telemetry?`** ++"boolean"++: Enable telemetry for the network. -- **`jaeger_agent?`** ++"string"++: The Jaeger agent endpoint passed to the nodes. Only available on Kubernetes. -- **`tracing_collator_url?`** ++"string"++: The URL of the tracing collator used to query by the tracing assertion. Should be tempo query compatible. -- **`tracing_collator_service_name?`** ++"string"++: Service name for tempo query frontend. Only available on Kubernetes. Defaults to `tempo-tempo-distributed-query-frontend`. -- **`tracing_collator_service_namespace?`** ++"string"++: Namespace where tempo is running. Only available on Kubernetes. Defaults to `tempo`. -- **`tracing_collator_service_port?`** ++"number"++: Port of the query instance of tempo. Only available on Kubernetes. Defaults to `3100`. -- **`enable_tracing?`** ++"boolean"++: Enable the tracing system. Only available on Kubernetes. Defaults to `true`. -- **`provider`** ++"string"++: Provider to use. Default is `kubernetes`". -- **`polkadot_introspector?`** ++"boolean"++: Deploy an instance of polkadot-introspector. Only available on Podman and Kubernetes. Defaults to `false`. -- **`backchannel?`** ++"boolean"++: Deploy an instance of backchannel server. Only available on Kubernetes. Defaults to `false`. -- **`image_pull_policy?`** ++"string"++: Image pull policy to use in the network. Possible values are `Always`, `IfNotPresent`, and `Never`. -- **`local_ip?`** ++"string"++: IP used for exposing local services (rpc/metrics/monitors). Defaults to `"127.0.0.1"`. -- **`global_delay_network_global_settings?`** ++"number"++: Delay in seconds to apply to the network. -- **`node_verifier?`** ++"string"++: Specify how to verify node readiness or deactivate by using `None`. Possible values are `None` and `Metric`. Defaults to `Metric`. - -For example, the following configuration file defines a minimal example for the settings: - -=== "TOML" - - ```toml title="base-example.toml" - [settings] - timeout = 1000 - bootnode = false - provider = "kubernetes" - backchannel = false - # ... - - ``` - -=== "JSON" - - ```json title="base-example.json" - { - "settings": { - "timeout": 1000, - "bootnode": false, - "provider": "kubernetes", - "backchannel": false, - "...": {} - }, - "...": {} - } - - ``` - -### Relay Chain Configuration - -You can use the `relaychain` keyword to define further parameters for the relay chain at start-up. The available keys are: - -- **`default_command?`** ++"string"++: The default command to run. Defaults to `polkadot`. -- **`default_image?`** ++"string"++: The default Docker image to use. -- **`default_resources?`** ++"Resources"++: Represents the resource limits/reservations the nodes need by default. Only available on Kubernetes. - - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } - ``` - -- **`default_db_snapshot?`** ++"string"++: The default database snapshot to use. -- **`default_prometheus_prefix`** ++"string"++: A parameter for customizing the metric's prefix. Defaults to `substrate`. -- **`default_substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version. - - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } - ``` - -- **`default_keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. -- **`chain`** ++"string"++: The chain name. -- **`chain_spec_path?`** ++"string"++: Path to the chain spec file. Should be the plain version to allow customizations. -- **`chain_spec_command?`** ++"string"++: Command to generate the chain spec. It can't be used in combination with `chain_spec_path`. -- **`default_args?`** ++"string[]"++: An array of arguments to use as default to pass to the command. -- **`default_overrides?`** ++"Override[]"++: An array of overrides to upload to the node. - - ??? child "`Override` interface definition" - ```js - export interface Override { - local_path: string; - remote_name: string; - } - ``` - -- **`random_nominators_count?`** ++"number"++: If set and the stacking pallet is enabled, Zombienet will generate the input quantity of nominators and inject them into the genesis. -- **`max_nominations`** ++"number"++: The max number of nominations allowed by a nominator. Should match the value set in the runtime. Defaults to `24`. -- **`nodes?`** ++"Node[]"++: An array of nodes to spawn. It is further defined in the [Node Configuration](#node-configuration) section. -- **`node_groups?`** ++"NodeGroup[]"++: An array of node groups to spawn. It is further defined in the [Node Group Configuration](#node-group-configuration) section. -- **`total_node_in_group?`** ++"number"++: The total number of nodes in the group. Defaults to `1`. -- **`genesis`** ++"JSON"++: The genesis configuration. -- **`default_delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. - - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` - -#### Node Configuration - -One specific key capable of receiving more subkeys is the `nodes` key. This key is used to define further parameters for the nodes. The available keys: - -- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). -- **`image?`** ++"string"++: Override default Docker image to use for this node. -- **`command?`** ++"string"++: Override default command to run. -- **`command_with_args?`** ++"string"++: Override default command and arguments. -- **`args?`** ++"string[]"++: Arguments to be passed to the command. -- **`env?`** ++"envVars[]"++: Environment variables to set in the container. - - ??? child "`envVars` interface definition" - ```js - export interface EnvVars { - name: string; - value: string; - } - ``` - -- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. -- **`db_snapshot?`** ++"string"++: Database snapshot to use. -- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. - - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } - ``` - -- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. - - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } - ``` - -- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. -- **`validator`** ++"boolean"++: Pass the `--validator` flag to the command. Defaults to `true`. -- **`invulnerable`** ++"boolean"++: If true, add the node to invulnerables in the chain spec. Defaults to `false`. -- **`balance`** ++"number"++: Balance to set in balances for node's account. Defaults to `2000000000000`. -- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. -- **`add_to_bootnodes?`** ++"boolean"++: Add this node to the bootnode list. Defaults to `false`. -- **`ws_port?`** ++"number"++: WS port to use. -- **`rpc_port?`** ++"number"++: RPC port to use. -- **`prometheus_port?`** ++"number"++: Prometheus port to use. -- **`p2p_cert_hash?`** ++"string"++: Libp2p certhash to use with webRTC transport. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. - - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` - -The following configuration file defines a minimal example for the relay chain, including the `nodes` key: - -=== "TOML" - - ```toml title="relaychain-example-nodes.toml" - [relaychain] - default_command = "polkadot" - default_image = "polkadot-debug:master" - chain = "rococo-local" - chain_spec_path = "INSERT_PATH_TO_CHAIN_SPEC" - default_args = ["--chain", "rococo-local"] - - [[relaychain.nodes]] - name = "alice" - validator = true - balance = 1000000000000 - - [[relaychain.nodes]] - name = "bob" - validator = true - balance = 1000000000000 - # ... - - ``` - -=== "JSON" - - ```json title="relaychain-example-nodes.json" - { - "relaychain": { - "default_command": "polkadot", - "default_image": "polkadot-debug:master", - "chain": "rococo-local", - "chain_spec_path": "INSERT_PATH_TO_CHAIN-SPEC.JSON", - "default_args": ["--chain", "rococo-local"], - "nodes": [ - { - "name": "alice", - "validator": true, - "balance": 1000000000000 - }, - { - "name": "bob", - "validator": true, - "balance": 1000000000000 - } - ] - } - } - - ``` - -#### Node Group Configuration - -The `node_groups` key defines further parameters for the node groups. The available keys are: - -- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). -- **`image?`** ++"string"++: Override default Docker image to use for this node. -- **`command?`** ++"string"++: Override default command to run. -- **`args?`** ++"string[]"++: Arguments to be passed to the command. -- **`env?`** ++"envVars[]"++: Environment variables to set in the container. - - ??? child "`envVars` interface definition" - ```js - export interface EnvVars { - name: string; - value: string; - } - ``` - -- **`overrides?`** ++"Override[]"++: Array of overrides definitions. - - ??? child "`Override` interface definition" - ```js - export interface Override { - local_path: string; - remote_name: string; - } - ``` - -- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. -- **`db_snapshot?`** ++"string"++: Database snapshot to use. -- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. - - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } - ``` - -- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. - - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } - ``` - -- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. -- **`count`** ++"number | string"++: Number of nodes to launch for this group. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. - - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` - -The following configuration file defines a minimal example for the relay chain, including the `node_groups` key: - -=== "TOML" - - ```toml title="relaychain-example-node-groups.toml" - [relaychain] - default_command = "polkadot" - default_image = "polkadot-debug:master" - chain = "rococo-local" - chain_spec_path = "INSERT_PATH_TO_CHAIN_SPEC" - default_args = ["--chain", "rococo-local"] - - [[relaychain.node_groups]] - name = "group-1" - count = 2 - image = "polkadot-debug:master" - command = "polkadot" - args = ["--chain", "rococo-local"] - # ... - - ``` - -=== "JSON" - - ```json title="relaychain-example-node-groups.json" - { - "relaychain": { - "default_command": "polkadot", - "default_image": "polkadot-debug:master", - "chain": "rococo-local", - "chain_spec_path": "INSERT_PATH_TO_CHAIN-SPEC.JSON", - "default_args": ["--chain", "rococo-local"], - "node_groups": [ - { - "name": "group-1", - "count": 2, - "image": "polkadot-debug:master", - "command": "polkadot", - "args": ["--chain", "rococo-local"] - } - ], - "...": {} - }, - "...": {} - } - - ``` - -### Parachain Configuration - -The `parachain` keyword defines further parameters for the parachain. The available keys are: - -- **`id`** ++"number"++: The id to assign to this parachain. Must be unique. -- **`chain?`** ++"string"++: The chain name. -- **`force_decorator?`** ++"string"++: Force the use of a specific decorator. -- **`genesis?`** ++"JSON"++: The genesis configuration. -- **`balance?`** ++"number"++: Balance to set in balances for parachain's account. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. - - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` - -- **`add_to_genesis?`** ++"boolean"++: Flag to add parachain to genesis or register in runtime. Defaults to `true`. -- **`register_para?`** ++"boolean"++: Flag to specify whether the para should be registered. The `add_to_genesis` flag must be set to false for this flag to have any effect. Defaults to `true`. -- **`onboard_as_parachain?`** ++"boolean"++: Flag to specify whether the para should be onboarded as a parachain, rather than remaining a parathread. Defaults to `true`. -- **`genesis_wasm_path?`** ++"string"++: Path to the Wasm file to use. -- **`genesis_wasm_generator?`** ++"string"++: Command to generate the Wasm file. -- **`genesis_state_path?`** ++"string"++: Path to the state file to use. -- **`genesis_state_generator?`** ++"string"++: Command to generate the state file. -- **`chain_spec_path?`** ++"string"++: Path to the chain spec file. -- **`chain_spec_command?`** ++"string"++: Command to generate the chain spec. -- **`cumulus_based?`** ++"boolean"++: Flag to use cumulus command generation. Defaults to `true`. -- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. -- **`prometheus_prefix?`** ++"string"++: Parameter for customizing the metric's prefix for all parachain nodes/collators. Defaults to `substrate`. -- **`collator?`** ++"Collator"++: Further defined in the [Collator Configuration](#collator-configuration) section. -- **`collator_groups?`** ++"CollatorGroup[]"++: An array of collator groups to spawn. It is further defined in the [Collator Groups Configuration](#collator-groups-configuration) section. - -For example, the following configuration file defines a minimal example for the parachain: - -=== "TOML" - - ```toml title="parachain-example.toml" - [parachain] - id = 100 - add_to_genesis = true - cumulus_based = true - genesis_wasm_path = "INSERT_PATH_TO_WASM" - genesis_state_path = "INSERT_PATH_TO_STATE" - # ... - - ``` - -=== "JSON" - - ```json title="parachain-example.json" - { - "parachain": { - "id": 100, - "add_to_genesis": true, - "cumulus_based": true, - "genesis_wasm_path": "INSERT_PATH_TO_WASM", - "genesis_state_path": "INSERT_PATH_TO_STATE", - "...": {} - }, - "...": {} - } - - ``` - -#### Collator Configuration - -One specific key capable of receiving more subkeys is the `collator` key. This key defines further parameters for the nodes. The available keys are: - -- **`name`** ++"string"++: Name of the collator. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). -- **`image?`** ++"string"++: Image to use for the collator. -- **`command_with_args?`** ++"string"++: Overrides both command and arguments for the collator. -- **`validator`** ++"boolean"++: Pass the `--validator` flag to the command. Defaults to `true`. -- **`invulnerable`** ++"boolean"++: If true, add the collator to invulnerables in the chain spec. Defaults to `false`. -- **`balance`** ++"number"++: Balance to set in balances for collator's account. Defaults to `2000000000000`. -- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. -- **`add_to_bootnodes?`** ++"boolean"++: Add this collator to the bootnode list. Defaults to `false`. -- **`ws_port?`** ++"number"++: WS port to use. -- **`rpc_port?`** ++"number"++: RPC port to use. -- **`prometheus_port?`** ++"number"++: Prometheus port to use. -- **`p2p_port?`** ++"number"++: P2P port to use. -- **`p2p_cert_hash?`** ++"string"++: Libp2p certhash to use with webRTC transport. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. - - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` - -- **`command?`** ++"string"++: Override default command to run. -- **`args?`** ++"string[]"++: Arguments to be passed to the command. -- **`env?`** ++"envVars[]"++: Environment variables to set in the container. - - ??? child "`envVars` interface definition" - ```js - export interface EnvVars { - name: string; - value: string; - } - ``` - -- **`overrides?`** ++"Override[]"++: Array of overrides definitions. - - ??? child "`Override` interface definition" - ```js - export interface Override { - local_path: string; - remote_name: string; - } - ``` - -- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. -- **`db_snapshot?`** ++"string"++: Database snapshot to use. -- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. - - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } - ``` - -- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. - - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } - ``` - -- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. - -The configuration file below defines a minimal example for the collator: - -=== "TOML" - - ```toml title="collator-example.toml" - [parachain] - id = 100 - add_to_genesis = true - cumulus_based = true - genesis_wasm_path = "INSERT_PATH_TO_WASM" - genesis_state_path = "INSERT_PATH_TO_STATE" - - [[parachain.collators]] - name = "alice" - image = "polkadot-parachain" - command = "polkadot-parachain" - # ... - - ``` - -=== "JSON" - - ```json title="collator-example.json" - { - "parachain": { - "id": 100, - "add_to_genesis": true, - "cumulus_based": true, - "genesis_wasm_path": "INSERT_PATH_TO_WASM", - "genesis_state_path": "INSERT_PATH_TO_STATE", - "collators": [ - { - "name": "alice", - "image": "polkadot-parachain", - "command": "polkadot-parachain", - "...": {} - } - ] - }, - "...": {} - } - - ``` - -#### Collator Groups Configuration - -The `collator_groups` key defines further parameters for the collator groups. The available keys are: - -- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). -- **`image?`** ++"string"++: Override default Docker image to use for this node. -- **`command?`** ++"string"++: Override default command to run. -- **`args?`** ++"string[]"++: Arguments to be passed to the command. -- **`env?`** ++"envVars[]"++: Environment variables to set in the container. - - ??? child "`envVars` interface definition" - ```js - export interface EnvVars { - name: string; - value: string; - } - ``` - -- **`overrides?`** ++"Override[]"++: Array of overrides definitions. - - ??? child "`Override` interface definition" - ```js - export interface Override { - local_path: string; - remote_name: string; - } - ``` - -- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. -- **`db_snapshot?`** ++"string"++: Database snapshot to use. -- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. - - ??? child "`SubstrateCliArgsVersion` enum definition" - ```js - export enum SubstrateCliArgsVersion { - V0 = 0, - V1 = 1, - V2 = 2, - V3 = 3, - } - ``` - -- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. - - ??? child "`Resources` interface definition" - ```js - export interface Resources { - resources: { - requests?: { - memory?: string; - cpu?: string; - }; - limits?: { - memory?: string; - cpu?: string; - }; - }; - } - ``` - -- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. -- **`count`** ++"number | string"++: Number of nodes to launch for this group. -- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. - - ??? child "`DelayNetworkSettings` interface definition" - ```js - export interface DelayNetworkSettings { - latency: string; - correlation?: string; // should be parsable as float by k8s - jitter?: string; - } - ``` - -For instance, the configuration file below defines a minimal example for the collator groups: - -=== "TOML" - - ```toml title="collator-groups-example.toml" - [parachain] - id = 100 - add_to_genesis = true - cumulus_based = true - genesis_wasm_path = "INSERT_PATH_TO_WASM" - genesis_state_path = "INSERT_PATH_TO_STATE" - - [[parachain.collator_groups]] - name = "group-1" - count = 2 - image = "polkadot-parachain" - command = "polkadot-parachain" - # ... - - ``` - -=== "JSON" - - ```json title="collator-groups-example.json" - { - "parachain": { - "id": 100, - "add_to_genesis": true, - "cumulus_based": true, - "genesis_wasm_path": "INSERT_PATH_TO_WASM", - "genesis_state_path": "INSERT_PATH_TO_STATE", - "collator_groups": [ - { - "name": "group-1", - "count": 2, - "image": "polkadot-parachain", - "command": "polkadot-parachain", - "...": {} - } - ] - }, - "...": {} - } - - ``` - -### XCM Configuration - -You can use the `hrmp_channels` keyword to define further parameters for the XCM channels at start-up. The available keys are: - -- **`hrmp_channels`** ++"HrmpChannelsConfig[]"++: Array of Horizontal Relay-routed Message Passing (HRMP) channel configurations. - - ??? child "`HrmpChannelsConfig` interface definition" - ```js - export interface HrmpChannelsConfig { - sender: number; - recipient: number; - max_capacity: number; - max_message_size: number; - } - ``` - Each of the `HrmpChannelsConfig` keys are defined as follows: - - - **`sender` ++"number"++**: Parachain ID of the sender. - - **`recipient` ++"number"++**: Parachain ID of the recipient. - - **`max_capacity` ++"number"++**: Maximum capacity of the HRMP channel. - - **`max_message_size` ++"number"++**: Maximum message size allowed in the HRMP channel. - -## Where to Go Next - -
    - -- External __Zombienet Support__ - - --- - - [Parity Technologies](https://www.parity.io/){target=\_blank} has designed and developed this framework, now maintained by the Zombienet team. - - For further support and information, refer to the following contact points: - - [:octicons-arrow-right-24: Zombienet repository](https://github.com/paritytech/zombienet){target=\_blank} - - [:octicons-arrow-right-24: Element public channel](https://matrix.to/#/!FWyuEyNvIFygLnWNMh:parity.io?via=parity.io&via=matrix.org&via=web3.foundation){target=\_blank} - - -- Tutorial __Spawn a Basic Chain with Zombienet__ - - --- - - Learn to spawn, connect to and monitor a basic blockchain network with Zombienet, using customizable configurations for streamlined development and debugging. - - [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/spawn-basic-chain/) - -
    - - ---- - -Page Title: Get Started with Parachain Development - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/get-started/ -- Summary: Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. - -# Get Started - -The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. - -## Quick Start Guides - -Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. - -| Tutorial | Tools | Description | -| :--------------------------------------------------------------------------------------------: | :----------------------------: | :---------------------------------------------------------------------: | -| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | Learn how to set up and run the Polkadot SDK Parachain Template locally | -| [Launch a Local Parachain](/parachains/testing/run-a-parachain-network/) | Zombienet, Chopsticks | Set up a local development environment for testing | -| [Connect to Polkadot](/chain-interactions/query-on-chain-data/query-sdks/) | Polkadot.js, Substrate Connect | Connect your application to Polkadot networks | -| [Fork an Existing Parachain](/parachains/testing/fork-a-parachain/) | Chopsticks | Create a local fork of a live parachain for testing | - -## Launch a Simple Parachain - -Learn the fundamentals of launching and deploying a parachain to the Polkadot network. - -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------: | -| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | -| [Deploy to Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/) | Step-by-step tutorial to deploying your parachain to Polkadot | -| [Obtain Coretime](/parachains/launch-a-parachain/obtain-coretime/) | Learn how to acquire blockspace using Polkadot's coretime model (RegionX) | - -## Customize Your Runtime - -Build custom functionality for your parachain by composing and creating pallets. - -| Tutorial | Description | -| :-------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------: | -| [Add Existing Pallets to the Runtime](/parachains/customize-runtime/add-existing-pallets/) | Integrate pre-built pallets from the FRAME ecosystem | -| [Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/) | Configure and use multiple instances of the same pallet | -| [Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/) | Enable smart contract capabilities using Contracts or EVM pallets | - -### Pallet Development - -Deep dive into creating and managing custom pallets for your parachain. - -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------: | -| [Create a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/) | Build a pallet from scratch with custom logic | -| [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/) | Set up a mock runtime environment for testing | -| [Pallet Unit Testing](/parachains/customize-runtime/pallet-development/pallet-testing/) | Write comprehensive tests for your pallet logic | -| [Add Your Custom Pallet to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/) | Integrate your custom pallet into your parachain runtime | -| [Benchmark the Custom Pallet](/parachains/customize-runtime/pallet-development/benchmark-pallet/) | Measure and optimize pallet performance with benchmarking | - -## Testing - -Test your parachain in various environments before production deployment. - -| Tutorial | Description | -| :---------------------------------------------------------------------: | :-----------------------------------------------------: | -| [Fork a Parachain](/parachains/testing/fork-a-parachain/) | Use Chopsticks to create a local fork for testing | -| [Run a Parachain Network](/parachains/testing/run-a-parachain-network/) | Launch a complete parachain test network with Zombienet | - -## Runtime Upgrades and Maintenance - -Manage your parachain's lifecycle with forkless upgrades and maintenance operations. - -| Tutorial | Description | -| :-----------------------------------------------------------------------: | :--------------------------------------------------: | -| [Runtime Upgrades](/parachains/runtime-maintenance/runtime-upgrades/) | Perform forkless runtime upgrades via governance | -| [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/) | Safely migrate storage when updating runtime logic | -| [Unlock Parachains](/parachains/runtime-maintenance/unlock-parachains/) | Understand parachain lifecycle and unlock mechanisms | - -## Interoperability - -Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). - -| Tutorial | Description | -| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: | -| [Open HRMP Channels Between Parachains](/parachains/interoperability/channels-between-parachains/) | Establish communication channels with other parachains | -| [Open HRMP Channels with System Parachains](/parachains/interoperability/channels-with-system-parachains/) | Connect with Asset Hub and other system parachains | - -## Integrations - -Integrate your parachain with essential ecosystem tools and services. - -| Tutorial | Description | -| :--------------------------------------------: | :----------------------------------------------------: | -| [Wallets](/parachains/integrations/wallets/) | Integrate wallet support for user interactions | -| [Indexers](/parachains/integrations/indexers/) | Set up indexing solutions for querying blockchain data | -| [Oracles](/parachains/integrations/oracles/) | Connect your parachain to off-chain data sources | - -## Additional Resources - -- [Polkadot SDK Documentation](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/index.html) -- [Polkadot Wiki - Parachains](https://wiki.polkadot.network/docs/learn-parachains/) - - ---- - -Page Title: Get Started with Smart Contracts - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/get-started/ -- Summary: Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. - -# Get Started - -This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need. - -## Quick Starts - -Kick off development fast with curated links for connecting, funding, exploring, and deploying your first contract. - -| Quick Start | Tools | Description | -|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:| -| [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer | -| [Get Test Tokens](/smart-contracts/faucets/){target=\_blank} | - | Request test funds to deploy and interact with contracts | -| [Explore Transactions](/smart-contracts/explorers/){target=\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state | -| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} | Remix | One‑click browser deployment to Polkadot Hub | -| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\_blank} | Foundry | Scripted deployments and testing from the CLI | -| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} | Hardhat | Project scaffolding, testing, and deployments | - -## Build and Test Locally - -Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. - -| Build and Test Locally | Tools | Description | -|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:| -| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\_blank} | Polkadot SDK node | Spin up a local node for iterative development | -| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts | -| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\_blank} | Remix | Publish verified source on explorers | -| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\_blank} | Foundry | Install toolchain and configure networks | -| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\_blank} | Foundry | Write and run Solidity tests locally | -| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\_blank} | Foundry | Verify deployed bytecode and metadata | -| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} | Hardhat | Initialize a project and configure networks | -| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} | Hardhat | Unit test contracts and run scripts | -| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\_blank} | Hardhat | Verify deployments on explorers | - -## Ethereum Developer Resources - -Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. - -| Ethereum Developer Guides | Description | -|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:| -| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts | -| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\_blank} | Transaction types, fees, and multi‑dimensional metering | -| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} | Gas vs. weight, proof size, and storage deposits | -| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\_blank} | Deployment patterns and best practices on Polkadot Hub | -| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank} | Supported Ethereum JSON‑RPC methods and examples | -| [Migration](/smart-contracts/for-eth-devs/migration/){target=\_blank} | Port existing apps and tooling to Polkadot Hub | -| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} | Overview of EVM and native execution on the Hub | - -## Cookbook: Hands‑on Tutorials - -Follow step‑by‑step guides that walk through common tasks and complete dApp examples. - -| Tutorial | Tools | Description | -|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:| -| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} | Remix | Minimal deployment walkthrough | -| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token | -| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection | -| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\_blank} | Hardhat | Full dApp project: compile, test, deploy | -| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\_blank} | Multiple | End‑to‑end dApp patterns and practices | - -## Libraries - -Choose the client libraries that fit your stack for connecting wallets and calling contracts. - -| Library | Description | -|:------------------------------------------------------------------:|:-------------------------------------------------------:| -| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank} | Connect, sign, and interact with contracts using Ethers | -| [viem](/smart-contracts/libraries/viem/){target=\_blank} | Type‑safe EVM interactions and utilities | -| [Wagmi](/smart-contracts/libraries/wagmi/){target=\_blank} | React hooks for wallet connections and contract calls | -| [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank} | Web3 provider and contract APIs | -| [Web3.py](/smart-contracts/libraries/web3-py/){target=\_blank} | Python toolkit for on‑chain interactions and scripts | - -## Integrations - -Integrate essential services like wallets, indexers, and oracles to round out your dApp. - -| Integration | Description | -|:-------------------------------------------------------------------:|:-----------------------------------------:| -| [Wallets](/smart-contracts/integrations/wallets/){target=\_blank} | Supported wallets and configuration notes | -| [Indexers](/smart-contracts/integrations/indexers/){target=\_blank} | Index and query blockchain data | -| [Oracles](/smart-contracts/integrations/oracles/){target=\_blank} | Bring external data on‑chain | - -## Precompiles - -Discover precompiled system contracts available on the Hub and how to use them. - -| Topic | Description | -|:------------------------------------------------------------------------:|:---------------------------------------------------:| -| [Overview of Precompiles](/smart-contracts/precompiles/){target=\_blank} | What precompiles are available on the Hub | -| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\_blank} | EVM precompiles and interfaces | -| [Staking](/smart-contracts/precompiles/staking/){target=\_blank} | Interact with staking functionality via precompiles | -| [XCM](/smart-contracts/precompiles/xcm/){target=\_blank} | Cross‑chain messaging helpers for contracts | - -From here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\_blank} or reach out in the community channels. - - ---- - -Page Title: Glossary - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md -- Canonical (HTML): https://docs.polkadot.com/reference/glossary/ -- Summary: Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. - -# Glossary - -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. - -Additional glossaries from around the ecosystem you might find helpful: - -- [Polkadot Wiki Glossary](https://wiki.polkadot.com/general/glossary){target=\_blank} -- [Polkadot SDK Glossary](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/glossary/index.html){target=\_blank} - -## Authority - -The role in a blockchain that can participate in consensus mechanisms. - -- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final. -- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author). - -Authority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol. - -## Authority Round (Aura) - -A deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol. - -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. - -## Blind Assignment of Blockchain Extension (BABE) - -A [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block. - -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. - -## Block Author - -The node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_. - -## Byzantine Fault Tolerance (BFT) - -The ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack. - -### Byzantine Failure - -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. - -### Practical Byzantine Fault Tolerance (pBFT) - -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. - -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. - -### Preimage - -A preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\_blank}, the output, the hash, cannot be used to reveal the input, the preimage. - -## Call - -In the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object. - -## Chain Specification - -A chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains. - -## Collator - -An [author](#block-author) of a [parachain](#parachain) network. -They aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus). - -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. - -## Collective - -Most often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network. - -## Consensus - -Consensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship. - -See also [hybrid consensus](#hybrid-consensus). - -## Consensus Algorithm - -Ensures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft). - -Consensus algorithms are generally concerned with ensuring two properties: - -- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. -- **Liveness**: Indicating the ability of the chain to keep progressing. - -## Consensus Engine - -The node subsystem responsible for consensus tasks. - -For detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} blog series. - -See also [hybrid consensus](#hybrid-consensus). - -## Coretime - -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. - -On-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety. - -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank}. - -## Development Phrase - -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. - -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: - -``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk -``` - -Many tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`. - -## Digest - -An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: - -- [Light clients](#light-client) for chain synchronization. -- Consensus engines for block verification. -- The runtime itself, in the case of pre-runtime digests. - -## Dispatchable - -Function objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations. - -## Events - -A means of recording that some particular [state](#state) transition happened. - -In the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization. - -## Executor - -A means of executing a function call in a given [runtime](#runtime) with a set of dependencies. -There are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_. - -- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes. - -- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain. - -## Existential Deposit - -The minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. - -If an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\_blank} to drop its references to that account. - -If the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\_blank}. - -## Extrinsic - -A general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder. - -It is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). - -For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. - -## Fork Choice Rule/Strategy - -A fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\_blank}, in which the chain with the most blocks is selected. - -## FRAME (Framework for Runtime Aggregation of Modularized Entities) - -Enables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes. - -[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank} - -## Full Node - -A node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization. - -## Genesis Configuration - -A mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file. - -## GRANDPA - -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. - -The [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\_blank}. - -## Header - -A structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization. - -## Hybrid Consensus - -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. - -Hybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa). - -## Inherent Transactions - -A special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block. - -Only the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified. - -## JSON-RPC - -A stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON. - -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. - -## Keystore - -A subsystem for managing keys for the purpose of producing new blocks. - -## Kusama - -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. - -Kusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\_blank} network and is referred to as [Polkadot's "wild cousin."](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\_blank}. - -As a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation. - -## libp2p - -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). - -Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. - -## Light Client - -A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. - -A light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\_blank} server, enabling blockchain users to interact with the network. - -## Metadata - -Data that provides information about one or more aspects of a system. -The metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system. - -## Nominated Proof of Stake (NPoS) - -A method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes. - -## Oracle - -An entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services. - -## Origin - -A [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\_blank}. - -## Pallet - -A module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime). -Pallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item). - -## Parachain - -A parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_. -You can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\_blank}. - -## Paseo - -Paseo TestNet provisions testing on Polkadot's "production" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing. - -## Polkadot - -The [Polkadot network](https://polkadot.com/){target=\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain). - -## Polkadot Cloud - -Polkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance. - -## Polkadot Hub - -Polkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3. - -## PolkaVM - -PolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution. - -## Relay Chain - -Relay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another. - -## Rococo - -A [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead. - -## Runtime - -The runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function. - -## Slot - -A fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block. - -## Sovereign Account - -The unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem. - -The sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier. - -## SS58 Address Format - -A public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain - -The [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks - -## State Transition Function (STF) - -The logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime). - -## Storage Item - -[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime). -Learn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\_blank} reference document in the Polkadot SDK. - -## Substrate - -A flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\_blank}. - -## Transaction - -An [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}. - -## Transaction Era - -A definable period expressed as a range of block numbers during which a transaction can be included in a block. -Transaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero. - -## Trie (Patricia Merkle Tree) - -A data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set. - -In Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays. - -## Validator - -A validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance. - -## WebAssembly (Wasm) - -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. - -[Wasm](https://webassembly.org/){target=\_blank} can be compiled from many languages, including -the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state. - -## Weight - -A convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block. -Polkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware. - -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: - -- Block construction -- Network propagation -- Import and verification - -By defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements. - -## Westend - -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. - - ---- - -Page Title: Indexers - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md -- Canonical (HTML): https://docs.polkadot.com/parachains/integrations/indexers/ -- Summary: Discover blockchain indexers. Enhance data access, enable fast and complex queries, and optimize blockchain data for seamless app performance. - -# Indexers - -## The Challenge of Blockchain Data Access - -Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges: - -- Data is scattered and unorganized across the blockchain. -- Retrieving large datasets can take days or weeks to sync. -- Complex operations (like aggregations, averages, or cross-chain queries) require additional processing. -- Direct blockchain queries can impact dApp performance and responsiveness. - -## What is a Blockchain Indexer? - -A blockchain indexer is a specialized infrastructure tool that processes, organizes, and stores blockchain data in an optimized format for efficient querying. Think of it as a search engine for blockchain data that: - -- Continuously monitors the blockchain for new blocks and transactions. -- Processes and categorizes this data according to predefined schemas. -- Stores the processed data in an easily queryable database. -- Provides efficient APIs (typically [GraphQL](https://graphql.org/){target=\_blank}) for data retrieval. - -## Indexer Implementations - -
    - -- __Subsquid__ - - --- - - Subsquid is a data network that allows rapid and cost-efficient retrieval of blockchain data from 100+ chains using Subsquid's decentralized data lake and open-source SDK. In simple terms, Subsquid can be considered an ETL (extract, transform, and load) tool with a GraphQL server included. It enables comprehensive filtering, pagination, and even full-text search capabilities. Subsquid has native and full support for EVM and Substrate data, even within the same project. - - [:octicons-arrow-right-24: Reference](https://www.sqd.ai/){target=\_blank} - -- __Subquery__ - - --- - - SubQuery is a fast, flexible, and reliable open-source data decentralised infrastructure network that provides both RPC and indexed data to consumers worldwide. - It provides custom APIs for your web3 project across multiple supported chains. - - [:octicons-arrow-right-24: Reference](https://subquery.network/){target=\_blank} - -
    - - ---- - -Page Title: Install Polkadot SDK - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md -- Canonical (HTML): https://docs.polkadot.com/parachains/install-polkadot-sdk/ -- Summary: Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. - -# Install Polkadot SDK - -This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts: - -- **Installing dependencies**: Setting up Rust, required system packages, and development tools. -- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. - -Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. - -## Install Dependencies: macOS - -You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. - -### Before You Begin {: #before-you-begin-mac-os } - -Before you install Rust and set up your development environment on macOS, verify that your computer meets the following basic requirements: - -- Operating system version is 10.7 Lion or later. -- Processor speed of at least 2 GHz. Note that 3 GHz is recommended. -- Memory of at least 8 GB RAM. Note that 16 GB is recommended. -- Storage of at least 10 GB of available space. -- Broadband Internet connection. - -### Install Homebrew - -In most cases, you should use Homebrew to install and manage packages on macOS computers. If you don't already have Homebrew installed on your local computer, you should download and install it before continuing. - -To install Homebrew: - -1. Open the Terminal application. -2. Download and install Homebrew by running the following command: - - ```bash - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" - ``` - -3. Verify Homebrew has been successfully installed by running the following command: - - ```bash - brew --version - ``` - - The command displays output similar to the following: - -
    - brew --version - Homebrew 4.3.15 -
    - -### Support for Apple Silicon - -Protobuf must be installed before the build process can begin. To install it, run the following command: - -```bash -brew install protobuf -``` - -### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } - -Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `openssl`. - -To install `openssl` and the Rust toolchain on macOS: - -1. Open the Terminal application. -2. Ensure you have an updated version of Homebrew by running the following command: - - ```bash - brew update - ``` - -3. Install the `openssl` package by running the following command: - - ```bash - brew install openssl - ``` - -4. Download the `rustup` installation program and use it to install Rust by running the following command: - - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -5. Follow the prompts displayed to proceed with a default installation. -6. Update your current shell to include Cargo by running the following command: - - ```bash - source ~/.cargo/env - ``` - -7. Configure the Rust toolchain to default to the latest stable version by running the following commands: - - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` - -8. Install `cmake` using the following command: - - ```bash - brew install cmake - ``` - -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - -## Install Dependencies: Linux - -Rust supports most Linux distributions. Depending on the specific distribution and version of the operating system you use, you might need to add some software dependencies to your environment. In general, your development environment should include a linker or a C-compatible compiler, such as `clang`, and an appropriate integrated development environment (IDE). - -### Before You Begin {: #before-you-begin-linux } - -Check the documentation for your operating system for information about the installed packages and how to download and install any additional packages you might need. For example, if you use Ubuntu, you can use the Ubuntu Advanced Packaging Tool (`apt`) to install the `build-essential` package: - -```bash -sudo apt install build-essential -``` - -At a minimum, you need the following packages before you install Rust: - -```text -clang curl git make -``` - -Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `libssl-dev` or `openssl-devel`. - -### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } - -To install the Rust toolchain on Linux: - -1. Open a terminal shell. -2. Check the packages installed on the local computer by running the appropriate package management command for your Linux distribution. -3. Add any package dependencies you are missing to your local development environment by running the appropriate package management command for your Linux distribution: - - === "Ubuntu" - - ```bash - sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler - ``` - - === "Debian" - - ```sh - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` - - === "Arch" - - ```sh - pacman -Syu --needed --noconfirm curl git clang make protobuf - ``` - - === "Fedora" - - ```sh - sudo dnf update - sudo dnf install clang curl git openssl-devel make protobuf-compiler - ``` - - === "OpenSUSE" - - ```sh - sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf - ``` - - Remember that different distributions might use different package managers and bundle packages in different ways. For example, depending on your installation selections, Ubuntu Desktop and Ubuntu Server might have different packages and different requirements. However, the packages listed in the command-line examples are applicable to many common Linux distributions, including Debian, Linux Mint, MX Linux, and Elementary OS. - -4. Download the `rustup` installation program and use it to install Rust by running the following command: - - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -5. Follow the prompts displayed to proceed with a default installation. -6. Update your current shell to include Cargo by running the following command: - - ```bash - source $HOME/.cargo/env - ``` - -7. Verify your installation by running the following command: - - ```bash - rustc --version - ``` - -8. Configure the Rust toolchain to default to the latest stable version by running the following commands: - - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` - -9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - -## Install Dependencies: Windows (WSL) - -In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. - -However, suppose your local computer uses Microsoft Windows instead of a UNIX-based operating system. In that case, you can configure it with additional software to make it a suitable development environment for building Substrate-based blockchains. To prepare a development environment on a Microsoft Windows computer, you can use Windows Subsystem for Linux (WSL) to emulate a UNIX operating environment. - -### Before You Begin {: #before-you-begin-windows-wls } - -Before installing on Microsoft Windows, verify the following basic requirements: - -- You have a computer running a supported Microsoft Windows operating system: - - **For Windows desktop**: You must be running Microsoft Windows 10, version 2004 or later, or Microsoft Windows 11 to install WSL. - - **For Windows server**: You must be running Microsoft Windows Server 2019, or later, to install WSL on a server operating system. -- You have a good internet connection and access to a shell terminal on your local computer. - -### Set Up Windows Subsystem for Linux - -WSL enables you to emulate a Linux environment on a computer that uses the Windows operating system. The primary advantage of this approach for Substrate development is that you can use all of the code and command-line examples as described in the Substrate documentation. For example, you can run common commands—such as `ls` and `ps`—unmodified. By using WSL, you can avoid configuring a virtual machine image or a dual-boot operating system. - -To prepare a development environment using WSL: - -1. Check your Windows version and build number to see if WSL is enabled by default. - - If you have Microsoft Windows 10, version 2004 (Build 19041 and higher), or Microsoft Windows 11, WSL is available by default and you can continue to the next step. - - If you have an older version of Microsoft Windows installed, see the [WSL manual installation steps for older versions](https://learn.microsoft.com/en-us/windows/wsl/install-manual){target=\_blank}. If you are installing on an older version of Microsoft Windows, you can download and install WLS 2 if your computer has Windows 10, version 1903 or higher. - -2. Select **Windows PowerShell** or **Command Prompt** from the **Start** menu, right-click, then **Run as administrator**. - -3. In the PowerShell or Command Prompt terminal, run the following command: - - ```bash - wsl --install - ``` - - This command enables the required WSL 2 components that are part of the Windows operating system, downloads the latest Linux kernel, and installs the Ubuntu Linux distribution by default. - - If you want to review the other Linux distributions available, run the following command: - - ```bash - wsl --list --online - ``` - -4. After the distribution is downloaded, close the terminal. - -5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. - - Restarting the computer is required to start the installation of the Linux distribution. It can take a few minutes for the installation to complete after you restart. - - For more information about setting up WSL as a development environment, see the [Set up a WSL development environment](https://learn.microsoft.com/en-us/windows/wsl/setup/environment){target=\_blank} docs. - -### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } - -To install the Rust toolchain on WSL: - -1. Click the **Start** menu, then select **Ubuntu**. -2. Type a UNIX user name to create a user account. -3. Type a password for your UNIX user, then retype the password to confirm it. -4. Download the latest updates for the Ubuntu distribution using the Ubuntu Advanced Packaging Tool (`apt`) by running the following command: - - ```bash - sudo apt update - ``` - -5. Add the required packages for the Ubuntu distribution by running the following command: - - ```bash - sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler - ``` - -6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: - - ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - ``` - -7. Follow the prompts displayed to proceed with a default installation. - -8. Update your current shell to include Cargo by running the following command: - - ```bash - source ~/.cargo/env - ``` - -9. Verify your installation by running the following command: - - ```bash - rustc --version - ``` - -10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: - - ```bash - rustup default stable - rustup update - rustup target add wasm32-unknown-unknown - rustup component add rust-src - ``` - -11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - -## Build the Polkadot SDK - -After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. - -### Clone the Polkadot SDK - -1. Clone the Polkadot SDK repository: - - ```bash - git clone https://github.com/paritytech/polkadot-sdk.git - ``` - -2. Navigate into the project directory: - - ```bash - cd polkadot-sdk - ``` - -### Compile the Polkadot SDK - -Compile the entire Polkadot SDK repository to ensure your environment is properly configured: - -```bash -cargo build --release --locked -``` - -!!!note - This initial compilation will take significant time, depending on your machine specifications. It compiles all components of the Polkadot SDK to verify your toolchain is correctly configured. - -### Verify the Build - -Once the build completes successfully, verify the installation by checking the compiled binaries: - -```bash -ls target/release -``` - -You should see several binaries, including: - -- `polkadot`: The Polkadot relay chain node. -- `polkadot-parachain`: The parachain collator node. -- `polkadot-omni-node`:The omni node for running parachains. -- `substrate-node`: The kitchensink node with many pre-configured pallets. - -Verify the Polkadot binary works by checking its version: - -```bash -./target/release/polkadot --version -``` - -This should display version information similar to: - -```bash -polkadot 1.16.0-1234abcd567 -``` - -If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! - -## Optional: Run the Kitchensink Node - -The Polkadot SDK includes a feature-rich node called "kitchensink" located at `substrate/bin/node`. This node comes pre-configured with many pallets and features from the Polkadot SDK, making it an excellent reference for exploring capabilities and understanding how different components work together. - -!!!note - If you've already compiled the Polkadot SDK in the previous step, the `substrate-node` binary is already built and ready to use. You can skip directly to running the node. - -### Run the Kitchensink Node in Development Mode - -From the `polkadot-sdk` root directory, start the kitchensink node in development mode: - -```bash -./target/release/substrate-node --dev -``` - -The `--dev` flag enables development mode, which: - -- Runs a single-node development chain. -- Produces and finalizes blocks automatically. -- Uses pre-configured development accounts (Alice, Bob, etc.). -- Deletes all data when stopped, ensuring a clean state on restart. - - -You should see log output indicating the node is running and producing blocks, with increasing block numbers after `finalized`. - -### Interact with the Kitchensink Node - -The kitchensink node is accessible at `ws://localhost:9944`. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your browser to explore its features and connect to the local node. - -1. Click the network icon in the top left corner. -2. Scroll to **Development** and select **Local Node**. -3. Click **Switch** to connect to your local node. - -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) - -Once connected, the interface updates its color scheme to indicate a successful connection to the local node. - -![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) - -You can now explore the various pallets and features included in the kitchensink node, making it a valuable reference as you develop your own blockchain applications. - -To stop the node, press `Control-C` in the terminal. - -## Where to Go Next - -
    - -- __Get Started with Parachain Development__ - - --- - - Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. - - [:octicons-arrow-right-24: Get Started](/parachains/get-started/) - -
    - - ---- - -Page Title: Interoperability - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/interoperability/ -- Summary: Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. - -# Interoperability - -## Introduction - -Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions. - -Polkadot’s design ensures that blockchains can transcend their individual limitations by working together as part of a unified system. This cooperative architecture is what sets Polkadot apart in the blockchain landscape. - -## Why Interoperability Matters - -The blockchain ecosystem is inherently fragmented. Different blockchains excel in specialized domains such as finance, gaming, or supply chain management, but these chains function in isolation without interoperability. This lack of connectivity stifles the broader utility of blockchain technology. - -Interoperability solves this problem by enabling blockchains to: - -- **Collaborate across networks**: Chains can interact to share assets, functionality, and data, creating synergies that amplify their individual strengths. -- **Achieve greater scalability**: Specialized chains can offload tasks to others, optimizing performance and resource utilization. -- **Expand use-case potential**: Cross-chain applications can leverage features from multiple blockchains, unlocking novel user experiences and solutions. - -In the Polkadot ecosystem, interoperability transforms a collection of isolated chains into a cohesive, efficient network, pushing the boundaries of what blockchains can achieve together. - -## Key Mechanisms for Interoperability - -At the core of Polkadot's cross-chain collaboration are foundational technologies designed to break down barriers between networks. These mechanisms empower blockchains to communicate, share resources, and operate as a cohesive ecosystem. - -### Cross-Consensus Messaging (XCM): The Backbone of Communication - -Polkadot's Cross-Consensus Messaging (XCM) is the standard framework for interaction between parachains, relay chains, and, eventually, external blockchains. XCM provides a trustless, secure messaging format for exchanging assets, sharing data, and executing cross-chain operations. - -Through XCM, decentralized applications can: - -- Transfer tokens and other assets across chains. -- Coordinate complex workflows that span multiple blockchains. -- Enable seamless user experiences where underlying blockchain differences are invisible. -- XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem. - -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. - -### Bridges: Connecting External Networks - -While XCM enables interoperability within the Polkadot ecosystem, bridges extend this functionality to external blockchains such as Ethereum and Bitcoin. By connecting these networks, bridges allow Polkadot-based chains to access external liquidity, additional functionalities, and broader user bases. - -With bridges, developers and users gain the ability to: - -- Integrate external assets into Polkadot-based applications. -- Combine the strengths of Polkadot’s scalability with the liquidity of other networks. -- Facilitate accurate multi-chain applications that transcend ecosystem boundaries. - -For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. - -## The Polkadot Advantage - -Polkadot was purpose-built for interoperability. Unlike networks that add interoperability as an afterthought, Polkadot integrates it as a fundamental design principle. This approach offers several distinct advantages: - -- **Developer empowerment**: Polkadot’s interoperability tools allow developers to build applications that leverage multiple chains’ capabilities without added complexity. -- **Enhanced ecosystem collaboration**: Chains in Polkadot can focus on their unique strengths while contributing to the ecosystem’s overall growth. -- **Future-proofing blockchain**: By enabling seamless communication, Polkadot ensures its ecosystem can adapt to evolving demands and technologies. - -## Looking Ahead - -Polkadot’s vision of interoperability extends beyond technical functionality, representing a shift towards a more collaborative blockchain landscape. By enabling chains to work together, Polkadot fosters innovation, efficiency, and accessibility, paving the way for a decentralized future where blockchains are not isolated competitors but interconnected collaborators. - - ---- - -Page Title: Introduction to XCM - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md -- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ -- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. - -# Introduction to XCM - -## Introduction - -Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. - -With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. - -## Messaging Format - -XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. - -XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. - -## The Four Principles of XCM - -XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: - -- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. -- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. -- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. -- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. - -These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. - -## The XCM Tech Stack - -![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) - -The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. - -## Core Functionalities of XCM - -XCM enhances cross-consensus communication by introducing several powerful features: - -- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. -- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. -- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. - -The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. - -## XCM Example - -The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). - -```rust -let message = Xcm(vec![ - WithdrawAsset((Here, amount).into()), - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } -]); -``` - -The message consists of three instructions described as follows: - -- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. - - ```rust - WithdrawAsset((Here, amount).into()), - ``` - - - **`Here`**: The native parachain token. - - **`amount`**: The number of tokens that are transferred. - - The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. - -- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. - - ```rust - BuyExecution { - fees: (Here, amount).into(), - weight_limit: WeightLimit::Unlimited - }, - ``` - - - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. - - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. - -- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. - - ```rust - DepositAsset { - assets: All.into(), - beneficiary: MultiLocation { - parents: 0, - interior: Junction::AccountId32 { - network: None, - id: BOB.clone().into() - }.into(), - }.into() - } - ``` - - - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. - -This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - -## Overview - -XCM revolutionizes cross-chain communication by enabling use cases such as: - -- Token transfers between blockchains. -- Asset locking for cross-chain smart contract interactions. -- Remote execution of functions on other blockchains. - -These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - - ---- - -Page Title: JSON-RPC APIs - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ -- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. - -# JSON-RPC APIs - -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction - -Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. - -This guide uses the Polkadot Hub TestNet endpoint: - -```text -https://testnet-passet-hub-eth-rpc.polkadot.io -``` - -## Available Methods - -### eth_accounts - -Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_accounts" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_accounts", - "params":[], - "id":1 -}' -``` - ---- - -### eth_blockNumber - -Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_blockNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_blockNumber", - "params":[], - "id":1 -}' -``` - ---- - -### eth_call - -Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction call object. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_call" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_call", - "params":[{ - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_CALL" - }, "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_chainId - -Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_chainId" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_chainId", - "params":[], - "id":1 -}' -``` - ---- - -### eth_estimateGas - -Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction call object. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_estimateGas" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_estimateGas", - "params":[{ - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_FUNCTION_CALL" - }], - "id":1 -}' -``` - -Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. - ---- - -### eth_gasPrice - -Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_gasPrice" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_gasPrice", - "params":[], - "id":1 -}' -``` - ---- - -### eth_getBalance - -Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_getBalance" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBalance", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getBlockByHash - -Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. - -**Parameters**: - -- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. - -**Example**: - -```bash title="eth_getBlockByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockByHash", - "params":["INSERT_BLOCK_HASH", INSERT_BOOLEAN], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values. - ---- - -### eth_getBlockByNumber - -Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. - -**Parameters**: - -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. - -**Example**: - -```bash title="eth_getBlockByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockByNumber", - "params":["INSERT_BLOCK_VALUE", INSERT_BOOLEAN], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values. - ---- - -### eth_getBlockTransactionCountByNumber - -Returns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\_blank}. - -**Parameters**: - -- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - -**Example**: - -```bash title="eth_getBlockTransactionCountByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockTransactionCountByNumber", - "params":["INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getBlockTransactionCountByHash - -Returns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}. - -**Parameters**: - -- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getBlockTransactionCountByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getBlockTransactionCountByHash", - "params":["INSERT_BLOCK_HASH"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. - ---- - -### eth_getCode - -Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - -**Example**: - -```bash title="eth_getCode" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getCode", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getLogs - -Returns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}. - -**Parameters**: - -- **`filter` ++"object"++**: The filter object. - - **`fromBlock` ++"string"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - - **`toBlock` ++"string"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. - - **`address` ++"string" or "array of strings"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`topics` ++"array of strings"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string or an array of such strings (meaning OR). - - **`blockhash` ++"string"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getLogs" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getLogs", - "params":[{ - "fromBlock": "latest", - "toBlock": "latest" - }], - "id":1 -}' -``` - ---- - -### eth_getStorageAt - -Returns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`storageKey` ++"string"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - -**Example**: - -```bash title="eth_getStorageAt" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getStorageAt", - "params":["INSERT_ADDRESS", "INSERT_STORAGE_KEY", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getTransactionCount - -Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}. - -**Parameters**: - -- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - -**Example**: - -```bash title="eth_getTransactionCount" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionCount", - "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ---- - -### eth_getTransactionByHash - -Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. - -**Parameters**: - -- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionByHash" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByHash", - "params":["INSERT_TRANSACTION_HASH"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. - ---- - -### eth_getTransactionByBlockNumberAndIndex - -Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. - -**Parameters**: - -- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionByBlockNumberAndIndex" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByBlockNumberAndIndex", - "params":["INSERT_BLOCK_VALUE", "INSERT_TRANSACTION_INDEX"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. - ---- - -### eth_getTransactionByBlockHashAndIndex - -Returns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}. - -**Parameters**: - -- **`blockHash` ++"string"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionByBlockHashAndIndex" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionByBlockHashAndIndex", - "params":["INSERT_BLOCK_HASH", "INSERT_TRANSACTION_INDEX"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. - ---- - -### eth_getTransactionReceipt - -Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. - -**Parameters**: - -- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_getTransactionReceipt" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_getTransactionReceipt", - "params":["INSERT_TRANSACTION_HASH"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. - ---- - -### eth_maxPriorityFeePerGas - -Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. - -**Parameters**: - -None. - -**Example**: - -```bash title="eth_maxPriorityFeePerGas" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_maxPriorityFeePerGas", - "params":[], - "id":1 -}' -``` - ---- - -### eth_sendRawTransaction - -Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. - -**Parameters**: - -- **`callData` ++"string"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_sendRawTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_sendRawTransaction", - "params":["INSERT_CALL_DATA"], - "id":1 -}' -``` - -Ensure to replace the `INSERT_CALL_DATA` with the proper values. - ---- - -### eth_sendTransaction - -Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. - -**Parameters**: - -- **`transaction` ++"object"++**: The transaction object. - - **`from` ++"string"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`to` ++"string"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`data` ++"string"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`nonce` ++"string"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - -**Example**: - -```bash title="eth_sendTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_sendTransaction", - "params":[{ - "from": "INSERT_SENDER_ADDRESS", - "to": "INSERT_RECIPIENT_ADDRESS", - "gas": "INSERT_GAS_LIMIT", - "gasPrice": "INSERT_GAS_PRICE", - "value": "INSERT_VALUE", - "input": "INSERT_INPUT_DATA", - "nonce": "INSERT_NONCE" - }], - "id":1 -}' -``` +5. Configure and execute the deployment: -Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values. + ```js title="scripts/deploy.js" + const providerConfig = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; ---- + const mnemonic = 'INSERT_MNEMONIC'; -### eth_syncing + deployContract('Storage', mnemonic, providerConfig); + ``` -Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. + !!! note + A mnemonic (seed phrase) is a series of words that can generate multiple private keys and their corresponding addresses. It's used here to derive the wallet that will sign and pay for the deployment transaction. **Always keep your mnemonic secure and never share it publicly**. -**Parameters**: + Ensure to replace the `INSERT_MNEMONIC` placeholder with your actual mnemonic. -None. +??? code "View complete script" -**Example**: + ```js title="scripts/deploy.js" + // Deploy an EVM-compatible smart contract using ethers.js + const { writeFileSync, existsSync, readFileSync } = require('fs'); + const { join } = require('path'); + const { ethers, JsonRpcProvider } = require('ethers'); -```bash title="eth_syncing" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"eth_syncing", - "params":[], - "id":1 -}' -``` + const codegenDir = join(__dirname); ---- + // Creates an Ethereum provider with specified RPC URL and chain details + const createProvider = (rpcUrl, chainId, chainName) => { + const provider = new JsonRpcProvider(rpcUrl, { + chainId: chainId, + name: chainName, + }); + return provider; + }; -### net_listening + // Reads and parses the ABI file for a given contract + const getAbi = (contractName) => { + try { + return JSON.parse( + readFileSync(join(codegenDir, `${contractName}.json`), 'utf8'), + ); + } catch (error) { + console.error( + `Could not find ABI for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; -Returns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\_blank}. + // Reads the compiled bytecode for a given contract + const getByteCode = (contractName) => { + try { + const bytecodePath = join( + codegenDir, + '../contracts', + `${contractName}.polkavm`, + ); + return `0x${readFileSync(bytecodePath).toString('hex')}`; + } catch (error) { + console.error( + `Could not find bytecode for contract ${contractName}:`, + error.message, + ); + throw error; + } + }; -**Parameters**: + const deployContract = async (contractName, mnemonic, providerConfig) => { + console.log(`Deploying ${contractName}...`); -None. + try { + // Step 1: Set up provider and wallet + const provider = createProvider( + providerConfig.rpc, + providerConfig.chainId, + providerConfig.name, + ); + const walletMnemonic = ethers.Wallet.fromPhrase(mnemonic); + const wallet = walletMnemonic.connect(provider); -**Example**: + // Step 2: Create and deploy the contract + const factory = new ethers.ContractFactory( + getAbi(contractName), + getByteCode(contractName), + wallet, + ); + const contract = await factory.deploy(); + await contract.waitForDeployment(); -```bash title="net_listening" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_listening", - "params":[], - "id":1 -}' -``` + // Step 3: Save deployment information + const address = await contract.getAddress(); + console.log(`Contract ${contractName} deployed at: ${address}`); ---- + const addressesFile = join(codegenDir, 'contract-address.json'); + const addresses = existsSync(addressesFile) + ? JSON.parse(readFileSync(addressesFile, 'utf8')) + : {}; + addresses[contractName] = address; + writeFileSync(addressesFile, JSON.stringify(addresses, null, 2), 'utf8'); + } catch (error) { + console.error(`Failed to deploy contract ${contractName}:`, error); + } + }; -### net_peerCount + const providerConfig = { + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, + name: 'polkadot-hub-testnet', + }; -Returns the number of peers currently connected to the client. + const mnemonic = 'INSERT_MNEMONIC'; -**Parameters**: + deployContract('Storage', mnemonic, providerConfig); -None. + ``` -**Example**: +To run the script, execute the following command: -```bash title="net_peerCount" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_peerCount", - "params":[], - "id":1 -}' +```bash +node deploy ``` ---- +After running this script, your contract will be deployed to Polkadot Hub, and its address will be saved in `contract-address.json` within your project directory. You can use this address for future contract interactions. -### net_version +## Interact with the Contract -Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. +Once the contract is deployed, you can interact with it by calling its functions. For example, to set a number, read it and then modify that number by its double, you can create a file named `checkStorage.js` in the root of your project and add the following code: -**Parameters**: +```js title="scripts/checkStorage.js" +const { ethers } = require('ethers'); +const { readFileSync } = require('fs'); +const { join } = require('path'); -None. +const createProvider = (providerConfig) => { + return new ethers.JsonRpcProvider(providerConfig.rpc, { + chainId: providerConfig.chainId, + name: providerConfig.name, + }); +}; -**Example**: +const createWallet = (mnemonic, provider) => { + return ethers.Wallet.fromPhrase(mnemonic).connect(provider); +}; -```bash title="net_version" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"net_version", - "params":[], - "id":1 -}' -``` +const loadContractAbi = (contractName, directory = __dirname) => { + const contractPath = join(directory, `${contractName}.json`); + const contractJson = JSON.parse(readFileSync(contractPath, 'utf8')); + return contractJson.abi || contractJson; // Depending on JSON structure +}; ---- +const createContract = (contractAddress, abi, wallet) => { + return new ethers.Contract(contractAddress, abi, wallet); +}; -### system_health +const interactWithStorageContract = async ( + contractName, + contractAddress, + mnemonic, + providerConfig, + numberToSet, +) => { + try { + console.log(`Setting new number in Storage contract: ${numberToSet}`); -Returns information about the health of the system. + // Create provider and wallet + const provider = createProvider(providerConfig); + const wallet = createWallet(mnemonic, provider); -**Parameters**: + // Load the contract ABI and create the contract instance + const abi = loadContractAbi(contractName); + const contract = createContract(contractAddress, abi, wallet); -None. + // Send a transaction to set the stored number + const tx1 = await contract.setNumber(numberToSet); + await tx1.wait(); // Wait for the transaction to be mined + console.log(`Number successfully set to ${numberToSet}`); -**Example**: + // Retrieve the updated number + const storedNumber = await contract.storedNumber(); + console.log(`Retrieved stored number:`, storedNumber.toString()); + + // Send a transaction to set the stored number + const tx2 = await contract.setNumber(numberToSet * 2); + await tx2.wait(); // Wait for the transaction to be mined + console.log(`Number successfully set to ${numberToSet * 2}`); + + // Retrieve the updated number + const updatedNumber = await contract.storedNumber(); + console.log(`Retrieved stored number:`, updatedNumber.toString()); + } catch (error) { + console.error('Error interacting with Storage contract:', error.message); + } +}; + +const providerConfig = { + name: 'asset-hub-smart-contracts', + rpc: 'https://testnet-passet-hub-eth-rpc.polkadot.io', + chainId: 420420422, +}; + +const mnemonic = 'INSERT_MNEMONIC'; +const contractName = 'Storage'; +const contractAddress = 'INSERT_CONTRACT_ADDRESS'; +const newNumber = 42; + +interactWithStorageContract( + contractName, + contractAddress, + mnemonic, + providerConfig, + newNumber, +); -```bash title="system_health" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"system_health", - "params":[], - "id":1 -}' ``` ---- +Ensure you replace the `INSERT_MNEMONIC`, `INSERT_CONTRACT_ADDRESS`, and `INSERT_ADDRESS_TO_CHECK` placeholders with actual values. Also, ensure the contract ABI file (`Storage.json`) is correctly referenced. -### web3_clientVersion +To interact with the contract, run: -Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. +```bash +node checkStorage +``` -**Parameters**: +## Where to Go Next -None. +Now that you have the foundational knowledge to use Ethers.js with Polkadot Hub, you can: -**Example**: +- **Dive into Ethers.js utilities**: Discover additional Ethers.js features, such as wallet management, signing messages, etc. +- **Implement batch transactions**: Use Ethers.js to execute batch transactions for efficient multi-step contract interactions. +- **Build scalable applications**: Combine Ethers.js with frameworks like [`Next.js`](https://nextjs.org/docs){target=\_blank} or [`Node.js`](https://nodejs.org/en){target=\_blank} to create full-stack decentralized applications (dApps). -```bash title="web3_clientVersion" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"web3_clientVersion", - "params":[], - "id":1 -}' -``` --- -### debug_traceBlockByNumber - -Traces a block's execution by its number and returns a detailed execution trace for each transaction. +Page Title: Deploy Contracts Using Remix IDE -**Parameters**: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-deploy-a-contract.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/dev-environments/remix/deploy-a-contract/ +- Summary: Learn how to deploy smart contracts to the Polkadot Hub network and interact with them using the Remix IDE and wallet providers, covering deployment and state. -- **`blockValue` ++"string"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`options` ++"object"++**: (Optional) An object containing tracer options. - - **`tracer` ++"string"++**: The name of the tracer to use (e.g., `"callTracer"`, `"opTracer"`). - - Other tracer-specific options may be supported. +# Deploy Smart Contracts Using Remix IDE -**Example**: +## Overview -```bash title="debug_traceBlockByNumber" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceBlockByNumber", - "params":["INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], - "id":1 -}' -``` +After compiling your smart contract in Remix IDE, the next step is to deploy it to the Polkadot Hub network. This guide will walk you through the deployment process using a wallet provider and show you how to interact with your deployed contracts directly from the Remix interface. -Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. +## Prerequisites ---- +Before deploying your contract, ensure you have: -### debug_traceTransaction +- Completed the [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} and have a compiled contract ready. +- A compatible wallet extension installed (e.g., [MetaMask](https://metamask.io/){target=\_blank} or [Talisman](https://www.talisman.xyz/){target=\_blank}). +- Your wallet connected to the Polkadot Hub network. Check the [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} guide for more information. +- Test tokens in your wallet to cover deployment and transaction fees (available from the [Polkadot faucet](/smart-contracts/faucet/){target=\_blank}). -Traces the execution of a single transaction by its hash and returns a detailed execution trace. +## Deploy Contracts -**Parameters**: +The steps to use Remix IDE to deploy a contract to Polkadot Hub are as follows: -- **`transactionHash` ++"string"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). +1. Navigate to [Remix](https://remix.ethereum.org/){target=\_blank} in your web browser. +2. Locate the **Deploy & Run Transactions** tab. +3. Select the **Environment** dropdown. +4. Select **Browser Extension**. +5. Select the **Injected Provider - MetaMask** option. +6. Click the **Deploy** button and then click **Confirm** in the wallet popup. -**Example**: +Once your contract is deployed successfully, you will see the deployment confirmation in the Remix terminal. -```bash title="debug_traceTransaction" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceTransaction", - "params":["INSERT_TRANSACTION_HASH", {"tracer": "callTracer"}], - "id":1 -}' -``` +![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-1.gif) -Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. +## Interact with Contracts ---- +Deployed contracts appear in the **Deployed/Unpinned Contracts** section. Follow these steps to interact with the deployed contract: -### debug_traceCall +1. Expand the contract to view available methods. -Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. + !!! tip + Pin your frequently used contracts to the **Pinned Contracts** section for easy access. -**Parameters**: +2. Select any of the exposed methods to interact with the contract. -- **`transaction` ++"object"++**: The transaction call object, similar to `eth_call` parameters. - - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). + You can use these methods to interact with your deployed contract by reading or writing to its state. Remix IDE uses a color-coding scheme for method buttons to help differentiate between types of available methods as follows: -**Example**: + - **Blue buttons**: indicate `view` or `pure` functions which read state only. Interactions do not create a new transaction and do not incur gas fees. + - **Orange buttons**: label `non-payable` functions which change contract state but don't accept any value (ETH or other tokens) being sent with the transaction. + - **Red buttons**: designate `payable` functions which create a transaction and can accept a value (ETH or other tokens) to send with the transaction. -```bash title="debug_traceCall" -curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ --H "Content-Type: application/json" \ ---data '{ - "jsonrpc":"2.0", - "method":"debug_traceCall", - "params":[{ - "from": "INSERT_SENDER_ADDRESS", - "to": "INSERT_RECIPIENT_ADDRESS", - "data": "INSERT_ENCODED_CALL" - }, "INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], - "id":1 -}' -``` +If you deployed the `Counter.sol` contract from [Remix IDE setup](/smart-contracts/dev-environments/remix/get-started/){target=\_blank}, you can try interacting with the exposed methods as follows: -Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value. +1. Select the **GetCount** button to read the current count value. ---- +2. Select the **Increment** button to increment the count value. -## Response Format +3. Submit the transaction and click the **Confirm** button in the wallet pop-up. -All responses follow the standard JSON-RPC 2.0 format: +Once the transaction is confirmed, you will see the updated count value in the Remix terminal. -```json -{ - "jsonrpc": "2.0", - "id": 1, - "result": ... // The return value varies by method -} -``` +![](/images/smart-contracts/dev-environments/remix/deploy-a-contract/remix-2.gif) -## Error Handling +## Where to Go Next -If an error occurs, the response will include an error object: +You've successfully deployed and interacted with your smart contract on Polkadot Hub using Remix IDE. Continue enhancing your development workflow with these resources: -```json -{ - "jsonrpc": "2.0", - "id": 1, - "error": { - "code": -32000, - "message": "Error message here" - } -} -``` +
    ---- -Page Title: Light Clients +- Guide __Troubleshooting__ -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/light-clients/ -- Summary: Light clients enable secure and efficient blockchain interaction without running a full node. Learn everything you need to know about light clients on Polkadot. + --- -# Light Clients + Find solutions to common issues when working with Remix IDE. -## Introduction + [:octicons-arrow-right-24: Get Started](/smart-contracts/dev-environments/remix/troubleshooting-faq/) -Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes. +
    -This guide covers: -- What light clients are and how they work. -- Their advantages compared to full nodes and JSON-RPC. -- Available implementations in the Polkadot ecosystem. -- How to use light clients in your applications. +--- -Light clients are particularly valuable for resource-constrained environments and applications requiring secure, decentralized blockchain access without the overhead of maintaining full nodes. +Page Title: Deploying Uniswap V2 on Polkadot -!!!note "Light node or light client?" - The terms _light node_ and _light client_ are interchangeable. Both refer to a blockchain client that syncs without downloading the entire blockchain state. All nodes in a blockchain network are fundamentally clients, engaging in peer-to-peer communication. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/eth-dapps/uniswap-v2/ +- Summary: Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. -## Light Clients Workflow +# Deploy Uniswap V2 -Unlike JSON-RPC interfaces, where an application must maintain a list of providers or rely on a single node, light clients are not limited to or dependent on a single node. They use cryptographic proofs to verify the blockchain's state, ensuring it is up-to-date and accurate. By verifying only block headers, light clients avoid syncing the entire state, making them ideal for resource-constrained environments. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -```mermaid -flowchart LR -DAPP([dApp])-- Query Account Info -->LC([Light Client]) -LC -- Request --> FN(((Full Node))) -LC -- Response --> DAPP -FN -- Response (validated via Merkle proof) --> LC -``` +Decentralized exchanges (DEXs) are a cornerstone of the DeFi ecosystem, allowing for permissionless token swaps without intermediaries. [Uniswap V2](https://docs.uniswap.org/contracts/v2/overview){target=\_blank}, with its Automated Market Maker (AMM) model, revolutionized DEXs by enabling liquidity provision for any ERC-20 token pair. -In the diagram above, the decentralized application queries on-chain account information through the light client. The light client runs as part of the application and requires minimal memory and computational resources. It uses Merkle proofs to verify the state retrieved from a full node in a trust-minimized manner. Polkadot-compatible light clients utilize [warp syncing](https://spec.polkadot.network/sect-lightclient#sect-sync-warp-lightclient){target=\_blank}, which downloads only block headers. +This tutorial will guide you through how Uniswap V2 works so you can take advantage of it in your projects deployed to Polkadot Hub. By understanding these contracts, you'll gain hands-on experience with one of the most influential DeFi protocols and understand how it functions across blockchain ecosystems. -Light clients can quickly verify the blockchain's state, including [GRANDPA finality](/polkadot-protocol/glossary#grandpa){target=\_blank} justifications. +## Prerequisites -!!!note "What does it mean to be trust-minimized?" - _Trust-minimized_ means that the light client does not need to fully trust the full node from which it retrieves the state. This is achieved through the use of Merkle proofs, which allow the light client to verify the correctness of the state by checking the Merkle tree root. +Before starting, make sure you have: -## JSON-RPC and Light Client Comparison +- Node.js (v16.0.0 or later) and npm installed. +- Basic understanding of Solidity and JavaScript. +- Familiarity with [`hardhat-polkadot`](/smart-contracts/dev-environments/hardhat/get-started/){target=\_blank} development environment. +- Some PAS test tokens to cover transaction fees (obtained from the [Polkadot faucet](https://faucet.polkadot.io/?parachain=1111){target=\_blank}). +- Basic understanding of how AMMs and liquidity pools work. -Another common method of communication between a user interface (UI) and a node is through the JSON-RPC protocol. Generally, the UI retrieves information from the node, fetches network or [pallet](/polkadot-protocol/glossary#pallet){target=\_blank} data, and interacts with the blockchain. This is typically done in one of two ways: +## Set Up the Project -- **User-controlled nodes**: The UI connects to a node client installed on the user's machine. - - These nodes are secure, but installation and maintenance can be inconvenient. -- **Publicly accessible nodes**: The UI connects to a third-party-owned publicly accessible node client. - - These nodes are convenient but centralized and less secure. Applications must maintain a list of backup nodes in case the primary node becomes unavailable. +Let's start by cloning the Uniswap V2 project: -While light clients still communicate with [full nodes](/polkadot-protocol/glossary#full-node), they offer significant advantages for applications requiring a secure alternative to running a full node: +1. Clone the Uniswap V2 repository: -| Full Node | Light Client | -| :---------------------------------------------------------------------------------------------: | :------------------------------------------------------------: | -| Fully verifies all blocks of the chain | Verifies only the authenticity of blocks | -| Stores previous block data and the chain's storage in a database | Does not require a database | -| Installation, maintenance, and execution are resource-intensive and require technical expertise | No installation is typically included as part of the application | + ``` + git clone https://github.com/polkadot-developers/polkavm-hardhat-examples.git -b v0.0.6 + cd polkavm-hardhat-examples/uniswap-v2-polkadot/ + ``` -## Using Light Clients +2. Install the required dependencies: -The [`smoldot`](https://github.com/smol-dot/smoldot){target=\_blank} client is the cornerstone of light client implementation for Polkadot SDK-based chains. It provides the primitives needed to build light clients and is also integrated into libraries such as [PAPI](#papi-light-client-support). + ```bash + npm install + ``` -### PAPI Light Client Support +3. Update the `hardhat.config.js` file so the paths for the Substrate node and the ETH-RPC adapter match with the paths on your machine. For more info, check the [Testing your Contract](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} section in the Hardhat guide. -The [Polkadot API (PAPI)](/develop/toolkit/api-libraries/papi){target=\_blank} library natively supports light client configurations powered by [`smoldot`](https://github.com/smol-dot/smoldot){target=\_blank}. This allows developers to connect to multiple chains simultaneously using a light client. + ```js title="hardhat.config.js" + hardhat: { + polkavm: true, + nodeConfig: { + nodeBinaryPath: '../bin/substrate-node', + rpcPort: 8000, + dev: true, + }, + adapterConfig: { + adapterBinaryPath: '../bin/eth-rpc', + dev: true, + }, + }, + ``` -### Substrate Connect - Browser Extension +4. Create a `.env` file in your project root to store your private keys (you can use as an example the `env.example` file): -The [Substrate Connect browser extension](https://www.npmjs.com/package/@substrate/connect-extension-protocol){target=\_blank} enables end-users to interact with applications connected to multiple blockchains or to connect their own blockchains to supported applications. + ```text title=".env" + LOCAL_PRIV_KEY="INSERT_LOCAL_PRIVATE_KEY" + AH_PRIV_KEY="INSERT_AH_PRIVATE_KEY" + ``` -Establishing a sufficient number of peers can be challenging due to browser limitations on WebSocket connections from HTTPS pages, as many nodes require TLS. The Substrate Connect browser extension addresses this limitation by keeping chains synced in the background, enabling faster application performance. + Ensure to replace `"INSERT_LOCAL_PRIVATE_KEY"` with a private key available in the local environment (you can get them from this [file](https://github.com/paritytech/hardhat-polkadot/blob/main/packages/hardhat-polkadot-node/src/constants.ts#L22){target=\_blank}). And `"INSERT_AH_PRIVATE_KEY"` with the account's private key you want to use to deploy the contracts. You can get this by exporting the private key from your wallet (e.g., MetaMask). -Substrate Connect automatically detects whether the user has the extension installed. If not, an in-page Wasm light client is created for them. + !!!warning + Keep your private key safe, and never share it with anyone. If it is compromised, your funds can be stolen. -## Resources +5. Compile the contracts: -- [What is a light client and why you should care?](https://medium.com/paritytech/what-is-a-light-client-and-why-you-should-care-75f813ae2670){target=\_blank} -- [Introducing Substrate Connect: Browser-Based Light Clients for Connecting to Substrate Chains](https://www.parity.io/blog/introducing-substrate-connect){target=\_blank} -- [Substrate Connect GitHub Repository](https://github.com/paritytech/substrate-connect/tree/master/projects/extension){target=\_blank} -- [Light Clients - Polkadot Specification](https://spec.polkadot.network/sect-lightclient){target=\_blank} + ```bash + npx hardhat compile + ``` +If the compilation is successful, you should see the following output: ---- +
    + npx hardhat compile + Compiling 12 Solidity files + Successfully compiled 12 Solidity files +
    -Page Title: Networks +After running the above command, you should see the compiled contracts in the `artifacts-pvm` directory. This directory contains the ABI and bytecode of your contracts. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/networks/ -- Summary: Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. +## Understanding Uniswap V2 Architecture -# Networks +Before interacting with the contracts, it's essential to understand the core architecture that powers Uniswap V2. This model forms the basis of nearly every modern DEX implementation and operates under automated market making, token pair liquidity pools, and deterministic pricing principles. -## Introduction +At the heart of Uniswap V2 lies a simple but powerful system composed of two major smart contracts: -The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's various networks and explain how they fit into the development workflow. +- **Factory contract**: The factory acts as a registry and creator of new trading pairs. When two ERC-20 tokens are to be traded, the Factory contract is responsible for generating a new Pair contract that will manage that specific token pair’s liquidity pool. It keeps track of all deployed pairs and ensures uniqueness—no duplicate pools can exist for the same token combination. +- **Pair contract**: Each pair contract is a decentralized liquidity pool that holds reserves of two ERC-20 tokens. These contracts implement the core logic of the AMM, maintaining a constant product invariant (x \* y = k) to facilitate swaps and price determination. Users can contribute tokens to these pools in return for LP (liquidity provider) tokens, which represent their proportional share of the reserves. -## Network Overview +This minimal architecture enables Uniswap to be highly modular, trustless, and extensible. By distributing responsibilities across these components, developers, and users can engage with the protocol in a composable and predictable manner, making it an ideal foundation for DEX functionality across ecosystems, including Polkadot Hub. -Polkadot's development process is structured to ensure new features and upgrades are rigorously tested before being deployed on live production networks. The progression follows a well-defined path, starting from local environments and advancing through TestNets, ultimately reaching the Polkadot MainNet. The diagram below outlines the typical progression of the Polkadot development cycle: +The project scaffolding is as follows: -``` mermaid -flowchart LR - id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] - id1[Local] --> id3[Paseo] --> id5[Polkadot] +```bash +uniswap-V2-polkadot +├── bin/ +├── contracts/ +│ ├── interfaces/ +│ │ ├── IERC20.sol +│ │ ├── IUniswapV2Callee.sol +│ │ ├── IUniswapV2ERC20.sol +│ │ ├── IUniswapV2Factory.sol +│ │ └── IUniswapV2Pair.sol +│ ├── libraries/ +│ │ ├── Math.sol +│ │ ├── SafeMath.sol +│ │ └── UQ112x112.sol +│ ├── test/ +│ │ └── ERC20.sol +│ ├── UniswapV2ERC20.sol +│ ├── UniswapV2Factory.sol +│ └── UniswapV2Pair.sol +├── ignition/ +├── scripts/ +│ └── deploy.js +├── node_modules/ +├── test/ +│ ├── shared/ +│ │ ├── fixtures.js +│ │ └── utilities.js +│ ├── UniswapV2ERC20.js +│ ├── UniswapV2Factory.js +│ └── UniswapV2Pair.js +├── .env.example +├── .gitignore +├── hardhat.config.js +├── package.json +└── README.md ``` -This flow ensures developers can thoroughly test and iterate without risking real tokens or affecting production networks. Testing tools like [Chopsticks](#chopsticks) and various TestNets make it easier to experiment safely before releasing to production. - -A typical journey through the Polkadot core protocol development process might look like this: - -1. **Local development node**: Development starts in a local environment, where developers can create, test, and iterate on upgrades or new features using a local development node. This stage allows rapid experimentation in an isolated setup without any external dependencies. - -2. **Westend**: After testing locally, upgrades are deployed to [Westend](#westend), Polkadot's primary TestNet. Westend simulates real-world conditions without using real tokens, making it the ideal place for rigorous feature testing before moving on to production networks. - -3. **Kusama**: Once features have passed extensive testing on Westend, they move to Kusama, Polkadot's experimental and fast-moving "canary" network. Kusama operates as a high-fidelity testing ground with actual economic incentives, giving developers insights into how their features will perform in a real-world environment. - -4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network. - - In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. - -5. **Paseo**: For parachain and dApp developers, Paseo serves as a community-run TestNet that mirrors Polkadot's runtime. Like Westend for core protocol development, Paseo provides a testing ground for parachain development without affecting live networks. - -!!!note - The Rococo TestNet deprecation date was October 14, 2024. Teams should use Westend for Polkadot protocol and feature testing and Paseo for chain development-related testing. - -## Polkadot Development Networks +## Test the Contracts -Development and testing are crucial to building robust dApps and parachains and performing network upgrades within the Polkadot ecosystem. To achieve this, developers can leverage various networks and tools that provide a risk-free environment for experimentation and validation before deploying features to live networks. These networks help avoid the costs and risks associated with real tokens, enabling testing for functionalities like governance, cross-chain messaging, and runtime upgrades. +You can run the provided test suite to ensure the contracts are working as expected. The tests cover various scenarios, including creating pairs, adding liquidity, and executing swaps. -## Kusama Network +To test it locally, you can run the following commands: -Kusama is the experimental version of Polkadot, designed for developers who want to move quickly and test their applications in a real-world environment with economic incentives. Kusama serves as a production-grade testing ground where developers can deploy features and upgrades with the pressure of game theory and economics in mind. It mirrors Polkadot but operates as a more flexible space for innovation. +1. Spawn a local node for testing: -The native token for Kusama is KSM. For more information about KSM, visit the [Native Assets](https://wiki.polkadot.com/kusama/kusama-getting-started/){target=\_blank} page. + ```bash + npx hardhat node + ``` -## Test Networks + This command will spawn a local Substrate node along with the ETH-RPC adapter. The node will be available at `ws://127.0.0.1:8000` and the ETH-RPC adapter at `http://localhost:8545`. -The following test networks provide controlled environments for testing upgrades and new features. TestNet tokens are available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}. +2. In a new terminal, run the tests: -### Westend + ```bash + npx hardhat test --network localNode + ``` -Westend is Polkadot's primary permanent TestNet. Unlike temporary test networks, Westend is not reset to the genesis block, making it an ongoing environment for testing Polkadot core features. Managed by Parity Technologies, Westend ensures that developers can test features in a real-world simulation without using actual tokens. +The result should look like this: -The native token for Westend is WND. More details about WND can be found on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_2){target=\_blank} page. +
    + npx hardhat test --network localNode + Compiling 12 Solidity files + Successfully compiled 12 Solidity files + + UniswapV2ERC20 + ✔ name, symbol, decimals, totalSupply, balanceOf, DOMAIN_SEPARATOR, PERMIT_TYPEHASH (44ms) + ✔ approve (5128ms) + ✔ transfer (5133ms) + ✔ transfer:fail + ✔ transferFrom (6270ms) + ✔ transferFrom:max (6306ms) + + UniswapV2Factory + ✔ feeTo, feeToSetter, allPairsLength + ✔ createPair (176ms) + ✔ createPair:reverse (1224ms) + ✔ setFeeTo (1138ms) + ✔ setFeeToSetter (1125ms) + + UniswapV2Pair + ✔ mint (11425ms) + ✔ getInputPrice:0 (12590ms) + ✔ getInputPrice:1 (17600ms) + ✔ getInputPrice:2 (17618ms) + ✔ getInputPrice:3 (17704ms) + ✔ getInputPrice:4 (17649ms) + ✔ getInputPrice:5 (17594ms) + ✔ getInputPrice:6 (13643ms) + ✔ optimistic:0 (17647ms) + ✔ optimistic:1 (17946ms) + ✔ optimistic:2 (17657ms) + ✔ optimistic:3 (21625ms) + ✔ swap:token0 (12665ms) + ✔ swap:token1 (17631ms) + ✔ burn (17690ms) + ✔ feeTo:off (23900ms) + ✔ feeTo:on (24991ms) + + 28 passing (12m) +
    -### Paseo +## Deploy the Contracts -[Paseo](https://github.com/paseo-network){target=\_blank} is a community-managed TestNet designed for parachain and dApp developers. It mirrors Polkadot's runtime and is maintained by Polkadot community members. Paseo provides a dedicated space for parachain developers to test their applications in a Polkadot-like environment without the risks associated with live networks. +After successfully testing the contracts, you can deploy them to the local node or Polkadot Hub. The deployment script is located in the `scripts` directory and is named `deploy.js`. This script deploys the `Factory` and `Pair` contracts to the network. -The native token for Paseo is PAS. Additional information on PAS is available on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_1){target=\_blank} page. +To deploy the contracts, run the following command: -## Local Test Networks +```bash +npx hardhat run scripts/deploy.js --network localNode +``` -Local test networks are an essential part of the development cycle for blockchain developers using the Polkadot SDK. They allow for fast, iterative testing in controlled, private environments without connecting to public TestNets. Developers can quickly spin up local instances to experiment, debug, and validate their code before deploying to larger TestNets like Westend or Paseo. Two key tools for local network testing are Zombienet and Chopsticks. +This command deploys the contracts to your local blockchain for development and testing. If you want to deploy to Polkadot Hub, you can use the following command: -### Zombienet +```bash +npx hardhat run scripts/deploy.js --network passetHub +``` -[Zombienet](https://github.com/paritytech/zombienet){target=\_blank} is a flexible testing framework for Polkadot SDK-based blockchains. It enables developers to create and manage ephemeral, short-lived networks. This feature makes Zombienet particularly useful for quick iterations, as it allows you to run multiple local networks concurrently, mimicking different runtime conditions. Whether you're developing a parachain or testing your custom blockchain logic, Zombienet gives you the tools to automate local testing. +The command above deploys to the actual Polkadot TestNet. It requires PAS test tokens, persists on the network, and operates under real network conditions. -Key features of Zombienet include: +The deployment script will output the addresses of the deployed contracts. Save these addresses, as you will need them to interact with the contracts. For example, the output should look like this: -- Creating dynamic, local networks with different configurations. -- Running parachains and relay chains in a simulated environment. -- Efficient testing of network components like cross-chain messaging and governance. +
    + npx hardhat run scripts/deploy.js --network localNode + Successfully compiled 12 Solidity files + Deploying contracts using 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac + Deploying UniswapV2ERC20... + ETH deployed to : 0x7acc1aC65892CF3547b1b0590066FB93199b430D + Deploying UniswapV2Factory... + Factory deployed to : 0x85b108660f47caDfAB9e0503104C08C1c96e0DA9 + Deploying UniswapV2Pair with JsonRpcProvider workaround... + Pair deployed to : 0xF0e46847c8bFD122C4b5EEE1D4494FF7C5FC5104 +
    -Zombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets. +## Conclusion -### Chopsticks +This tutorial guided you through deploying Uniswap V2 contracts to Polkadot Hub. This implementation brings the powerful AMM architecture to the Polkadot ecosystem, laying the foundation for the decentralized trading of ERC-20 token pairs. -[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\_blank} is a tool designed to create forks of Polkadot SDK-based blockchains, allowing developers to interact with network forks as part of their testing process. This capability makes Chopsticks a powerful option for testing upgrades, runtime changes, or cross-chain applications in a forked network environment. +By following this guide, you've gained practical experience with: -Key features of Chopsticks include: +- Setting up a Hardhat project for deploying to Polkadot Hub. +- Understanding the Uniswap V2 architecture. +- Testing Uniswap V2 contracts in a local environment. +- Deploying contracts to both local and testnet environments. -- Forking live Polkadot SDK-based blockchains for isolated testing. -- Simulating cross-chain messages in a private, controlled setup. -- Debugging network behavior by interacting with the fork in real-time. +To build on this foundation, you could extend this project by implementing functionality to create liquidity pools, execute token swaps, and build a user interface for interacting with your deployment. -Chopsticks provides a controlled environment for developers to safely explore the effects of runtime changes. It ensures that network behavior is tested and verified before upgrades are deployed to live networks. +This knowledge can be leveraged to build more complex DeFi applications or to integrate Uniswap V2 functionality into your existing projects on Polkadot. --- -Page Title: Node and Runtime +Page Title: Dual Virtual Machine Stack -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/node-and-runtime/ -- Summary: Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/dual-vm-stack/ +- Summary: Compare Polkadot’s dual smart contract VMs—REVM for EVM compatibility and PolkaVM for RISC-V performance, flexibility, and efficiency. -# Node and Runtime +# Dual Virtual Machine Stack +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction -Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network. +Polkadot's smart contract platform supports two distinct virtual machine (VM) architectures, providing developers with flexibility in selecting the optimal execution backend for their specific needs. This approach strikes a balance between immediate Ethereum compatibility and long-term innovation, enabling developers to deploy either unmodified (Ethereum Virtual Machine) EVM contracts using Rust Ethereum Virtual Machine (REVM) or optimize for higher performance using PolkaVM (PVM). + +Both VM options share common infrastructure, including RPC interfaces, tooling support, and precompiles. The following sections compare architectures and guide you in selecting the best VM for your project's needs. -Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. +## Migrate from EVM -If the system were a monolithic protocol, any modification would require updating the entire system. Instead, Polkadot achieves true upgradeability by defining an immutable meta-protocol (the client) and a protocol (the runtime) that can be upgraded independently. +The [REVM backend](https://github.com/bluealloy/revm){target=\_blank} integrates a complete Rust implementation of the EVM, enabling Solidity contracts to run unchanged on Polkadot's smart contract platform. -This separation gives the [Polkadot Relay Chain](/polkadot-protocol/architecture/polkadot-chain){target=\_blank} and all connected [parachains](/polkadot-protocol/architecture/parachains){target=\_blank} an evolutionary advantage over other blockchain platforms. +REVM allows developers to use their existing Ethereum tooling and infrastructure to build on Polkadot. Choose REVM to: -## Architectural Principles +- Migrate existing Ethereum contracts without modifications. +- Retain exact EVM behavior for audit tools. +- Use developer tools that rely upon inspecting EVM bytecode. +- Prioritize rapid deployment over optimization. +- Work with established Ethereum infrastructure and tooling to build on Polkadot. -The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: +REVM enables Ethereum developers to seamlessly migrate to Polkadot, achieving performance and fee improvements without modifying their existing contracts or developer tooling stack. -- Client (Meta-protocol): - - Handles the foundational infrastructure of the blockchain. - - Manages runtime execution, networking, consensus, and other off-chain components. - - Provides an immutable base layer that ensures network stability. - - Upgradable only through hard forks. +## Upgrade to PolkaVM -- Runtime (Protocol): - - Defines the blockchain's state transition logic. - - Determines the specific rules and behaviors of the blockchain. - - Compiled to WebAssembly (Wasm) for platform-independent execution. - - Capable of being upgraded without network-wide forking. +[**PolkaVM**](https://github.com/paritytech/polkavm){target=\_blank} is a custom virtual machine optimized for performance with [RISC-V-based](https://en.wikipedia.org/wiki/RISC-V){target=\_blank} architecture, supporting Solidity and additional high-performance languages. It serves as the core execution environment, integrated directly within the runtime. Choose the PolkaVM for: -### Advantages of this Architecture +- An efficient interpreter for immediate code execution. +- A planned [Just In Time (JIT)](https://en.wikipedia.org/wiki/Just-in-time_compilation){target=\_blank} compiler for optimized performance. +- Dual-mode execution capability, allowing selection of the most appropriate backend for specific workloads. +- Optimized performance for short-running contract calls through the interpreter. -- **Forkless upgrades**: Runtime can be updated without disrupting the entire network. -- **Modularity**: Clear separation allows independent development of client and runtime. -- **Flexibility**: Enables rapid iteration and evolution of blockchain logic. -- **Performance**: WebAssembly compilation provides efficient, cross-platform execution. +The interpreter remains particularly beneficial for contracts with minimal code execution, as it enables immediate code execution through lazy interpretation. -## Node (Client) +## Architecture -The node, also known as the client, is the core component responsible for executing the Wasm runtime and orchestrating various essential blockchain components. It ensures the correct execution of the state transition function and manages multiple critical subsystems, including: +The following key components of PolkaVM work together to enable Ethereum compatibility on Polkadot-based chains. -- **Wasm execution**: Runs the blockchain runtime, which defines the state transition rules. -- **Database management**: Stores blockchain data. -- **Networking**: Facilitates peer-to-peer communication, block propagation, and transaction gossiping. -- **Transaction pool (Mempool)**: Manages pending transactions before they are included in a block. -- **Consensus mechanism**: Ensures agreement on the blockchain state across nodes. -- **RPC services**: Provides external interfaces for applications and users to interact with the node. +### Revive Pallet -## Runtime +[**`pallet_revive`**](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/index.html){target=\_blank} is a runtime module that executes smart contracts by adding extrinsics, runtime APIs, and logic to convert Ethereum-style transactions into formats compatible with Polkadot SDK-based blockchains. It processes Ethereum-style transactions through the following workflow: -The runtime is more than just a set of rules. It's the fundamental logic engine that defines a blockchain's entire behavior. In Polkadot SDK-based blockchains, the runtime represents a complete, self-contained description of the blockchain's state transition function. +```mermaid +sequenceDiagram + participant User as User/dApp + participant Proxy as Ethereum JSON RPC Proxy + participant Chain as Blockchain Node + participant Pallet as pallet_revive + + User->>Proxy: Submit Ethereum Transaction + Proxy->>Chain: Repackage as Polkadot Compatible Transaction + Chain->>Pallet: Process Transaction + Pallet->>Pallet: Decode Ethereum Transaction + Pallet->>Pallet: Execute Contract via PolkaVM + Pallet->>Chain: Return Results + Chain->>Proxy: Forward Results + Proxy->>User: Return Ethereum-compatible Response +``` -### Characteristics +This proxy-based approach eliminates the need for node binary modifications, maintaining compatibility across different client implementations. Preserving the original Ethereum transaction payload simplifies the adaptation of existing tools, which can continue processing familiar transaction formats. -The runtime is distinguished by three key characteristics: +### PolkaVM Design Fundamentals -- **Business logic**: Defines the complete application-specific blockchain behavior. -- **WebAssembly compilation**: Ensures platform-independent, secure execution. -- **On-chain storage**: Stored within the blockchain's state, allowing dynamic updates. +PolkaVM differs from the EVM in two key ways that make it faster, more hardware-efficient, and easier to extend: -### Key Functions +- **Register-based design**: Instead of a stack machine, PolkaVM uses a RISC-V–style register model. This design: -The runtime performs several critical functions, such as: + - Uses a fixed set of registers to pass arguments, not an infinite stack. + - Maps cleanly to real hardware like x86-64. + - Simplifies compilation and boosts runtime efficiency. + - Enables tighter control over register allocation and performance tuning. -- Define state transition rules. -- Implement blockchain-specific logic. -- Manage account interactions. -- Control transaction processing. -- Define governance mechanisms. -- Handle custom pallets and modules. +- **64-bit word size**: PolkaVM runs on a native 64-bit word size, aligning directly with modern CPUs. This design: -## Communication Between Node and Runtime + - Executes arithmetic operations with direct hardware support. + - Maintains compatibility with Solidity’s 256-bit types via YUL translation. + - Accelerates computation-heavy workloads through native word alignment. + - Integrates easily with low-level, performance-focused components. -The client and runtime communicate exclusively using [SCALE-encoded](/polkadot-protocol/parachain-basics/data-encoding){target=\_blank} communication. This ensures efficient and compact data exchange between the two components. +## Where To Go Next -### Runtime APIs +
    -The Runtime API consists of well-defined functions and constants a client assumes are implemented in the Runtime Wasm blob. These APIs enable the client to interact with the runtime to execute blockchain operations and retrieve information. The client invokes these APIs to: +- Learn __Contract Deployment__ -- Build, execute, and finalize blocks. -- Access metadata. -- Access consensus related information. -- Handle transaction execution. + --- -### Host Functions + Learn how REVM and PVM compare for compiling and deploying smart contracts. -During execution, the runtime can access certain external client functionalities via host functions. The specific functions the client exposes allow the runtime to perform operations outside the WebAssembly domain. Host functions enable the runtime to: + [:octicons-arrow-right-24: Reference](/smart-contracts/for-eth-devs/contract-deployment/) -- Perform cryptographic operations. -- Access the current blockchain state. -- Handle storage modifications. -- Allocate memory. +
    --- -Page Title: On-Chain Governance Overview +Page Title: Fork a Parachain Using Chopsticks -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md -- Canonical (HTML): https://docs.polkadot.com/reference/governance/ -- Summary: Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md +- Canonical (HTML): https://docs.polkadot.com/parachains/testing/fork-a-parachain/ +- Summary: Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. -# On-Chain Governance +# Fork a Parachain Using Chopsticks ## Introduction -Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model. - -This guide will explain the principles and structure of OpenGov and walk you through its key components, such as Origins, Tracks, and Delegation. You will learn about improvements over earlier governance systems, including streamlined voting processes and enhanced stakeholder participation. - -With OpenGov, Polkadot achieves a flexible, scalable, and democratic governance framework that allows multiple proposals to proceed simultaneously, ensuring the network evolves in alignment with its community's needs. - -## Governance Evolution +[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network. -Polkadot’s governance journey began with [Governance V1](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#governance-summary){target=\_blank}, a system that proved effective in managing treasury funds and protocol upgrades. However, it faced limitations, such as: +This guide walks you through installing Chopsticks and provides information on configuring a local blockchain fork. By streamlining testing and experimentation, Chopsticks empowers developers to innovate and accelerate their blockchain projects within the Polkadot ecosystem. -- Slow voting cycles, causing delays in decision-making. -- Inflexibility in handling multiple referendums, restricting scalability. +For additional support and information, please reach out through [GitHub Issues](https://github.com/AcalaNetwork/chopsticks/issues){target=_blank}. -To address these challenges, Polkadot introduced OpenGov, a governance model designed for greater inclusivity, efficiency, and scalability. OpenGov replaces the centralized structures of Governance V1, such as the Council and Technical Committee, with a fully decentralized and dynamic framework. +!!! warning + Chopsticks uses [Smoldot](https://github.com/smol-dot/smoldot){target=_blank} light client, which only supports the native Polkadot SDK API. Consequently, a Chopsticks-based fork doesn't support Ethereum JSON-RPC calls, meaning you cannot use it to fork your chain and connect Metamask. -For a full comparison of the historic and current governance models, visit the [Gov1 vs. Polkadot OpenGov](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#gov1-vs-polkadot-opengov){target=\_blank} section of the Polkadot Wiki. +## Prerequisites -## OpenGov Key Features +Before you begin, ensure you have the following installed: -OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: +- [Node.js](https://nodejs.org/en/){target=\_blank}. +- A package manager such as [npm](https://www.npmjs.com/){target=\_blank}, which should be installed with Node.js by default, or [Yarn](https://yarnpkg.com/){target=\_blank}. -- **Decentralization**: Shifts all decision-making power to the public, ensuring a more democratic process. -- **Enhanced delegation**: Allows users to delegate their votes to trusted experts across specific governance tracks. -- **Simultaneous referendums**: Multiple proposals can progress at once, enabling faster decision-making. -- **Polkadot Technical Fellowship**: A broad, community-driven group replacing the centralized Technical Committee. +## Install Chopsticks -This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. +You can install Chopsticks globally or locally in your project. Choose the option that best fits your development workflow. This documentation explains the features of Chopsticks version `1.2.2`. Make sure you're using the correct version to match these instructions. -## Origins and Tracks +### Global Installation -In OpenGov, origins and tracks are central to managing proposals and votes. +To install Chopsticks globally, allowing you to use it across multiple projects, run: -- **Origin**: Determines the authority level of a proposal (e.g., Treasury, Root) which decides the track of all referendums from that origin. -- **Track**: Define the procedural flow of a proposal, such as voting duration, approval thresholds, and enactment timelines. +```bash +npm i -g @acala-network/chopsticks@1.2.2 +``` -Developers must be aware that referendums from different origins and tracks will take varying amounts of time to reach approval and enactment. The [Polkadot Technical Fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} has the option to shorten this timeline by whitelisting a proposal and allowing it to be enacted through the [Whitelist Caller](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#whitelisted-caller){target=\_blank} origin. +Now, you should be able to run the `chopsticks` command from your terminal. -Visit [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#origins-and-tracks){target=\_blank} for details on current origins and tracks, associated terminology, and parameters. +### Local Installation -## Referendums +To use Chopsticks in a specific project, first create a new directory and initialize a Node.js project: -In OpenGov, anyone can submit a referendum, fostering an open and participatory system. The timeline for a referendum depends on the privilege level of the origin with more significant changes offering more time for community voting and participation before enactment. +```bash +mkdir my-chopsticks-project +cd my-chopsticks-project +npm init -y +``` -The timeline for an individual referendum includes four distinct periods: +Then, install Chopsticks as a local dependency: -- **Lead-in**: A minimum amount of time to allow for community participation, available room in the origin, and payment of the decision deposit. Voting is open during this period. -- **Decision**: Voting continues. -- **Confirmation**: Referendum must meet [approval and support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} criteria during entire period to avoid rejection. -- **Enactment**: Changes approved by the referendum are executed. +```bash +npm i @acala-network/chopsticks@1.2.2 +``` -### Vote on Referendums +Finally, you can run Chopsticks using the `npx` command. To see all available options and commands, run it with the `--help` flag: -Voters can vote with their tokens on each referendum. Polkadot uses a voluntary token locking mechanism, called conviction voting, as a way for voters to increase their voting power. A token holder signals they have a stronger preference for approving a proposal based upon their willingness to lock up tokens. Longer voluntary token locks are seen as a signal of continual approval and translate to increased voting weight. +```bash +npx @acala-network/chopsticks --help +``` -See [Voting on a Referendum](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank} for a deeper look at conviction voting and related token locks. +## Configure Chopsticks -### Delegate Voting Power +To run Chopsticks, you need to configure some parameters. This can be set either through using a configuration file or the command line interface (CLI). The parameters that can be configured are as follows: -The OpenGov system also supports multi-role delegations, allowing token holders to assign their voting power on different tracks to entities with expertise in those areas. +- **`genesis`**: The link to a parachain's raw genesis file to build the fork from, instead of an endpoint. +- **`timestamp`**: Timestamp of the block to fork from. +- **`endpoint`**: The endpoint of the parachain to fork. +- **`block`**: Use to specify at which block hash or number to replay the fork. +- **`wasm-override`**: Path of the Wasm to use as the parachain runtime, instead of an endpoint's runtime. +- **`db`**: Path to the name of the file that stores or will store the parachain's database. +- **`config`**: Path or URL of the config file. +- **`port`**: The port to expose an endpoint on. +- **`build-block-mode`**: How blocks should be built in the fork: batch, manual, instant. +- **`import-storage`**: A pre-defined JSON/YAML storage path to override in the parachain's storage. +- **`allow-unresolved-imports`**: Whether to allow Wasm unresolved imports when using a Wasm to build the parachain. +- **`html`**: Include to generate storage diff preview between blocks. +- **`mock-signature-host`**: Mock signature host so that any signature starts with `0xdeadbeef` and filled by `0xcd` is considered valid. -For example, if a token holder lacks the technical knowledge to evaluate proposals on the [Root track](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#root){target=\_blank}, they can delegate their voting power for that track to an expert they trust to vote in the best interest of the network. This ensures informed decision-making across tracks while maintaining flexibility for token holders. +### Configuration File -Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. +The Chopsticks source repository includes a collection of [YAML](https://yaml.org/){target=\_blank} files that can be used to set up various Polkadot SDK chains locally. You can download these configuration files from the [repository's `configs` folder](https://github.com/AcalaNetwork/chopsticks/tree/master/configs){target=\_blank}. -### Cancel a Referendum +An example of a configuration file for Polkadot is as follows: -Polkadot OpenGov has two origins for rejecting ongoing referendums: +{% raw %} +```yaml +endpoint: + - wss://rpc.ibp.network/polkadot + - wss://polkadot-rpc.dwellir.com +mock-signature-host: true +block: ${env.POLKADOT_BLOCK_NUMBER} +db: ./db.sqlite +runtime-log-level: 5 -- [**Referendum Canceller**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-canceller){target=\_blank}: Cancels an active referendum when non-malicious errors occur and refunds the deposits to the originators. -- [**Referendum Killer**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-killer){target=\_blank}: Used for urgent, malicious cases this origin instantly terminates an active referendum and slashes deposits. +import-storage: + System: + Account: + - - - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY + - providers: 1 + data: + free: '10000000000000000000' + ParasDisputes: + $removePrefix: ['disputes'] # those can makes block building super slow -See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. +``` +{% endraw %} -## Additional Resources +The configuration file allows you to modify the storage of the forked network by rewriting the pallet, state component and value that you want to change. For example, Polkadot's file rewrites Alice's `system.Account` storage so that the free balance is set to `10000000000000000000`. -- **[Democracy pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/democracy/src){target=\_blank}**: Handles administration of general stakeholder voting. -- **[Gov2: Polkadot’s Next Generation of Decentralised Governance](https://medium.com/polkadot-network/gov2-polkadots-next-generation-of-decentralised-governance-4d9ef657d11b){target=\_blank}**: Medium article by Gavin Wood. -- **[Polkadot Direction](https://matrix.to/#/#Polkadot-Direction:parity.io){target=\_blank}**: Matrix Element client. -- **[Polkassembly](https://polkadot.polkassembly.io/){target=\_blank}**: OpenGov dashboard and UI. -- **[Polkadot.js Apps Governance](https://polkadot.js.org/apps/#/referenda){target=\_blank}**: Overview of active referendums. +### CLI Flags +Alternatively, all settings (except for genesis and timestamp) can be configured via command-line flags, providing a comprehensive method to set up the environment. ---- +## WebSocket Commands -Page Title: Oracles +Chopstick's internal WebSocket server has special endpoints that allow the manipulation of the local Polkadot SDK chain. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md -- Canonical (HTML): https://docs.polkadot.com/parachains/integrations/oracles/ -- Summary: Learn about blockchain oracles, the essential bridges connecting blockchains with real-world data for decentralized applications in the Polkadot ecosystem. +These are the methods that can be invoked and their parameters: -# Oracles +- **dev_newBlock** (newBlockParams): Generates one or more new blocks. -## What is a Blockchain Oracle? + === "Parameters" -Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the "blockchain oracle problem." Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain. + - **`newBlockParams` ++"NewBlockParams"++**: The parameters to build the new block with. Where the `NewBlockParams` interface includes the following properties. -While simple oracle implementations may rely on a single trusted provider, more sophisticated solutions use decentralized networks where multiple providers stake assets and reach consensus on data validity. Typical applications include DeFi price feeds, weather data for insurance contracts, and cross-chain asset verification. + - **`count` ++"number"++**: The number of blocks to build. + - **`dmp` ++"{ msg: string, sentAt: number }[]"++**: The downward messages to include in the block. + - **`hrmp` ++"Record"++**: The horizontal messages to include in the block. + - **`to` ++"number"++**: The block number to build to. + - **`transactions` ++"string[]"++**: The transactions to include in the block. + - **`ump` ++"Record"++**: The upward messages to include in the block. + - **`unsafeBlockHeight` ++"number"++**: Build block using a specific block height (unsafe). -## Oracle Implementations + === "Example" -
    + ```js + import { ApiPromise, WsProvider } from '@polkadot/api'; -- __Acurast__ + async function main() { + const wsProvider = new WsProvider('ws://localhost:8000'); + const api = await ApiPromise.create({ provider: wsProvider }); + await api.isReady; + await api.rpc('dev_newBlock', { count: 1 }); + } - --- + main(); - Acurast is a decentralized, serverless cloud platform that uses a distributed network of mobile devices for oracle services, addressing centralized trust and data ownership issues. In the Polkadot ecosystem, it allows developers to define off-chain data and computation needs, which are processed by these devices acting as decentralized oracle nodes, delivering results to Substrate (Wasm) and EVM environments. + ``` - [:octicons-arrow-right-24: Reference](https://acurast.com/){target=\_blank} +- **dev_setBlockBuildMode** (buildBlockMode): Sets block build mode. -
    + === "Parameter" + + - **`buildBlockMode` ++"BuildBlockMode"++**: The build mode. Can be any of the following modes: + ```ts + export enum BuildBlockMode { + Batch = 'Batch', /** One block per batch (default) */ + Instant = 'Instant', /** One block per transaction */ + Manual = 'Manual', /** Only build when triggered */ + } + ``` + + === "Example" ---- + ```js + import { ApiPromise, WsProvider } from '@polkadot/api'; -Page Title: Overview of FRAME + async function main() { + const wsProvider = new WsProvider('ws://localhost:8000'); + const api = await ApiPromise.create({ provider: wsProvider }); + await api.isReady; + await api.rpc('dev_setBlockBuildMode', 'Instant'); + } -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md -- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ -- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. + main(); -# Customize Your Runtime + ``` -## Introduction +- **dev_setHead** (hashOrNumber): Sets the head of the blockchain to a specific hash or number. -A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. + === "Parameter" -This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. + - **`hashOrNumber` ++"string | number"++**: The block hash or number to set as head. -## Understanding Your Runtime + === "Example" -The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. + ```js + import { ApiPromise, WsProvider } from '@polkadot/api'; -Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. + async function main() { + const wsProvider = new WsProvider('ws://localhost:8000'); + const api = await ApiPromise.create({ provider: wsProvider }); + await api.isReady; + await api.rpc('dev_setHead', 500); + } -## Runtime Architecture + main(); -The following diagram shows how FRAME components work together to form your runtime: + ``` -![](/images/parachains/customize-runtime/index/frame-overview-01.webp) +- **dev_setRuntimeLogLevel** (runtimeLogLevel): Sets the runtime log level. -The main components are: + === "Parameter" -- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. -- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. -- **`frame_system`**: Provides core runtime primitives and storage. -- **`frame_support`**: Utilities and macros that simplify pallet development. + - **`runtimeLogLevel` ++"number"++**: The runtime log level to set. -## Building Blocks: Pallets + === "Example" -[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. + ```js + import { ApiPromise, WsProvider } from '@polkadot/api'; -A pallet can implement virtually any blockchain feature you need: + async function main() { + const wsProvider = new WsProvider('ws://localhost:8000'); + const api = await ApiPromise.create({ provider: wsProvider }); + await api.isReady; + await api.rpc('dev_setRuntimeLogLevel', 1); + } -- Expose new transactions that users can submit. -- Store data on-chain. -- Enforce business rules and validation logic. -- Emit events to notify users of state changes. -- Handle errors gracefully. + main(); -### Pre-Built Pallets vs. Custom Pallets + ``` -FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. +- **dev_setStorage** (values, blockHash): Creates or overwrites the value of any storage. -However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. + === "Parameters" -### Pallet Structure + - **`values` ++"object"++**: JSON object resembling the path to a storage value. + - **`blockHash` ++"string"++**: The block hash to set the storage value. -FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. + === "Example" -A typical pallet looks like this: + ```js + import { ApiPromise, WsProvider } from '@polkadot/api'; -```rust -pub use pallet::*; + import { Keyring } from '@polkadot/keyring'; + async function main() { + const wsProvider = new WsProvider('ws://localhost:8000'); + const api = await ApiPromise.create({ provider: wsProvider }); + await api.isReady; + const keyring = new Keyring({ type: 'ed25519' }); + const bob = keyring.addFromUri('//Bob'); + const storage = { + System: { + Account: [[[bob.address], { data: { free: 100000 }, nonce: 1 }]], + }, + }; + await api.rpc('dev_setStorage', storage); + } -#[frame_support::pallet] -pub mod pallet { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; + main(); - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); + ``` - #[pallet::config] // snip - #[pallet::event] // snip - #[pallet::error] // snip - #[pallet::storage] // snip - #[pallet::call] // snip -} -``` +- **dev_timeTravel** (date): Sets the timestamp of the block to a specific date". -Every pallet can implement these core macros: + === "Parameter" -- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. -- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. -- **`#[pallet::config]`**: Defines configuration and associated types. -- **`#[pallet::event]`**: Defines events emitted by your pallet. -- **`#[pallet::error]`**: Defines error types your pallet can return. -- **`#[pallet::storage]`**: Defines on-chain storage items. -- **`#[pallet::call]`**: Defines dispatchable functions (transactions). + - **`date` ++"string"++**: Timestamp or date string to set. All future blocks will be sequentially created after this point in time. -For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. + === "Example" -## How Runtime Customization Works + ```js + import { ApiPromise, WsProvider } from '@polkadot/api'; -Customizing your runtime typically follows these patterns: + async function main() { + const wsProvider = new WsProvider('ws://localhost:8000'); + const api = await ApiPromise.create({ provider: wsProvider }); + await api.isReady; + await api.rpc('dev_timeTravel', '2030-08-15T00:00:00'); + } -**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. + main(); -**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. + ``` -**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. +## Where to Go Next -**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. +
    -The following diagram illustrates how pallets combine to form a complete runtime: +- Tutorial __Fork a Chain with Chopsticks__ -![](/images/parachains/customize-runtime/index/frame-overview-02.webp) + --- -## Starting Templates + Visit this guide for step-by-step instructions for configuring and interacting with your forked chain. -The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. + [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/fork-live-chains/) -- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. +
    -- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. -- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. +--- -- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. +Page Title: Get Started with Parachain Development -## Key Customization Scenarios +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/get-started/ +- Summary: Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. -This section covers the most common customization patterns you'll encounter: +# Get Started -- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. +The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples. -- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. +## Quick Start Guides -- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. +Quick start guides help developers set up and interact with the Polkadot parachain ecosystem using various tools and frameworks. -- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. +| Tutorial | Tools | Description | +| :--------------------------------------------------------------------------------------------: | :----------------------------: | :---------------------------------------------------------------------: | +| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | Learn how to set up and run the Polkadot SDK Parachain Template locally | +| [Launch a Local Parachain](/parachains/testing/run-a-parachain-network/) | Zombienet, Chopsticks | Set up a local development environment for testing | +| [Connect to Polkadot](/chain-interactions/query-on-chain-data/query-sdks/) | Polkadot.js, Substrate Connect | Connect your application to Polkadot networks | +| [Fork an Existing Parachain](/parachains/testing/fork-a-parachain/) | Chopsticks | Create a local fork of a live parachain for testing | -- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. +## Launch a Simple Parachain +Learn the fundamentals of launching and deploying a parachain to the Polkadot network. ---- +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------: | +| [Set Up the Parachain Template](/parachains/launch-a-parachain/set-up-the-parachain-template/) | Polkadot SDK | +| [Deploy to Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/) | Step-by-step tutorial to deploying your parachain to Polkadot | +| [Obtain Coretime](/parachains/launch-a-parachain/obtain-coretime/) | Learn how to acquire blockspace using Polkadot's coretime model (RegionX) | -Page Title: Overview of the Polkadot Relay Chain +## Customize Your Runtime -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md -- Canonical (HTML): https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/ -- Summary: Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. +Build custom functionality for your parachain by composing and creating pallets. -# Overview +| Tutorial | Description | +| :-------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------: | +| [Add Existing Pallets to the Runtime](/parachains/customize-runtime/add-existing-pallets/) | Integrate pre-built pallets from the FRAME ecosystem | +| [Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/) | Configure and use multiple instances of the same pallet | +| [Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/) | Enable smart contract capabilities using Contracts or EVM pallets | -## Introduction +### Pallet Development -Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank}, and cross-chain interactions via its native [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank}. +Deep dive into creating and managing custom pallets for your parachain. -This guide covers key aspects of Polkadot’s architecture, including its high-level protocol structure, blockspace commoditization, and the role of its native token, DOT, in governance, staking, and resource allocation. +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------: | +| [Create a Custom Pallet](/parachains/customize-runtime/pallet-development/create-a-pallet/) | Build a pallet from scratch with custom logic | +| [Mock Your Runtime](/parachains/customize-runtime/pallet-development/mock-runtime/) | Set up a mock runtime environment for testing | +| [Pallet Unit Testing](/parachains/customize-runtime/pallet-development/pallet-testing/) | Write comprehensive tests for your pallet logic | +| [Add Your Custom Pallet to the Runtime](/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/) | Integrate your custom pallet into your parachain runtime | +| [Benchmark the Custom Pallet](/parachains/customize-runtime/pallet-development/benchmark-pallet/) | Measure and optimize pallet performance with benchmarking | -## Polkadot 1.0 +## Testing -Polkadot 1.0 represents the state of Polkadot as of 2023, coinciding with the release of [Polkadot runtime v1.0.0](https://github.com/paritytech/polkadot/releases/tag/v1.0.0){target=\_blank}. This section will focus on Polkadot 1.0, along with philosophical insights into network resilience and blockspace. +Test your parachain in various environments before production deployment. -As a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including: +| Tutorial | Description | +| :---------------------------------------------------------------------: | :-----------------------------------------------------: | +| [Fork a Parachain](/parachains/testing/fork-a-parachain/) | Use Chopsticks to create a local fork for testing | +| [Run a Parachain Network](/parachains/testing/run-a-parachain-network/) | Launch a complete parachain test network with Zombienet | -- **Application-specific Layer-1 blockchains (parachains)**: Polkadot's sharded network allows for parallel transaction processing, with shards that can have unique state transition functions, enabling custom-built L1 chains optimized for specific applications. +## Runtime Upgrades and Maintenance -- **Shared security and scalability**: L1 chains connected to Polkadot benefit from its [Nominated Proof of Stake (NPoS)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#nominated-proof-of-stake){target=\_blank} system, providing security out-of-the-box without the need to bootstrap their own. +Manage your parachain's lifecycle with forkless upgrades and maintenance operations. -- **Secure interoperability**: Polkadot's native interoperability enables seamless data and value exchange between parachains. This interoperability can also be used outside of the ecosystem for bridging with external networks. +| Tutorial | Description | +| :-----------------------------------------------------------------------: | :--------------------------------------------------: | +| [Runtime Upgrades](/parachains/runtime-maintenance/runtime-upgrades/) | Perform forkless runtime upgrades via governance | +| [Storage Migrations](/parachains/runtime-maintenance/storage-migrations/) | Safely migrate storage when updating runtime logic | +| [Unlock Parachains](/parachains/runtime-maintenance/unlock-parachains/) | Understand parachain lifecycle and unlock mechanisms | -- **Resilient infrastructure**: Decentralized and scalable, Polkadot ensures ongoing support for development and community initiatives via its on-chain [treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} and governance. +## Interoperability -- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. +Configure your parachain for cross-chain communication using XCM (Cross-Consensus Messaging). -- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. +| Tutorial | Description | +| :--------------------------------------------------------------------------------------------------------: | :----------------------------------------------------: | +| [Open HRMP Channels Between Parachains](/parachains/interoperability/channels-between-parachains/) | Establish communication channels with other parachains | +| [Open HRMP Channels with System Parachains](/parachains/interoperability/channels-with-system-parachains/) | Connect with Asset Hub and other system parachains | - - [Polkadot Blockchain Academy](https://polkadot.com/blockchain-academy){target=\_blank} - - [EdX courses](https://www.edx.org/school/web3x){target=\_blank} - - Rust and Substrate courses (coming soon) +## Integrations -### High-Level Architecture +Integrate your parachain with essential ecosystem tools and services. -Polkadot features a chain that serves as the central component of the system. This chain is depicted as a ring encircled by several parachains that are connected to it. +| Tutorial | Description | +| :--------------------------------------------: | :----------------------------------------------------: | +| [Wallets](/parachains/integrations/wallets/) | Integrate wallet support for user interactions | +| [Indexers](/parachains/integrations/indexers/) | Set up indexing solutions for querying blockchain data | +| [Oracles](/parachains/integrations/oracles/) | Connect your parachain to off-chain data sources | -According to Polkadot's design, any blockchain that can compile to WebAssembly (Wasm) and adheres to the Parachains Protocol becomes a parachain on the Polkadot network. +## Additional Resources -Here’s a high-level overview of the Polkadot protocol architecture: +- [Polkadot SDK Documentation](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/index.html) +- [Polkadot Wiki - Parachains](https://wiki.polkadot.network/docs/learn-parachains/) -![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } -Parachains propose blocks to Polkadot validators, who check for availability and validity before finalizing them. With the relay chain providing security, collators—full nodes of parachains—can focus on their tasks without needing strong incentives. +--- -The [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank} allows parachains to exchange messages freely, leveraging the chain's security for trust-free communication. +Page Title: Get Started with Smart Contracts -In order to interact with chains that want to use their own finalization process (e.g., Bitcoin), Polkadot has [bridges](/reference/parachains/interoperability/#bridges-connecting-external-networks){target=\_blank} that offer two-way compatibility, meaning that transactions can be made between different parachains. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/get-started/ +- Summary: Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. -### Polkadot's Additional Functionalities +# Get Started -Historically, obtaining core slots on Polkadot chain relied upon crowdloans and auctions. Chain cores were leased through auctions for three-month periods, up to a maximum of two years. Crowdloans enabled users to securely lend funds to teams for lease deposits in exchange for pre-sale tokens, which is the only way to access slots on Polkadot 1.0. Auctions are now deprecated in favor of [coretime](/polkadot-protocol/architecture/system-chains/coretime/){target=\_blank}. +This resource provides quick-starts for building smart contracts on Polkadot Hub. Use the tables below to jump directly to the tools and workflows you need. -Additionally, the chain handles [staking](https://wiki.polkadot.com/learn/learn-staking/){target=\_blank}, [accounts](/reference/parachains/accounts/){target=\_blank}, balances, and [governance](/reference/governance/){target=\_blank}. +## Quick Starts -#### Agile Coretime +Kick off development fast with curated links for connecting, funding, exploring, and deploying your first contract. -The new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. +| Quick Start | Tools | Description | +|:---------------------------------------------------------------------------------------------------:|:---------------------:|:---------------------------------------------------------------:| +| [Connect to Polkadot](/smart-contracts/connect/){target=\_blank} | Polkadot.js, MetaMask | Add the network, configure RPC, verify activity in the explorer | +| [Get Test Tokens](/smart-contracts/faucets/){target=\_blank} | - | Request test funds to deploy and interact with contracts | +| [Explore Transactions](/smart-contracts/explorers/){target=\_blank} | Subscan | Inspect transactions, logs, token transfers, and contract state | +| [Deploy with Remix](/smart-contracts/dev-environments/remix/deploy-a-contract/){target=\_blank} | Remix | One‑click browser deployment to Polkadot Hub | +| [Deploy with Foundry](/smart-contracts/dev-environments/foundry/deploy-a-contract/){target=\_blank} | Foundry | Scripted deployments and testing from the CLI | +| [Deploy with Hardhat](/smart-contracts/dev-environments/hardhat/deploy-a-contract/){target=\_blank} | Hardhat | Project scaffolding, testing, and deployments | -[Agile coretime](/reference/polkadot-hub/consensus-and-security/agile-coretime/){target=\_blank} improves the efficient use of Polkadot's network resources and offers economic flexibility for developers, extending Polkadot's capabilities far beyond the original vision outlined in the [whitepaper](https://polkadot.com/papers/Polkadot-whitepaper.pdf){target=\_blank}. +## Build and Test Locally -It enables parachains to purchase monthly "bulk" allocations of coretime (the time allocated for utilizing a core, measured in Polkadot relay chain blocks), ensuring heavy-duty parachains that can author a block every six seconds with [Asynchronous Backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} can reliably renew their coretime each month. Although six-second block times are now the default, parachains have the option of producing blocks less frequently. +Set up local environments and CI-friendly workflows to iterate quickly and validate changes before deploying. -Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. +| Build and Test Locally | Tools | Description | +|:------------------------------------------------------------------------------------------------------------:|:-----------------:|:----------------------------------------------------:| +| [Run a Local Dev Node](/smart-contracts/dev-environments/local-dev-node/){target=\_blank} | Polkadot SDK node | Spin up a local node for iterative development | +| [Remix: Get Started](/smart-contracts/dev-environments/remix/get-started/){target=\_blank} | Remix | Connect Remix to Polkadot Hub and configure accounts | +| [Remix: Verify a Contract](/smart-contracts/dev-environments/remix/verify-a-contract/){target=\_blank} | Remix | Publish verified source on explorers | +| [Foundry: Install and Config](/smart-contracts/dev-environments/foundry/install-and-config/){target=\_blank} | Foundry | Install toolchain and configure networks | +| [Foundry: Compile and Test](/smart-contracts/dev-environments/foundry/compile-and-test/){target=\_blank} | Foundry | Write and run Solidity tests locally | +| [Foundry: Verify a Contract](/smart-contracts/dev-environments/foundry/verify-a-contract/){target=\_blank} | Foundry | Verify deployed bytecode and metadata | +| [Hardhat: Install and Config](/smart-contracts/dev-environments/hardhat/install-and-config/){target=\_blank} | Hardhat | Initialize a project and configure networks | +| [Hardhat: Compile and Test](/smart-contracts/dev-environments/hardhat/compile-and-test/){target=\_blank} | Hardhat | Unit test contracts and run scripts | +| [Hardhat: Verify a Contract](/smart-contracts/dev-environments/hardhat/verify-a-contract/){target=\_blank} | Hardhat | Verify deployments on explorers | -### Polkadot's Resilience +## Ethereum Developer Resources -Decentralization is a vital component of blockchain networks, but it comes with trade-offs: +Bridge your Ethereum knowledge with Polkadot Hub specifics: account mapping, fees, JSON‑RPC, and deployment. -- An overly decentralized network may face challenges in reaching consensus and require significant energy to operate. -- Also, a network that achieves consensus quickly risks centralization, making it easier to manipulate or attack. +| Ethereum Developer Guides | Description | +|:---------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------:| +| [Accounts](/smart-contracts/for-eth-devs/accounts/){target=\_blank} | How 20‑byte Ethereum addresses map to 32‑byte Polkadot accounts | +| [Blocks, Transactions, and Fees](/smart-contracts/for-eth-devs/blocks-transactions-fees/){target=\_blank} | Transaction types, fees, and multi‑dimensional metering | +| [Gas Model](/smart-contracts/for-eth-devs/gas-model/){target=\_blank} | Gas vs. weight, proof size, and storage deposits | +| [Contract Deployment](/smart-contracts/for-eth-devs/contract-deployment/){target=\_blank} | Deployment patterns and best practices on Polkadot Hub | +| [JSON‑RPC APIs](/smart-contracts/for-eth-devs/json-rpc-apis/){target=\_blank} | Supported Ethereum JSON‑RPC methods and examples | +| [Migration](/smart-contracts/for-eth-devs/migration/){target=\_blank} | Port existing apps and tooling to Polkadot Hub | +| [Dual VM Stack](/smart-contracts/for-eth-devs/dual-vm-stack/){target=\_blank} | Overview of EVM and native execution on the Hub | -A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. +## Cookbook: Hands‑on Tutorials -Polkadot 1.0 currently achieves resilience through several strategies: +Follow step‑by‑step guides that walk through common tasks and complete dApp examples. -- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. +| Tutorial | Tools | Description | +|:--------------------------------------------------------------------------------------------------------:|:-------------------:|:-----------------------------------------:| +| [Deploy a Basic Contract](/smart-contracts/cookbook/smart-contracts/deploy-basic/remix/){target=\_blank} | Remix | Minimal deployment walkthrough | +| [Deploy an ERC‑20](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/){target=\_blank} | Remix, OpenZeppelin | Create, deploy, and mint a fungible token | +| [Deploy an NFT (ERC‑721)](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/){target=\_blank} | Remix, OpenZeppelin | Build and deploy an NFT collection | +| [Uniswap V2](/smart-contracts/cookbook/eth-dapps/uniswap-v2/){target=\_blank} | Hardhat | Full dApp project: compile, test, deploy | +| [Zero‑to‑Hero dApp](/smart-contracts/cookbook/dapps/zero-to-hero/){target=\_blank} | Multiple | End‑to‑end dApp patterns and practices | -- **Decentralized nodes**: Designed to encourage operators to join the network. This program aims to expand and diversify the validators in the ecosystem who aim to become independent of the program during their term. Feel free to explore more about the program on the official [Decentralized Nodes](https://nodes.web3.foundation/){target=\_blank} page. +## Libraries -- **On-chain treasury and governance**: Known as [OpenGov](/reference/governance/){target=\_blank}, this system allows every decision to be made through public referenda, enabling any token holder to cast a vote. +Choose the client libraries that fit your stack for connecting wallets and calling contracts. -### Polkadot's Blockspace +| Library | Description | +|:------------------------------------------------------------------:|:-------------------------------------------------------:| +| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\_blank} | Connect, sign, and interact with contracts using Ethers | +| [viem](/smart-contracts/libraries/viem/){target=\_blank} | Type‑safe EVM interactions and utilities | +| [Wagmi](/smart-contracts/libraries/wagmi/){target=\_blank} | React hooks for wallet connections and contract calls | +| [Web3.js](/smart-contracts/libraries/web3-js/){target=\_blank} | Web3 provider and contract APIs | +| [Web3.py](/smart-contracts/libraries/web3-py/){target=\_blank} | Python toolkit for on‑chain interactions and scripts | -Polkadot 1.0’s design allows for the commoditization of blockspace. +## Integrations -Blockspace is a blockchain's capacity to finalize and commit operations, encompassing its security, computing, and storage capabilities. Its characteristics can vary across different blockchains, affecting security, flexibility, and availability. +Integrate essential services like wallets, indexers, and oracles to round out your dApp. -- **Security**: Measures the robustness of blockspace in Proof of Stake (PoS) networks linked to the stake locked on validator nodes, the variance in stake among validators, and the total number of validators. It also considers social centralization (how many validators are owned by single operators) and physical centralization (how many validators run on the same service provider). +| Integration | Description | +|:-------------------------------------------------------------------:|:-----------------------------------------:| +| [Wallets](/smart-contracts/integrations/wallets/){target=\_blank} | Supported wallets and configuration notes | +| [Indexers](/smart-contracts/integrations/indexers/){target=\_blank} | Index and query blockchain data | +| [Oracles](/smart-contracts/integrations/oracles/){target=\_blank} | Bring external data on‑chain | -- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes. +## Precompiles -- **Availability**: Indicates how easily users can access blockspace. It should be easily accessible, allowing diverse business models to thrive, ideally regulated by a marketplace based on demand and supplemented by options for "second-hand" blockspace. +Discover precompiled system contracts available on the Hub and how to use them. -Polkadot is built on core blockspace principles, but there's room for improvement. Tasks like balance transfers, staking, and governance are managed on the relay chain. +| Topic | Description | +|:------------------------------------------------------------------------:|:---------------------------------------------------:| +| [Overview of Precompiles](/smart-contracts/precompiles/){target=\_blank} | What precompiles are available on the Hub | +| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\_blank} | EVM precompiles and interfaces | +| [Staking](/smart-contracts/precompiles/staking/){target=\_blank} | Interact with staking functionality via precompiles | +| [XCM](/smart-contracts/precompiles/xcm/){target=\_blank} | Cross‑chain messaging helpers for contracts | -Delegating these responsibilities to [system chains](/polkadot-protocol/architecture/system-chains/){target=\_blank} could enhance flexibility and allow the relay chain to concentrate on providing shared security and interoperability. +From here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\_blank} or reach out in the community channels. -For more information about blockspace, watch [Robert Habermeier’s interview](https://www.youtube.com/watch?v=e1vISppPwe4){target=\_blank} or read his [technical blog post](https://www.rob.tech/blog/polkadot-blockspace-over-blockchains/){target=\_blank}. -## DOT Token +--- -DOT is the native token of the Polkadot network, much like BTC for Bitcoin and Ether for the Ethereum blockchain. DOT has 10 decimals, uses the Planck base unit, and has a balance type of `u128`. The same is true for Kusama's KSM token with the exception of having 12 decimals. +Page Title: Get Started with XCM -### Redenomination of DOT - -Polkadot conducted a community poll, which ended on 27 July 2020 at block 888,888, to decide whether to redenominate the DOT token. The stakeholders chose to redenominate the token, changing the value of 1 DOT from 1e12 plancks to 1e10 plancks. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md +- Canonical (HTML): https://docs.polkadot.com/parachains/interoperability/get-started/ +- Summary: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. -Importantly, this did not affect the network's total number of base units (plancks); it only affects how a single DOT is represented. The redenomination became effective 72 hours after transfers were enabled, occurring at block 1,248,328 on 21 August 2020 around 16:50 UTC. +# Get Started with XCM -### The Planck Unit +## Introduction -The smallest unit of account balance on Polkadot SDK-based blockchains (such as Polkadot and Kusama) is called _Planck_, named after the Planck length, the smallest measurable distance in the physical universe. +Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems. -Similar to how BTC's smallest unit is the Satoshi and ETH's is the Wei, Polkadot's native token DOT equals 1e10 Planck, while Kusama's native token KSM equals 1e12 Planck. +With XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation. -### Uses for DOT +## Messaging Format -DOT serves three primary functions within the Polkadot network: +XCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics. -- **Governance**: It is used to participate in the governance of the network. -- **Staking**: DOT is staked to support the network's operation and security. -- **Buying coretime**: Used to purchase coretime in-bulk or on-demand and access the chain to benefit from Polkadot's security and interoperability. +XCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing. -Additionally, DOT can serve as a transferable token. For example, DOT, held in the treasury, can be allocated to teams developing projects that benefit the Polkadot ecosystem. +## The Four Principles of XCM -## JAM and the Road Ahead +XCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems: -The Join-Accumulate Machine (JAM) represents a transformative redesign of Polkadot's core architecture, envisioned as the successor to the current relay chain. Unlike traditional blockchain architectures, JAM introduces a unique computational model that processes work through two primary functions: +- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes. +- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended. +- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin. +- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems. -- **Join**: Handles data integration. -- **Accumulate**: Folds computations into the chain's state. +These principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments. -JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: +## The XCM Tech Stack -- **Permissionless code execution**: JAM is designed to be more generic and flexible, allowing for permissionless code execution through services that can be deployed without governance approval. -- **More effective block time utilization**: JAM's efficient pipeline processing model places the prior state root in block headers instead of the posterior state root, enabling more effective utilization of block time for computations. +![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp) -This architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes. +The XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels. +## Core Functionalities of XCM ---- +XCM enhances cross-consensus communication by introducing several powerful features: -Page Title: Parachains Overview +- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management. +- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification. +- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/ -- Summary: Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. +The standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications. -# Parachains Overview +## XCM Example -## Introduction +The following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA). -A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network. +```rust +let message = Xcm(vec![ + WithdrawAsset((Here, amount).into()), + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } +]); +``` -Unlike standalone blockchains that must bootstrap their own validator sets and security, parachains leverage Polkadot's pooled security model. This allows parachain developers to focus on their application-specific functionality rather than consensus and security infrastructure. Parachains can communicate with each other through Cross-Consensus Messaging (XCM), enabling seamless interoperability across the Polkadot ecosystem. +The message consists of three instructions described as follows: -Key capabilities that parachains provide include: +- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register. -- **Shared security**: Inherit security from Polkadot's validator set without maintaining your own. -- **Interoperability**: Communicate trustlessly with other parachains via XCM. -- **Scalability**: Process transactions in parallel with other parachains. -- **Customization**: Build application-specific logic tailored to your use case. -- **Upgradeability**: Upgrade runtime logic without hard forks. + ```rust + WithdrawAsset((Here, amount).into()), + ``` -## Polkadot SDK: Parachain Architecture + - **`Here`**: The native parachain token. + - **`amount`**: The number of tokens that are transferred. -Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: + The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register. -![](/images/reference/parachains/index/overview-01.webp) +- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\_blank} of the XCM instructions. -- **[Substrate](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html){target=\_blank}**: The foundation providing core blockchain primitives and libraries. -- **[FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank}**: A modular framework for building your parachain's runtime logic. -- **[Cumulus](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html){target=\_blank}**: Essential libraries and pallets that enable parachain functionality. -- **[XCM (Cross Consensus Messaging)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/xcm/index.html){target=\_blank}**: The messaging format for communicating with other parachains and the relay chain. -- **[Polkadot](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/polkadot/index.html){target=\_blank}**: The relay chain that provides security and coordination. + ```rust + BuyExecution { + fees: (Here, amount).into(), + weight_limit: WeightLimit::Unlimited + }, + ``` -### Substrate: The Foundation + - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight. + - **`weight_limit`**: Defines the maximum fees that can be used to buy weight. -Substrate provides the core infrastructure that every parachain is built upon. It handles the low-level blockchain functionality, allowing you to focus on your application's unique features. Substrate includes implementations for networking, database management, consensus participation, and the execution environment for your runtime. +- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\_blank}**: Moves the remaining tokens from the holding register to Bob’s account. -Every Polkadot SDK node consists of two main components: + ```rust + DepositAsset { + assets: All.into(), + beneficiary: MultiLocation { + parents: 0, + interior: Junction::AccountId32 { + network: None, + id: BOB.clone().into() + }.into(), + }.into() + } + ``` -- **Client (Host)**: Handles infrastructure services. + - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited. + +This step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - - Native binary that runs on validator and collator nodes. - - Executes the Wasm-compiled runtime. - - Manages networking, database, mempool, and block production. - - Interfaces with the relay chain for validation. +## Overview -- **Runtime (State Transition Function)**: Contains your business logic. +XCM revolutionizes cross-chain communication by enabling use cases such as: - - Defines how your Polkadot SDK node processes transactions. - - Compiled to [Wasm](https://webassembly.org/){target=\_blank} for deterministic execution. - - Stored on-chain and upgradeable via governance. +- Token transfers between blockchains. +- Asset locking for cross-chain smart contract interactions. +- Remote execution of functions on other blockchains. -```mermaid -%%{init: {'flowchart': {'padding': 5, 'nodeSpacing': 50, 'rankSpacing': 10}}}%% -graph TB - classDef title font-size:20px,font-weight:bold,stroke-width:0px - classDef clientStyle font-size:16px,font-weight:bold - classDef clientSubNodeStyle margin-top:10px - classDef runtimeCallExecutorStyle padding-top:10px +These functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\_blank}. - subgraph sg1[Parachain
    Node] - direction TB - I[RuntimeCall Executor] - B[Wasm Runtime - STF] +--- - subgraph sg2[Client] - direction TB - C[Network and Blockchain
    Infrastructure Services
    + Relay Chain Interface] - end +Page Title: Indexers - I --> B - end +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md +- Canonical (HTML): https://docs.polkadot.com/parachains/integrations/indexers/ +- Summary: Discover blockchain indexers. Enhance data access, enable fast and complex queries, and optimize blockchain data for seamless app performance. - class sg1 title - class sg2 clientStyle - class C clientSubNodeStyle - class I runtimeCallExecutorStyle +# Indexers -``` +## The Challenge of Blockchain Data Access -### FRAME: Building Blocks for Your Runtime +Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges: -FRAME provides modular components called [pallets](/reference/glossary#pallet){target=\_blank} that you can compose to build your parachain's runtime. Each pallet provides specific functionality that you can customize and configure for your needs. This modular approach allows you to quickly assemble complex functionality without writing everything from scratch. +- Data is scattered and unorganized across the blockchain. +- Retrieving large datasets can take days or weeks to sync. +- Complex operations (like aggregations, averages, or cross-chain queries) require additional processing. +- Direct blockchain queries can impact dApp performance and responsiveness. -```mermaid -graph LR - subgraph SP["Parachain Runtime"] - direction LR - Timestamp ~~~ Aura ~~~ ParachainSystem - Balances ~~~ TransactionPayment ~~~ Sudo - subgraph Timestamp["Timestamp"] - SS1[Custom Config] - end - subgraph Aura["Aura"] - SS2[Custom Config] - end - subgraph ParachainSystem["Parachain System"] - SS3[Custom Config] - end - subgraph Balances["Balances"] - SS4[Custom Config] - end - subgraph TransactionPayment["Transaction Payment"] - SS5[Custom Config] - end - subgraph Sudo["Sudo"] - SS6[Custom Config] - end - style Timestamp stroke:#FF69B4 - style Aura stroke:#FF69B4 - style ParachainSystem stroke:#FF69B4 - style Balances stroke:#FF69B4 - style TransactionPayment stroke:#FF69B4 - style Sudo stroke:#FF69B4 - style SS1 stroke-dasharray: 5 - style SS2 stroke-dasharray: 5 - style SS3 stroke-dasharray: 5 - style SS4 stroke-dasharray: 5 - style SS5 stroke-dasharray: 5 - style SS6 stroke-dasharray: 5 - - end - subgraph AP["Available FRAME Pallets"] - direction LR - A1[Aura]~~~A2[Parachain
    System]~~~A3[Transaction
    Payment]~~~A4[Sudo] - B1[Identity]~~~B2[Balances]~~~B3[Assets]~~~B4[EVM] - C1[Timestamp]~~~C2[Staking]~~~C3[Contracts]~~~C4[and more...] - end - AP --> SP -``` - -### Cumulus: Parachain-Specific Functionality - -Cumulus is what transforms a Polkadot SDK-based runtime into a parachain-capable runtime. It provides the essential components for communicating with the relay chain, participating in Polkadot's consensus, and handling parachain-specific operations like block validation and collation. - -Key Cumulus components include: - -- **Parachain system pallet**: Core parachain functionality and relay chain communication. -- **Collator consensus**: Block production logic for parachain collators. -- **Relay chain interface**: APIs for interacting with the Polkadot relay chain. -- **Validation data**: Handling proof-of-validity data required by relay chain validators. +## What is a Blockchain Indexer? -## Where to Go Next +A blockchain indexer is a specialized infrastructure tool that processes, organizes, and stores blockchain data in an optimized format for efficient querying. Think of it as a search engine for blockchain data that: -Building a parachain requires understanding the relationship between your chain and the Polkadot relay chain. The Polkadot SDK provides all the tools needed to design custom runtime logic, enable cross-chain communication, and deploy your parachain to production. +- Continuously monitors the blockchain for new blocks and transactions. +- Processes and categorizes this data according to predefined schemas. +- Stores the processed data in an easily queryable database. +- Provides efficient APIs (typically [GraphQL](https://graphql.org/){target=\_blank}) for data retrieval. -The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. +## Indexer Implementations
    -- Guide __Launch a Simple Parachain__ +- __Subsquid__ --- - Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. - - [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) + Subsquid is a data network that allows rapid and cost-efficient retrieval of blockchain data from 100+ chains using Subsquid's decentralized data lake and open-source SDK. In simple terms, Subsquid can be considered an ETL (extract, transform, and load) tool with a GraphQL server included. It enables comprehensive filtering, pagination, and even full-text search capabilities. Subsquid has native and full support for EVM and Substrate data, even within the same project. + [:octicons-arrow-right-24: Reference](https://www.sqd.ai/){target=\_blank} -- Guide __Customize Your Runtime__ +- __Subquery__ --- - Design your parachain's runtime logic and choose appropriate pallets for your use case. - - [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) + SubQuery is a fast, flexible, and reliable open-source data decentralised infrastructure network that provides both RPC and indexed data to consumers worldwide. + It provides custom APIs for your web3 project across multiple supported chains. -- Guide __Interoperability__ + [:octicons-arrow-right-24: Reference](https://subquery.network/){target=\_blank} - --- +
    - Implement XCM for trustless cross-chain communication with other parachains. - [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/) +--- -- Guide __Runtime Upgrades__ +Page Title: Install Polkadot SDK - --- +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md +- Canonical (HTML): https://docs.polkadot.com/parachains/install-polkadot-sdk/ +- Summary: Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. - Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. +# Install Polkadot SDK - [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) +This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts: -
    +- **Installing dependencies**: Setting up Rust, required system packages, and development tools. +- **Building the Polkadot SDK**: Cloning and compiling the Polkadot SDK repository. +Follow the appropriate section for your operating system to ensure all necessary tools are installed and configured properly. ---- +## Install Dependencies: macOS -Page Title: Polkadart +You can install Rust and set up a Substrate development environment on Apple macOS computers with Intel or Apple M1 processors. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/polkadart/ -- Summary: Polkadart is a type-safe, native Dart, SDK for Polkadot and any compatible Polkadot-SDK blockchain network. +### Before You Begin {: #before-you-begin-mac-os } -# Polkadart +Before you install Rust and set up your development environment on macOS, verify that your computer meets the following basic requirements: -Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications. +- Operating system version is 10.7 Lion or later. +- Processor speed of at least 2 GHz. Note that 3 GHz is recommended. +- Memory of at least 8 GB RAM. Note that 16 GB is recommended. +- Storage of at least 10 GB of available space. +- Broadband Internet connection. -This page will outline some of the core components of Polkadart. For more details, refer to the [official documentation](https://polkadart.dev){target=\_blank}. +### Install Homebrew -## Installation +In most cases, you should use Homebrew to install and manage packages on macOS computers. If you don't already have Homebrew installed on your local computer, you should download and install it before continuing. -Add Polkadart to your `pubspec.yaml`: +To install Homebrew: -=== "All packages" +1. Open the Terminal application. +2. Download and install Homebrew by running the following command: ```bash - dart pub add polkadart polkadart_cli polkadart_keyring polkadart_scale_codec secp256k1_ecdsa sr25519 ss58 substrate_bip39 substrate_metadata + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" ``` -=== "Core only" +3. Verify Homebrew has been successfully installed by running the following command: ```bash - dart pub add polkadart polkadart_cli polkadart_keyring + brew --version ``` -For type-safe API generation, add the following to your `pubspec.yaml`: - -{% raw %} -```yaml title="pubspec.yaml" -polkadart: - output_dir: lib/generated - chains: - polkadot: wss://rpc.polkadot.io - kusama: wss://kusama-rpc.polkadot.io - custom: wss://your-node.example.com -``` -{% endraw %} - -## Get Started + The command displays output similar to the following: -### Type Generation +
    + brew --version + Homebrew 4.3.15 +
    -Polkadart provides a CLI tool to generate type definitions from any Polkadot-SDK compatible blockchain network. This allows you to build type-safe Dart applications without dealing with the low-level details of the blockchain. +### Support for Apple Silicon -### Run Generator +Protobuf must be installed before the build process can begin. To install it, run the following command: ```bash -dart run polkadart_cli:generate -v +brew install protobuf ``` -### Use Generated Types +### Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os } -```dart -import 'package:your_app/generated/polkadot/polkadot.dart'; -import 'package:polkadart/polkadart.dart'; -import 'package:ss58/ss58.dart'; +Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `openssl`. -final provider = Provider.fromUri(Uri.parse('wss://rpc.polkadot.io')); -final polkadot = Polkadot(provider); - -// Account from SS58 address -final account = Address.decode('19t9Q2ay58hMDaeg6eeBhqmHsRnc2jDMV3cYYw9zbc59HLj'); +To install `openssl` and the Rust toolchain on macOS: -// Retrieve Account Balance -final accountInfo = await polkadot.query.system.account(account.pubkey); -print('Balance: ${accountInfo.data.free}') -``` +1. Open the Terminal application. +2. Ensure you have an updated version of Homebrew by running the following command: + + ```bash + brew update + ``` + +3. Install the `openssl` package by running the following command: -### Creating an API Instance + ```bash + brew install openssl + ``` -An API instance is required to interact with the blockchain. Polkadart provides a `Provider` class that allows you to connect to any network. +4. Download the `rustup` installation program and use it to install Rust by running the following command: -```dart -import 'package:demo/generated/polkadot/polkadot.dart'; -import 'package:polkadart/provider.dart'; + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -Future main(List arguments) async { - final provider = Provider.fromUri(Uri.parse('wss://rpc.polkadot.io')); - final polkadot = Polkadot(provider); -} -``` +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: -### Reading Chain Data + ```bash + source ~/.cargo/env + ``` -Besides querying the data using the `query` from the generated API, you can also use the State API for querying storage data, metadata, runtime information, and other chain information. +7. Configure the Rust toolchain to default to the latest stable version by running the following commands: -```dart -final stateApi = StateApi(provider); + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -// Get current runtime version -final runtimeVersion = await stateApi.getRuntimeVersion(); -print(runtimeVersion.toJson()); +8. Install `cmake` using the following command: -// Get metadata -final metadata = await stateApi.getMetadata(); -print('Metadata version: ${metadata.version}'); -``` + ```bash + brew install cmake + ``` -### Subscribe to New Blocks +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -You can subscribe to new blocks on the blockchain using the `subscribe` method. +## Install Dependencies: Linux -```dart -final subscription = await provider.subscribe('chain_subscribeNewHeads', []); +Rust supports most Linux distributions. Depending on the specific distribution and version of the operating system you use, you might need to add some software dependencies to your environment. In general, your development environment should include a linker or a C-compatible compiler, such as `clang`, and an appropriate integrated development environment (IDE). -subscription.stream.forEach((response) { - print('New head: ${response.result}'); -}); +### Before You Begin {: #before-you-begin-linux } + +Check the documentation for your operating system for information about the installed packages and how to download and install any additional packages you might need. For example, if you use Ubuntu, you can use the Ubuntu Advanced Packaging Tool (`apt`) to install the `build-essential` package: + +```bash +sudo apt install build-essential ``` -### Send a Transaction - -Perhaps the most common operation done in any blockchain is transferring funds. Here you can see how that can be done using Polkadart: - -```dart -final wallet = await KeyPair.sr25519.fromUri("//Alice"); -print('Alice\' wallet: ${wallet.address}'); - -// Get information necessary to build a proper extrinsic -final runtimeVersion = await polkadot.rpc.state.getRuntimeVersion(); -final currentBlockNumber = (await polkadot.query.system.number()) - 1; -final currentBlockHash = await polkadot.query.system.blockHash(currentBlockNumber); -final genesisHash = await polkadot.query.system.blockHash(0); -final nonce = await polkadot.rpc.system.accountNextIndex(wallet.address); - -// Make the encoded call -final multiAddress = $MultiAddress().id(wallet.publicKey.bytes); -final transferCall = polkadot.tx.balances.transferKeepAlive(dest: multiAddress, value: BigInt.one).encode(); - -// Make the payload -final payload = SigningPayload( - method: transferCall, - specVersion: runtimeVersion.specVersion, - transactionVersion: runtimeVersion.transactionVersion, - genesisHash: encodeHex(genesisHash), - blockHash: encodeHex(currentBlockHash), - blockNumber: currentBlockNumber, - eraPeriod: 64, - nonce: nonce, - tip: 0, -).encode(polkadot.registry); - -// Sign the payload and build the final extrinsic -final signature = wallet.sign(payload); -final extrinsic = ExtrinsicPayload( - signer: wallet.bytes(), - method: transferCall, - signature: signature, - eraPeriod: 64, - blockNumber: currentBlockNumber, - nonce: nonce, - tip: 0, -).encode(polkadot.registry, SignatureType.sr25519); - -// Send the extrinsic to the blockchain -final author = AuthorApi(provider); -await author.submitAndWatchExtrinsic(extrinsic, (data) { - print(data); -}); +At a minimum, you need the following packages before you install Rust: + +```text +clang curl git make ``` -## Where to Go Next +Because the blockchain requires standard cryptography to support the generation of public/private key pairs and the validation of transaction signatures, you must also have a package that provides cryptography, such as `libssl-dev` or `openssl-devel`. -To dive deeper into Polkadart, refer to the [official Polkadart documentation](https://polkadart.dev/){target=\_blank}, where you can find comprehensive guides for common use cases and advanced usage. +### Install Required Packages and Rust {: #install-required-packages-and-rust-linux } +To install the Rust toolchain on Linux: ---- +1. Open a terminal shell. +2. Check the packages installed on the local computer by running the appropriate package management command for your Linux distribution. +3. Add any package dependencies you are missing to your local development environment by running the appropriate package management command for your Linux distribution: -Page Title: Polkadot Omni Node + === "Ubuntu" -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/omninode/ -- Summary: Run parachain nodes easily with the polkadot-omni-node, a white-labeled binary that can run parachain nodes using a single pre-built solution. + ```bash + sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler + ``` -# Polkadot Omni Node + === "Debian" -## Introduction + ```sh + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler + ``` -The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\_blank} file, allowing it to adapt dynamically to different parachains. + === "Arch" -This approach enables it to act as a white-labeled node binary, capable of running most parachains that do not require custom node-level logic or extensions. Developers can leverage this flexibility to test, deploy, or operate parachain nodes without maintaining a dedicated codebase for each network. + ```sh + pacman -Syu --needed --noconfirm curl git clang make protobuf + ``` -This guide provides step-by-step instructions for installing the `polkadot-omni-node`, obtaining a chain specification, and spinning up a parachain node. + === "Fedora" -## Prerequisites + ```sh + sudo dnf update + sudo dnf install clang curl git openssl-devel make protobuf-compiler + ``` -Before getting started, ensure you have the following prerequisites: + === "OpenSUSE" -- **[Rust](https://rust-lang.org/tools/install/){target=\_blank}**: Required to build and install the `polkadot-omni-node` binary. + ```sh + sudo zypper install clang curl git openssl-devel llvm-devel libudev-devel make protobuf + ``` -Ensure Rust's `cargo` command is available in your terminal by running: + Remember that different distributions might use different package managers and bundle packages in different ways. For example, depending on your installation selections, Ubuntu Desktop and Ubuntu Server might have different packages and different requirements. However, the packages listed in the command-line examples are applicable to many common Linux distributions, including Debian, Linux Mint, MX Linux, and Elementary OS. -```bash -cargo --version -``` +4. Download the `rustup` installation program and use it to install Rust by running the following command: -## Install Polkadot Omni Node + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -To install `polkadot-omni-node` globally using `cargo`, run: +5. Follow the prompts displayed to proceed with a default installation. +6. Update your current shell to include Cargo by running the following command: -```bash -cargo install --locked polkadot-omni-node@0.7.0 -``` + ```bash + source $HOME/.cargo/env + ``` -This command downloads and installs version 0.7.0 of the binary, making it available system-wide. +7. Verify your installation by running the following command: -To confirm the installation, run: + ```bash + rustc --version + ``` -```bash -polkadot-omni-node --version -``` +8. Configure the Rust toolchain to default to the latest stable version by running the following commands: -You should see the installed version number printed to the terminal, confirming a successful installation. + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src + ``` -## Obtain Chain Specifications +9. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). -The `polkadot-omni-node` binary uses a chain specification file to configure and launch a parachain node. This file defines the parachain's genesis state and network settings. +## Install Dependencies: Windows (WSL) -The most common source for official chain specifications is the [`paritytech/chainspecs`](https://github.com/paritytech/chainspecs){target=\_blank} repository. These specifications are also browsable in a user-friendly format via the [Chainspec Collection](https://paritytech.github.io/chainspecs/){target=\_blank} website. +In general, UNIX-based operating systems—like macOS or Linux—provide a better development environment for building Substrate-based blockchains. -To obtain a chain specification: +However, suppose your local computer uses Microsoft Windows instead of a UNIX-based operating system. In that case, you can configure it with additional software to make it a suitable development environment for building Substrate-based blockchains. To prepare a development environment on a Microsoft Windows computer, you can use Windows Subsystem for Linux (WSL) to emulate a UNIX operating environment. -1. Visit the [Chainspec Collection](https://paritytech.github.io/chainspecs/){target=\_blank} website. -2. Find the parachain you want to run. -3. Click the chain spec to open it. -4. Copy the JSON content and save it locally as a `.json` file, e.g., `chain_spec.json`. +### Before You Begin {: #before-you-begin-windows-wls } -## Run a Parachain Full Node +Before installing on Microsoft Windows, verify the following basic requirements: -Once you've installed `polkadot-omni-node` and saved the appropriate chain specification file, you can start a full node for your chosen parachain. +- You have a computer running a supported Microsoft Windows operating system: + - **For Windows desktop**: You must be running Microsoft Windows 10, version 2004 or later, or Microsoft Windows 11 to install WSL. + - **For Windows server**: You must be running Microsoft Windows Server 2019, or later, to install WSL on a server operating system. +- You have a good internet connection and access to a shell terminal on your local computer. -To see all available flags and configuration options, run: +### Set Up Windows Subsystem for Linux -```bash -polkadot-omni-node --help -``` +WSL enables you to emulate a Linux environment on a computer that uses the Windows operating system. The primary advantage of this approach for Substrate development is that you can use all of the code and command-line examples as described in the Substrate documentation. For example, you can run common commands—such as `ls` and `ps`—unmodified. By using WSL, you can avoid configuring a virtual machine image or a dual-boot operating system. -To launch the node, run the following command, replacing `./INSERT_PARACHAIN_CHAIN_SPEC.json` with the actual path to your saved chain spec file. +To prepare a development environment using WSL: -This command will: +1. Check your Windows version and build number to see if WSL is enabled by default. -- Load the chain specification. -- Initialize the node using the provided network configuration. -- Begin syncing with the parachain network. + If you have Microsoft Windows 10, version 2004 (Build 19041 and higher), or Microsoft Windows 11, WSL is available by default and you can continue to the next step. -```bash -polkadot-omni-node --chain ./INSERT_PARACHAIN_CHAIN_SPEC.json --sync warp -``` + If you have an older version of Microsoft Windows installed, see the [WSL manual installation steps for older versions](https://learn.microsoft.com/en-us/windows/wsl/install-manual){target=\_blank}. If you are installing on an older version of Microsoft Windows, you can download and install WLS 2 if your computer has Windows 10, version 1903 or higher. -- The `--chain` flag tells the `polkadot-omni-node` which parachain to run by pointing to its chain specification file. -- The `--sync warp` flag enables warp sync, allowing the node to quickly catch up to the latest finalized state. Historical blocks are fetched in the background as the node continues operating. +2. Select **Windows PowerShell** or **Command Prompt** from the **Start** menu, right-click, then **Run as administrator**. -Once started, the node will begin connecting to peers and syncing with the network. You’ll see logs in your terminal reflecting its progress. +3. In the PowerShell or Command Prompt terminal, run the following command: -## Interact with the Node + ```bash + wsl --install + ``` -By default, `polkadot-omni-node` exposes a WebSocket endpoint at `ws://localhost:9944`, which you can use to interact with the running node. You can connect using: + This command enables the required WSL 2 components that are part of the Windows operating system, downloads the latest Linux kernel, and installs the Ubuntu Linux distribution by default. -- **[Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank}**: A web-based interface for exploring and interacting with Polkadot SDK-based chains. -- Custom scripts using compatible [libraries](/develop/toolkit/api-libraries/){target=\_blank}. + If you want to review the other Linux distributions available, run the following command: -Once connected, you can review blocks, call extrinsics, inspect storage, and interact with the runtime. + ```bash + wsl --list --online + ``` -## Parachain Compatibility +4. After the distribution is downloaded, close the terminal. -The `polkadot-omni-node` is designed to work with most parachains out of the box; however, your parachain's runtime must meet specific requirements and follow certain conventions to be compatible. This section outlines what your runtime needs to implement and configure to work seamlessly with the `polkadot-omni-node`: +5. Click the **Start** menu, select **Shut down or sign out**, then click **Restart** to restart the computer. -- Your runtime must implement the required runtime APIs (see below). -- Your runtime must include and configure the required pallets. + Restarting the computer is required to start the installation of the Linux distribution. It can take a few minutes for the installation to complete after you restart. -The [`parachain-template`](https://github.com/paritytech/polkadot-sdk-parachain-template/tree/v0.0.4){target=_blank} provides a complete reference implementation that is fully compatible with the `polkadot-omni-node`. You can use it as a starting point or reference for ensuring your runtime meets all compatibility requirements. + For more information about setting up WSL as a development environment, see the [Set up a WSL development environment](https://learn.microsoft.com/en-us/windows/wsl/setup/environment){target=\_blank} docs. -### Required Runtime APIs +### Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls } -Your parachain runtime must implement the following runtime APIs for the `polkadot-omni-node` to function properly: +To install the Rust toolchain on WSL: -- **GetParachainInfo Runtime API**: The omni-node requires the [`GetParachainInfo`](https://paritytech.github.io/polkadot-sdk/master/cumulus_primitives_core/trait.GetParachainInfo.html){target=\_blank} runtime API to identify and configure the parachain correctly. This API provides the parachain ID to the node. +1. Click the **Start** menu, then select **Ubuntu**. +2. Type a UNIX user name to create a user account. +3. Type a password for your UNIX user, then retype the password to confirm it. +4. Download the latest updates for the Ubuntu distribution using the Ubuntu Advanced Packaging Tool (`apt`) by running the following command: - ```rust title="runtime/src/apis.rs" - impl cumulus_primitives_core::GetParachainInfo for Runtime { - fn parachain_id() -> cumulus_primitives_core::ParaId { - // Return your parachain ID - ParachainInfo::parachain_id() - } - } + ```bash + sudo apt update ``` -- **Aura Runtime API**: For consensus, the `polkadot-omni-node` expects the [Aura runtime API](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/apis/trait.AuraApi.html){target=\_blank} to be implemented. - - ```rust title="runtime/src/apis.rs" - impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION) - } +5. Add the required packages for the Ubuntu distribution by running the following command: - fn authorities() -> Vec { - Aura::authorities().into_inner() - } - } + ```bash + sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler ``` -### Required Pallets +6. Download the `rustup` installation program and use it to install Rust for the Ubuntu distribution by running the following command: -Your runtime must include and properly configure the following pallets: + ```bash + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + ``` -- **System Pallet**: The System pallet ([`frame-system`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/prelude/frame_system/index.html){target=\_blank}) is fundamental and must be configured with appropriate types. +7. Follow the prompts displayed to proceed with a default installation. - ```rust title="runtime/src/lib.rs" - #[frame_support::runtime] - impl frame_system::Config for Runtime { - type Block = Block; - type BlockNumber = BlockNumber; - // ... other configurations - } +8. Update your current shell to include Cargo by running the following command: - // Must be named "System" for omni-node compatibility - pub type System = frame_system::Pallet; + ```bash + source ~/.cargo/env ``` -- **ParachainSystem Pallet**: This pallet ([`cumulus-pallet-parachain-system`](https://paritytech.github.io/polkadot-sdk/master/cumulus_pallet_parachain_system/index.html){target=\_blank}) enables parachain functionality and handles low-level details of being a parachain. +9. Verify your installation by running the following command: - ```rust title="runtime/src/lib.rs" - impl cumulus_pallet_parachain_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - // ... other configurations - } + ```bash + rustc --version + ``` - // Must be named "ParachainSystem" for omni-node compatibility - pub type ParachainSystem = cumulus_pallet_parachain_system::Pallet; +10. Configure the Rust toolchain to use the latest stable version as the default toolchain by running the following commands: + + ```bash + rustup default stable + rustup update + rustup target add wasm32-unknown-unknown + rustup component add rust-src ``` -- **Aura Pallet**: For block authoring consensus ([`pallet-aura`](https://paritytech.github.io/polkadot-sdk/master/pallet_aura/index.html){target=\_blank}). +11. Proceed to [Build the Polkadot SDK](#build-the-polkadot-sdk). - ```rust title="runtime/src/lib.rs" - impl pallet_aura::Config for Runtime { - type AuthorityId = AuraId; - type DisabledValidators = (); - type MaxAuthorities = MaxAuthorities; - type AllowMultipleBlocksPerSlot = ConstBool; - } +## Build the Polkadot SDK - pub type Aura = pallet_aura::Pallet; - ``` +After installing all dependencies, you can now clone and compile the Polkadot SDK repository to verify your setup. -- **ParachainInfo Pallet**: Provides parachain metadata ([`parachain-info`](https://paritytech.github.io/polkadot-sdk/master/staging_parachain_info/index.html){target=\_blank}). +### Clone the Polkadot SDK - ```rust title="runtime/src/lib.rs" - impl parachain_info::Config for Runtime {} +1. Clone the Polkadot SDK repository: - pub type ParachainInfo = parachain_info::Pallet; + ```bash + git clone https://github.com/paritytech/polkadot-sdk.git ``` -If you're migrating an existing parachain to use the `polkadot-omni-node`, you may need to perform runtime upgrades to add the required runtime APIs and pallets. Follow the standard parachain [runtime upgrade](/parachains/runtime-maintenance/runtime-upgrades/){target=\_blank} procedures to implement these changes on your live network. +2. Navigate into the project directory: + ```bash + cd polkadot-sdk + ``` ---- +### Compile the Polkadot SDK -Page Title: Polkadot SDK Accounts +Compile the entire Polkadot SDK repository to ensure your environment is properly configured: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/accounts/ -- Summary: Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. +```bash +cargo build --release --locked +``` -# Accounts +!!!note + This initial compilation will take significant time, depending on your machine specifications. It compiles all components of the Polkadot SDK to verify your toolchain is correctly configured. -## Introduction +### Verify the Build -Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains. +Once the build completes successfully, verify the installation by checking the compiled binaries: -This page will guide you through the essential aspects of accounts, including their data structure, balance types, reference counters, and address formats. You’ll learn how accounts are managed within the runtime, how balances are categorized, and how addresses are encoded and validated. +```bash +ls target/release +``` -## Account Data Structure +You should see several binaries, including: -Accounts are foundational to any blockchain, and the Polkadot SDK provides a flexible management system. This section explains how the Polkadot SDK defines accounts and manages their lifecycle through data structures within the runtime. +- `polkadot`: The Polkadot relay chain node. +- `polkadot-parachain`: The parachain collator node. +- `polkadot-omni-node`:The omni node for running parachains. +- `substrate-node`: The kitchensink node with many pre-configured pallets. -### Account +Verify the Polkadot binary works by checking its version: -The [`Account` data type](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/type.Account.html){target=\_blank} is a storage map within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank} that links an account ID to its corresponding data. This structure is fundamental for mapping account-related information within the chain. +```bash +./target/release/polkadot --version +``` -The code snippet below shows how accounts are defined: +This should display version information similar to: -```rs - /// The full account information for a particular account ID. - #[pallet::storage] - #[pallet::getter(fn account)] - pub type Account = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - AccountInfo, - ValueQuery, - >; +```bash +polkadot 1.16.0-1234abcd567 ``` -The preceding code block defines a storage map named `Account`. The `StorageMap` is a type of on-chain storage that maps keys to values. In the `Account` map, the key is an account ID, and the value is the account's information. Here, `T` represents the generic parameter for the runtime configuration, which is defined by the pallet's configuration trait (`Config`). - -The `StorageMap` consists of the following parameters: +If you see the version output without errors, your development environment is correctly configured and ready for Polkadot SDK development! -- **`_`**: Used in macro expansion and acts as a placeholder for the storage prefix type. Tells the macro to insert the default prefix during expansion. -- **`Blake2_128Concat`**: The hashing function applied to keys in the storage map. -- **`T: :AccountId`**: Represents the key type, which corresponds to the account’s unique ID. -- **`AccountInfo`**: The value type stored in the map. For each account ID, the map stores an `AccountInfo` struct containing: +## Optional: Run the Kitchensink Node - - **`T::Nonce`**: A nonce for the account, which is incremented with each transaction to ensure transaction uniqueness. - - **`T: :AccountData`**: Custom account data defined by the runtime configuration, which could include balances, locked funds, or other relevant information. - -- **`ValueQuery`**: Defines how queries to the storage map behave when no value is found; returns a default value instead of `None`. - -For a detailed explanation of storage maps, see the [`StorageMap`](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/struct.StorageMap.html){target=\_blank} entry in the Rust docs. - -### Account Info - -The `AccountInfo` structure is another key element within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank}, providing more granular details about each account's state. This structure tracks vital data, such as the number of transactions and the account’s relationships with other modules. - -```rs -/// Information of an account. -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct AccountInfo { - /// The number of transactions this account has sent. - pub nonce: Nonce, - /// The number of other modules that currently depend on this account's existence. The account - /// cannot be reaped until this is zero. - pub consumers: RefCount, - /// The number of other modules that allow this account to exist. The account may not be reaped - /// until this and `sufficients` are both zero. - pub providers: RefCount, - /// The number of modules that allow this account to exist for their own purposes only. The - /// account may not be reaped until this and `providers` are both zero. - pub sufficients: RefCount, - /// The additional data that belongs to this account. Used to store the balance(s) in a lot of - /// chains. - pub data: AccountData, -} -``` +The Polkadot SDK includes a feature-rich node called "kitchensink" located at `substrate/bin/node`. This node comes pre-configured with many pallets and features from the Polkadot SDK, making it an excellent reference for exploring capabilities and understanding how different components work together. -The `AccountInfo` structure includes the following components: +!!!note + If you've already compiled the Polkadot SDK in the previous step, the `substrate-node` binary is already built and ready to use. You can skip directly to running the node. -- **`nonce`**: Tracks the number of transactions initiated by the account, which ensures transaction uniqueness and prevents replay attacks. -- **`consumers`**: Counts how many other modules or pallets rely on this account’s existence. The account cannot be removed from the chain (reaped) until this count reaches zero. -- **`providers`**: Tracks how many modules permit this account’s existence. An account can only be reaped once both `providers` and `sufficients` are zero. -- **`sufficients`**: Represents the number of modules that allow the account to exist for internal purposes, independent of any other modules. -- **`AccountData`**: A flexible data structure that can be customized in the runtime configuration, usually containing balances or other user-specific data. +### Run the Kitchensink Node in Development Mode -This structure helps manage an account's state and prevents its premature removal while it is still referenced by other on-chain data or modules. The [`AccountInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.AccountInfo.html){target=\_blank} structure can vary as long as it satisfies the trait bounds defined by the `AccountData` associated type in the [`frame-system::pallet::Config`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/trait.Config.html){target=\_blank} trait. +From the `polkadot-sdk` root directory, start the kitchensink node in development mode: -### Account Reference Counters +```bash +./target/release/substrate-node --dev +``` -Polkadot SDK uses reference counters to track an account’s dependencies across different runtime modules. These counters ensure that accounts remain active while data is associated with them. +The `--dev` flag enables development mode, which: -The reference counters include: +- Runs a single-node development chain. +- Produces and finalizes blocks automatically. +- Uses pre-configured development accounts (Alice, Bob, etc.). +- Deletes all data when stopped, ensuring a clean state on restart. -- **`consumers`**: Prevents account removal while other pallets still rely on the account. -- **`providers`**: Ensures an account is active before other pallets store data related to it. -- **`sufficients`**: Indicates the account’s independence, ensuring it can exist even without a native token balance, such as when holding sufficient alternative assets. -#### Providers Reference Counters +You should see log output indicating the node is running and producing blocks, with increasing block numbers after `finalized`. -The `providers` counter ensures that an account is ready to be depended upon by other runtime modules. For example, it is incremented when an account has a balance above the existential deposit, which marks the account as active. +### Interact with the Kitchensink Node -The system requires this reference counter to be greater than zero for the `consumers` counter to be incremented, ensuring the account is stable before any dependencies are added. +The kitchensink node is accessible at `ws://localhost:9944`. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your browser to explore its features and connect to the local node. -#### Consumers Reference Counters +1. Click the network icon in the top left corner. +2. Scroll to **Development** and select **Local Node**. +3. Click **Switch** to connect to your local node. -The `consumers` counter ensures that the account cannot be reaped until all references to it across the runtime have been removed. This check prevents the accidental deletion of accounts that still have active on-chain data. +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-1.webp) -It is the user’s responsibility to clear out any data from other runtime modules if they wish to remove their account and reclaim their existential deposit. +Once connected, the interface updates its color scheme to indicate a successful connection to the local node. -#### Sufficients Reference Counter +![](/images/parachains/install-polkadot-sdk/install-polkadot-sdk-2.webp) -The `sufficients` counter tracks accounts that can exist independently without relying on a native account balance. This is useful for accounts holding other types of assets, like tokens, without needing a minimum balance in the native token. +You can now explore the various pallets and features included in the kitchensink node, making it a valuable reference as you develop your own blockchain applications. -For instance, the [Assets pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank}, may increment this counter for an account holding sufficient tokens. +To stop the node, press `Control-C` in the terminal. -#### Account Deactivation +## Where to Go Next -In Polkadot SDK-based chains, an account is deactivated when its reference counters (such as `providers`, `consumers`, and `sufficient`) reach zero. These counters ensure the account remains active as long as other runtime modules or pallets reference it. +
    -When all dependencies are cleared and the counters drop to zero, the account becomes deactivated and may be removed from the chain (reaped). This is particularly important in Polkadot SDK-based blockchains, where accounts with balances below the existential deposit threshold are pruned from storage to conserve state resources. +- __Get Started with Parachain Development__ -Each pallet that references an account has cleanup functions that decrement these counters when the pallet no longer depends on the account. Once these counters reach zero, the account is marked for deactivation. + --- -#### Updating Counters + Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. -The Polkadot SDK provides runtime developers with various methods to manage account lifecycle events, such as deactivation or incrementing reference counters. These methods ensure that accounts cannot be reaped while still in use. + [:octicons-arrow-right-24: Get Started](/parachains/get-started/) + +
    -The following helper functions manage these counters: -- **`inc_consumers()`**: Increments the `consumer` reference counter for an account, signaling that another pallet depends on it. -- **`dec_consumers()`**: Decrements the `consumer` reference counter, signaling that a pallet no longer relies on the account. -- **`inc_providers()`**: Increments the `provider` reference counter, ensuring the account remains active. -- **`dec_providers()`**: Decrements the `provider` reference counter, allowing for account deactivation when no longer in use. -- **`inc_sufficients()`**: Increments the `sufficient` reference counter for accounts that hold sufficient assets. -- **`dec_sufficients()`**: Decrements the `sufficient` reference counter. +--- -To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. +Page Title: JSON-RPC APIs -The `System` pallet offers three query functions to assist developers in tracking account states: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/for-eth-devs/json-rpc-apis/ +- Summary: JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. -- **[`can_inc_consumer()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_inc_consumer){target=\_blank}**: Checks if the account can safely increment the consumer reference. -- **[`can_dec_provider()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_dec_provider){target=\_blank}**: Ensures that no consumers exist before allowing the decrement of the provider counter. -- **[`is_provider_required()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.is_provider_required){target=\_blank}**: Verifies whether the account still has any active consumer references. +# JSON-RPC APIs -This modular and flexible system of reference counters tightly controls the lifecycle of accounts in Polkadot SDK-based blockchains, preventing the accidental removal or retention of unneeded accounts. You can refer to the [System pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html){target=\_blank} for more details. - +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -## Account Balance Types +Polkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\_blank} and provides examples of how to use them. -In the Polkadot ecosystem, account balances are categorized into different types based on how the funds are utilized and their availability. These balance types determine the actions that can be performed, such as transferring tokens, paying transaction fees, or participating in governance activities. Understanding these balance types helps developers manage user accounts and implement balance-dependent logic. +This guide uses the Polkadot Hub TestNet endpoint: -!!! note "A more efficient distribution of account balance types is in development" - Soon, pallets in the Polkadot SDK will implement the [`Fungible` trait](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} (see the [tracking issue](https://github.com/paritytech/polkadot-sdk/issues/226){target=\_blank} for more details). For example, the [`transaction-storage`](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_storage/index.html){target=\_blank} pallet changed the implementation of the [`Currency`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/currency/index.html){target=\_blank} trait (see the [Refactor transaction storage pallet to use fungible traits](https://github.com/paritytech/polkadot-sdk/pull/1800){target=\_blank} PR for further details): +```text +https://testnet-passet-hub-eth-rpc.polkadot.io +``` - ```rust - type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - ``` - - To the [`Fungible`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} trait: +## Available Methods - ```rust - type BalanceOf = <::Currency as FnInspect<::AccountId>>::Balance; - ``` - - This update will enable more efficient use of account balances, allowing the free balance to be utilized for on-chain activities such as setting proxies and managing identities. +### eth_accounts -### Balance Types +Returns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\_blank}. -The five main balance types are: +**Parameters**: -- **Free balance**: Represents the total tokens available to the account for any on-chain activity, including staking, governance, and voting. However, it may not be fully spendable or transferrable if portions of it are locked or reserved. -- **Locked balance**: Portions of the free balance that cannot be spent or transferred because they are tied up in specific activities like [staking](https://wiki.polkadot.com/learn/learn-staking/#nominating-validators){target=\_blank}, [vesting](https://wiki.polkadot.com/learn/learn-guides-transfers/#vested-transfers-with-the-polkadot-js-ui){target=\_blank}, or participating in [governance](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank}. While the tokens remain part of the free balance, they are non-transferable for the duration of the lock. -- **Reserved balance**: Funds locked by specific system actions, such as setting up an [identity](https://wiki.polkadot.com/learn/learn-identity/){target=\_blank}, creating [proxies](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}, or submitting [deposits for governance proposals](https://wiki.polkadot.com/learn/learn-guides-polkadot-opengov/#claiming-opengov-deposits){target=\_blank}. These tokens are not part of the free balance and cannot be spent unless they are unreserved. -- **Spendable balance**: The portion of the free balance that is available for immediate spending or transfers. It is calculated by subtracting the maximum of locked or reserved amounts from the free balance, ensuring that existential deposit limits are met. -- **Untouchable balance**: Funds that cannot be directly spent or transferred but may still be utilized for on-chain activities, such as governance participation or staking. These tokens are typically tied to certain actions or locked for a specific period. +None. -The spendable balance is calculated as follows: +**Example**: -```text -spendable = free - max(locked - reserved, ED) +```bash title="eth_accounts" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_accounts", + "params":[], + "id":1 +}' ``` -Here, `free`, `locked`, and `reserved` are defined above. The `ED` represents the [existential deposit](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank}, the minimum balance required to keep an account active and prevent it from being reaped. You may find you can't see all balance types when looking at your account via a wallet. Wallet providers often display only spendable, locked, and reserved balances. - -### Locks +--- -Locks are applied to an account's free balance, preventing that portion from being spent or transferred. Locks are automatically placed when an account participates in specific on-chain activities, such as staking or governance. Although multiple locks may be applied simultaneously, they do not stack. Instead, the largest lock determines the total amount of locked tokens. +### eth_blockNumber -Locks follow these basic rules: +Returns the number of the most recent block. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_blocknumber){target=\_blank}. -- If different locks apply to varying amounts, the largest lock amount takes precedence. -- If multiple locks apply to the same amount, the lock with the longest duration governs when the balance can be unlocked. +**Parameters**: -#### Locks Example +None. -Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: +**Example**: -- 80 DOT is staked with a 28-day lock period. -- 24 DOT is locked for governance with a 1x conviction and a 7-day lock period. -- 4 DOT is locked for governance with a 6x conviction and a 224-day lock period. +```bash title="eth_blockNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_blockNumber", + "params":[], + "id":1 +}' +``` -In this case, the total locked amount is 80 DOT because only the largest lock (80 DOT from staking) governs the locked balance. These 80 DOT will be released at different times based on the lock durations. In this example, the 24 DOT locked for governance will be released first since the shortest lock period is seven days. The 80 DOT stake with a 28-day lock period is released next. Now, all that remains locked is the 4 DOT for governance. After 224 days, all 80 DOT (minus the existential deposit) will be free and transferable. +--- -![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) +### eth_call -#### Edge Cases for Locks +Executes a new message call immediately without creating a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_call){target=\_blank}. -In scenarios where multiple convictions and lock periods are active, the lock duration and amount are determined by the longest period and largest amount. For example, if you delegate with different convictions and attempt to undelegate during an active lock period, the lock may be extended for the full amount of tokens. For a detailed discussion on edge case lock behavior, see this [Stack Exchange post](https://substrate.stackexchange.com/questions/5067/delegating-and-undelegating-during-the-lock-period-extends-it-for-the-initial-am){target=\_blank}. +**Parameters**: -### Balance Types on Polkadot.js +- **`transaction` ++"object"++**: The transaction call object. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -Polkadot.js provides a user-friendly interface for managing and visualizing various account balances on Polkadot and Kusama networks. When interacting with Polkadot.js, you will encounter multiple balance types that are critical for understanding how your funds are distributed and restricted. This section explains how different balances are displayed in the Polkadot.js UI and what each type represents. +**Example**: -![](/images/reference/parachains/accounts/accounts-02.webp) +```bash title="eth_call" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_call", + "params":[{ + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_CALL" + }, "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -The most common balance types displayed on Polkadot.js are: +Ensure to replace the `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper values. -- **Total balance**: The total number of tokens available in the account. This includes all tokens, whether they are transferable, locked, reserved, or vested. However, the total balance does not always reflect what can be spent immediately. In this example, the total balance is 0.6274 KSM. +--- -- **Transferable balance**: Shows how many tokens are immediately available for transfer. It is calculated by subtracting the locked and reserved balances from the total balance. For example, if an account has a total balance of 0.6274 KSM and a transferable balance of 0.0106 KSM, only the latter amount can be sent or spent freely. +### eth_chainId -- **Vested balance**: Tokens that allocated to the account but released according to a specific schedule. Vested tokens remain locked and cannot be transferred until fully vested. For example, an account with a vested balance of 0.2500 KSM means that this amount is owned but not yet transferable. +Returns the chain ID used for signing transactions. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_chainid){target=\_blank}. -- **Locked balance**: Tokens that are temporarily restricted from being transferred or spent. These locks typically result from participating in staking, governance, or vested transfers. In Polkadot.js, locked balances do not stack—only the largest lock is applied. For instance, if an account has 0.5500 KSM locked for governance and staking, the locked balance would display 0.5500 KSM, not the sum of all locked amounts. +**Parameters**: -- **Reserved balance**: Refers to tokens locked for specific on-chain actions, such as setting an identity, creating a proxy, or making governance deposits. Reserved tokens are not part of the free balance, but can be freed by performing certain actions. For example, removing an identity would unreserve those funds. +None. -- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period. +**Example**: -- **Redeemable balance**: The number of tokens that have completed the unbonding period and are ready to be unlocked and transferred again. For example, if an account has a redeemable balance of 0.1000 KSM, those tokens are now available for spending. +```bash title="eth_chainId" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_chainId", + "params":[], + "id":1 +}' +``` -- **Democracy balance**: Reflects the number of tokens locked for governance activities, such as voting on referenda. These tokens are locked for the duration of the governance action and are only released after the lock period ends. +--- -By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. +### eth_estimateGas -## Address Formats +Estimates gas required for a transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_estimategas){target=\_blank}. -The SS58 address format is a core component of the Polkadot SDK that enables accounts to be uniquely identified across Polkadot-based networks. This format is a modified version of Bitcoin's Base58Check encoding, specifically designed to accommodate the multi-chain nature of the Polkadot ecosystem. SS58 encoding allows each chain to define its own set of addresses while maintaining compatibility and checksum validation for security. +**Parameters**: -### Basic Format +- **`transaction` ++"object"++**: The transaction call object. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -SS58 addresses consist of three main components: +**Example**: -```text -base58encode(concat(,
    , )) +```bash title="eth_estimateGas" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_estimateGas", + "params":[{ + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_FUNCTION_CALL" + }], + "id":1 +}' ``` -- **Address type**: A byte or set of bytes that define the network (or chain) for which the address is intended. This ensures that addresses are unique across different Polkadot SDK-based chains. -- **Address**: The public key of the account encoded as bytes. -- **Checksum**: A hash-based checksum which ensures that addresses are valid and unaltered. The checksum is derived from the concatenated address type and address components, ensuring integrity. - -The encoding process transforms the concatenated components into a Base58 string, providing a compact and human-readable format that avoids easily confused characters (e.g., zero '0', capital 'O', lowercase 'l'). This encoding function ([`encode`](https://docs.rs/bs58/latest/bs58/fn.encode.html){target=\_blank}) is implemented exactly as defined in Bitcoin and IPFS specifications, using the same alphabet as both implementations. +Ensure to replace the `INSERT_RECIPIENT_ADDRESS` and `INSERT_ENCODED_CALL` with the proper values. -For more details about the SS58 address format implementation, see the [`Ss58Codec`](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Ss58Codec.html){target=\_blank} trait in the Rust Docs. +--- -### Address Type +### eth_gasPrice -The address type defines how an address is interpreted and to which network it belongs. Polkadot SDK uses different prefixes to distinguish between various chains and address formats: +Returns the current gas price in Wei. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gasprice){target=\_blank}. -- **Address types `0-63`**: Simple addresses, commonly used for network identifiers. -- **Address types `64-127`**: Full addresses that support a wider range of network identifiers. -- **Address types `128-255`**: Reserved for future address format extensions. +**Parameters**: -For example, Polkadot’s main network uses an address type of 0, while Kusama uses 2. This ensures that addresses can be used without confusion between networks. +None. -The address type is always encoded as part of the SS58 address, making it easy to quickly identify the network. Refer to the [SS58 registry](https://github.com/paritytech/ss58-registry){target=\_blank} for the canonical listing of all address type identifiers and how they map to Polkadot SDK-based networks. +**Example**: -### Address Length +```bash title="eth_gasPrice" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_gasPrice", + "params":[], + "id":1 +}' +``` -SS58 addresses can have different lengths depending on the specific format. Address lengths range from as short as 3 to 35 bytes, depending on the complexity of the address and network requirements. This flexibility allows SS58 addresses to adapt to different chains while providing a secure encoding mechanism. +--- -| Total | Type | Raw account | Checksum | -|-------|------|-------------|----------| -| 3 | 1 | 1 | 1 | -| 4 | 1 | 2 | 1 | -| 5 | 1 | 2 | 2 | -| 6 | 1 | 4 | 1 | -| 7 | 1 | 4 | 2 | -| 8 | 1 | 4 | 3 | -| 9 | 1 | 4 | 4 | -| 10 | 1 | 8 | 1 | -| 11 | 1 | 8 | 2 | -| 12 | 1 | 8 | 3 | -| 13 | 1 | 8 | 4 | -| 14 | 1 | 8 | 5 | -| 15 | 1 | 8 | 6 | -| 16 | 1 | 8 | 7 | -| 17 | 1 | 8 | 8 | -| 35 | 1 | 32 | 2 | +### eth_getBalance -SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. +Returns the balance of a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getbalance){target=\_blank}. -### Checksum Types +**Parameters**: -A checksum is applied to validate SS58 addresses. Polkadot SDK uses a Blake2b-512 hash function to calculate the checksum, which is appended to the address before encoding. The checksum length can vary depending on the address format (e.g., 1-byte, 2-byte, or longer), providing varying levels of validation strength. +- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. +**Example**: -### Validating Addresses +```bash title="eth_getBalance" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBalance", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -SS58 addresses can be validated using the subkey command-line interface or the Polkadot.js API. These tools help ensure an address is correctly formatted and valid for the intended network. The following sections will provide an overview of how validation works with these tools. +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. -#### Using Subkey +--- -[Subkey](https://paritytech.github.io/polkadot-sdk/master/subkey/index.html){target=\_blank} is a CLI tool provided by Polkadot SDK for generating and managing keys. It can inspect and validate SS58 addresses. +### eth_getBlockByHash -The `inspect` command gets a public key and an SS58 address from the provided secret URI. The basic syntax for the `subkey inspect` command is: +Returns information about a block by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash){target=\_blank}. -```bash -subkey inspect [flags] [options] uri -``` +**Parameters**: -For the `uri` command-line argument, you can specify the secret seed phrase, a hex-encoded private key, or an SS58 address. If the input is a valid address, the `subkey` program displays the corresponding hex-encoded public key, account identifier, and SS58 addresses. +- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. -For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: +**Example**: -```bash -subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" +```bash title="eth_getBlockByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockByHash", + "params":["INSERT_BLOCK_HASH", INSERT_BOOLEAN], + "id":1 +}' ``` -The command displays output similar to the following: +Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_BOOLEAN` with the proper values. -
    - subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" - Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account: - Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849 - Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR - Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - SS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR -
    +--- -The `subkey` program assumes an address is based on a public/private key pair. If you inspect an address, the command returns the 32-byte account identifier. +### eth_getBlockByNumber -However, not all addresses in Polkadot SDK-based networks are based on keys. +Returns information about a block by its number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbynumber){target=\_blank}. -Depending on the command-line options you specify and the input you provided, the command output might also display the network for which the address has been encoded. For example: +**Parameters**: -```bash -subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" -``` +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`fullTransactions` ++"boolean"++**: If `true`, returns full transaction details; if `false`, returns only transaction hashes. -The command displays output similar to the following: +**Example**: -
    - subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" - Public Key URI `12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU` is account: - Network ID/Version: polkadot - Public key (hex): 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Account ID: 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Public key (SS58): 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU - SS58 Address: 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU -
    +```bash title="eth_getBlockByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockByNumber", + "params":["INSERT_BLOCK_VALUE", INSERT_BOOLEAN], + "id":1 +}' +``` -#### Using Polkadot.js API +Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_BOOLEAN` with the proper values. -To verify an address in JavaScript or TypeScript projects, you can use the functions built into the [Polkadot.js API](https://polkadot.js.org/docs/){target=\_blank}. For example: +--- -```js -// Import Polkadot.js API dependencies -const { decodeAddress, encodeAddress } = require('@polkadot/keyring'); -const { hexToU8a, isHex } = require('@polkadot/util'); +### eth_getBlockTransactionCountByNumber -// Specify an address to test. -const address = 'INSERT_ADDRESS_TO_TEST'; +Returns the number of transactions in a block from a block number. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbynumber){target=\_blank}. -// Check address -const isValidSubstrateAddress = () => { - try { - encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); +**Parameters**: - return true; - } catch (error) { - return false; - } -}; +- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. -// Query result -const isValid = isValidSubstrateAddress(); -console.log(isValid); +**Example**: +```bash title="eth_getBlockTransactionCountByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockTransactionCountByNumber", + "params":["INSERT_BLOCK_VALUE"], + "id":1 +}' ``` -If the function returns `true`, the specified address is a valid address. - -#### Other SS58 Implementations +Ensure to replace the `INSERT_BLOCK_VALUE` with the proper values. -Support for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries. +--- -- **Crystal**: [`wyhaines/base58.cr`](https://github.com/wyhaines/base58.cr){target=\_blank} -- **Go**: [`itering/subscan-plugin`](https://github.com/itering/subscan-plugin){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **TypeScript**: [`subsquid/squid-sdk`](https://github.com/subsquid/squid-sdk){target=\_blank} +### eth_getBlockTransactionCountByHash +Returns the number of transactions in a block from a block hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblocktransactioncountbyhash){target=\_blank}. ---- +**Parameters**: -Page Title: Polkadot-API +- **`blockHash` ++"string"++**: The hash of the block to retrieve. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/papi/ -- Summary: Polkadot-API (PAPI) is a modular, composable library set designed for efficient interaction with Polkadot chains, prioritizing a "light-client first" approach. +**Example**: -# Polkadot-API +```bash title="eth_getBlockTransactionCountByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getBlockTransactionCountByHash", + "params":["INSERT_BLOCK_HASH"], + "id":1 +}' +``` -## Introduction +Ensure to replace the `INSERT_BLOCK_HASH` with the proper values. -[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications. +--- -PAPI is optimized for light-client functionality, using the new JSON-RPC spec to support decentralized interactions fully. It provides strong TypeScript support with types and documentation generated directly from on-chain metadata, and it offers seamless access to storage reads, constants, transactions, events, and runtime calls. Developers can connect to multiple chains simultaneously and prepare for runtime updates through multi-descriptor generation and compatibility checks. PAPI is lightweight and performant, leveraging native BigInt, dynamic imports, and modular subpaths to avoid bundling unnecessary assets. It supports promise-based and observable-based APIs, integrates easily with Polkadot.js extensions, and offers signing options through browser extensions or private keys. +### eth_getCode -## Get Started +Returns the code at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getcode){target=\_blank}. -### API Instantiation +**Parameters**: -To instantiate the API, you can install the package by using the following command: +- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). -=== "npm" +**Example**: - ```bash - npm i polkadot-api@1.17.2 - ``` +```bash title="eth_getCode" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getCode", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -=== "pnpm" +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - ```bash - pnpm add polkadot-api@1.17.2 - ``` +--- -=== "yarn" +### eth_getLogs - ```bash - yarn add polkadot-api@1.17.2 - ``` +Returns an array of all logs matching a given filter object. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getlogs){target=\_blank}. -Then, obtain the latest metadata from the target chain and generate the necessary types: +**Parameters**: -```bash -# Add the target chain -npx papi add dot -n polkadot -``` +- **`filter` ++"object"++**: The filter object. + - **`fromBlock` ++"string"++**: (Optional) Block number or tag to start from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + - **`toBlock` ++"string"++**: (Optional) Block number or tag to end at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. + - **`address` ++"string" or "array of strings"++**: (Optional) Contract address or a list of addresses from which to get logs. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`topics` ++"array of strings"++**: (Optional) Array of topics for filtering logs. Each topic can be a single [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string or an array of such strings (meaning OR). + - **`blockhash` ++"string"++**: (Optional) Hash of a specific block. Cannot be used with `fromBlock` or `toBlock`. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -The `papi add` command initializes the library by generating the corresponding types needed for the chain used. It assigns the chain a custom name and specifies downloading metadata from the Polkadot chain. You can replace `dot` with the name you prefer or with another chain if you want to add a different one. Once the latest metadata is downloaded, generate the required types: +**Example**: -```bash -# Generate the necessary types -npx papi +```bash title="eth_getLogs" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getLogs", + "params":[{ + "fromBlock": "latest", + "toBlock": "latest" + }], + "id":1 +}' ``` -You can now set up a [`PolkadotClient`](https://github.com/polkadot-api/polkadot-api/blob/main/packages/client/src/types.ts#L153){target=\_blank} with your chosen provider to begin interacting with the API. Choose from Smoldot via WebWorker, Node.js, or direct usage, or connect through the WSS provider. The examples below show how to configure each option for your setup. +--- -=== "Smoldot (WebWorker)" +### eth_getStorageAt - ```typescript - // `dot` is the identifier assigned during `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - import { getSmProvider } from 'polkadot-api/sm-provider'; - import { chainSpec } from 'polkadot-api/chains/polkadot'; - import { startFromWorker } from 'polkadot-api/smoldot/from-worker'; - import SmWorker from 'polkadot-api/smoldot/worker?worker'; +Returns the value from a storage position at a given address. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getstorageat){target=\_blank}. - const worker = new SmWorker(); - const smoldot = startFromWorker(worker); - const chain = await smoldot.addChain({ chainSpec }); +**Parameters**: - // Establish connection to the Polkadot relay chain - const client = createClient(getSmProvider(chain)); +- **`address` ++"string"++**: Contract or account address to query code. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`storageKey` ++"string"++**: Position in storage to retrieve data from. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - // To interact with the chain, obtain the `TypedApi`, which provides - // the necessary types for every API call on this chain - const dotApi = client.getTypedApi(dot); +**Example**: - ``` +```bash title="eth_getStorageAt" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getStorageAt", + "params":["INSERT_ADDRESS", "INSERT_STORAGE_KEY", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` -=== "Smoldot (Node.js)" - - ```typescript - // `dot` is the alias assigned during `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - import { getSmProvider } from 'polkadot-api/sm-provider'; - import { chainSpec } from 'polkadot-api/chains/polkadot'; - import { startFromWorker } from 'polkadot-api/smoldot/from-node-worker'; - import { fileURLToPath } from 'url'; - import { Worker } from 'worker_threads'; - - // Get the path for the worker file in ESM - const workerPath = fileURLToPath( - import.meta.resolve('polkadot-api/smoldot/node-worker'), - ); +Ensure to replace the `INSERT_ADDRESS`, `INSERT_STORAGE_KEY`, and `INSERT_BLOCK_VALUE` with the proper values. - const worker = new Worker(workerPath); - const smoldot = startFromWorker(worker); - const chain = await smoldot.addChain({ chainSpec }); +--- - // Set up a client to connect to the Polkadot relay chain - const client = createClient(getSmProvider(chain)); +### eth_getTransactionCount - // To interact with the chain's API, use `TypedApi` for access to - // all the necessary types and calls associated with this chain - const dotApi = client.getTypedApi(dot); +Returns the number of transactions sent from an address (nonce). [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactioncount){target=\_blank}. - ``` +**Parameters**: -=== "Smoldot" +- **`address` ++"string"++**: Address to query balance. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block). - ```typescript - // `dot` is the alias assigned when running `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - import { getSmProvider } from 'polkadot-api/sm-provider'; - import { chainSpec } from 'polkadot-api/chains/polkadot'; - import { start } from 'polkadot-api/smoldot'; +**Example**: - // Initialize Smoldot client - const smoldot = start(); - const chain = await smoldot.addChain({ chainSpec }); +```bash title="eth_getTransactionCount" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionCount", + "params":["INSERT_ADDRESS", "INSERT_BLOCK_VALUE"], + "id":1 +}' +``` - // Set up a client to connect to the Polkadot relay chain - const client = createClient(getSmProvider(chain)); +Ensure to replace the `INSERT_ADDRESS` and `INSERT_BLOCK_VALUE` with the proper values. - // Access the `TypedApi` to interact with all available chain calls and types - const dotApi = client.getTypedApi(dot); +--- - ``` +### eth_getTransactionByHash -=== "WSS" - - ```typescript - // `dot` is the identifier assigned when executing `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - // Use this import for Node.js environments - import { getWsProvider } from 'polkadot-api/ws-provider/web'; - import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat'; - - // Establish a connection to the Polkadot relay chain - const client = createClient( - // The Polkadot SDK nodes may have compatibility issues; using this enhancer is recommended. - // Refer to the Requirements page for additional details - withPolkadotSdkCompat(getWsProvider('wss://dot-rpc.stakeworld.io')), - ); +Returns information about a transaction by its hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyhash){target=\_blank}. - // To interact with the chain, obtain the `TypedApi`, which provides - // the types for all available calls in that chain - const dotApi = client.getTypedApi(dot); +**Parameters**: - ``` +- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -Now that you have set up the client, you can interact with the chain by reading and sending transactions. +**Example**: -### Reading Chain Data +```bash title="eth_getTransactionByHash" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByHash", + "params":["INSERT_TRANSACTION_HASH"], + "id":1 +}' +``` -The `TypedApi` provides a streamlined way to read blockchain data through three main interfaces, each designed for specific data access patterns: +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. -- **Constants**: Access fixed values or configurations on the blockchain using the `constants` interface. +--- - ```typescript - const version = await typedApi.constants.System.Version(); - ``` +### eth_getTransactionByBlockNumberAndIndex -- **Storage queries**: Retrieve stored values by querying the blockchain’s storage via the `query` interface. +Returns information about a transaction by block number and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblocknumberandindex){target=\_blank}. - ```typescript - const asset = await api.query.ForeignAssets.Asset.getValue( - token.location, - { at: 'best' }, - ); - ``` +**Parameters**: -- **Runtime APIs**: Interact directly with runtime APIs using the `apis` interface. +- **`blockValue` ++"string"++**: The block value to be fetched. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - ```typescript - const metadata = await typedApi.apis.Metadata.metadata(); - ``` +**Example**: -To learn more about the different actions you can perform with the `TypedApi`, refer to the [TypedApi reference](https://papi.how/typed){target=\_blank}. +```bash title="eth_getTransactionByBlockNumberAndIndex" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByBlockNumberAndIndex", + "params":["INSERT_BLOCK_VALUE", "INSERT_TRANSACTION_INDEX"], + "id":1 +}' +``` -### Sending Transactions +Ensure to replace the `INSERT_BLOCK_VALUE` and `INSERT_TRANSACTION_INDEX` with the proper values. -In PAPI, the `TypedApi` provides the `tx` and `txFromCallData` methods to send transactions. +--- -- The `tx` method allows you to directly send a transaction with the specified parameters by using the `typedApi.tx.Pallet.Call` pattern: +### eth_getTransactionByBlockHashAndIndex - ```typescript - const tx: Transaction = typedApi.tx.Pallet.Call({arg1, arg2, arg3}); - ``` +Returns information about a transaction by block hash and transaction index. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionbyblockhashandindex){target=\_blank}. - For instance, to execute the `balances.transferKeepAlive` call, you can use the following snippet: +**Parameters**: - ```typescript - import { MultiAddress } from '@polkadot-api/descriptors'; +- **`blockHash` ++"string"++**: The hash of the block. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`transactionIndex` ++"string"++**: The index of the transaction in the block. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. - const tx: Transaction = typedApi.tx.Balances.transfer_keep_alive({ - dest: MultiAddress.Id('INSERT_DESTINATION_ADDRESS'), - value: BigInt(INSERT_VALUE), - }); +**Example**: - ``` +```bash title="eth_getTransactionByBlockHashAndIndex" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionByBlockHashAndIndex", + "params":["INSERT_BLOCK_HASH", "INSERT_TRANSACTION_INDEX"], + "id":1 +}' +``` - Ensure you replace `INSERT_DESTINATION_ADDRESS` and `INSERT_VALUE` with the actual destination address and value, respectively. +Ensure to replace the `INSERT_BLOCK_HASH` and `INSERT_TRANSACTION_INDEX` with the proper values. -- The `txFromCallData` method allows you to send a transaction using the call data. This option accepts binary call data and constructs the transaction from it. It validates the input upon creation and will throw an error if invalid data is provided. The pattern is as follows: +--- - ```typescript - const callData = Binary.fromHex('0x...'); - const tx: Transaction = typedApi.txFromCallData(callData); - ``` +### eth_getTransactionReceipt - For instance, to execute a transaction using the call data, you can use the following snippet: +Returns the receipt of a transaction by transaction hash. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_gettransactionreceipt){target=\_blank}. - ```typescript - const callData = Binary.fromHex('0x00002470617065726d6f6f6e'); - const tx: Transaction = typedApi.txFromCallData(callData); - ``` +**Parameters**: -For more information about sending transactions, refer to the [Transactions](https://papi.how/typed/tx#transactions){target=\_blank} page. +- **`transactionHash` ++"string"++**: The hash of the transaction. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. -## Where to Go Next +**Example**: -For an in-depth guide on how to use PAPI, refer to the official [PAPI](https://papi.how/){target=\_blank} documentation. +```bash title="eth_getTransactionReceipt" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_getTransactionReceipt", + "params":["INSERT_TRANSACTION_HASH"], + "id":1 +}' +``` +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper values. --- -Page Title: Polkadot.js API - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/polkadot-js-api/ -- Summary: Interact with Polkadot SDK-based chains easily using the Polkadot.js API. Query chain data, submit transactions, and more via JavaScript or Typescript. - -# Polkadot.js API - -!!! warning "Maintenance Mode Only" - The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\_blank} (modern, type-safe API) as actively maintained alternatives. +### eth_maxPriorityFeePerGas -## Introduction +Returns an estimate of the current priority fee per gas, in Wei, to be included in a block. -The [Polkadot.js API](https://github.com/polkadot-js/api){target=\_blank} uses JavaScript/TypeScript to interact with Polkadot SDK-based chains. It allows you to query nodes, read chain state, and submit transactions through a dynamic, auto-generated API interface. +**Parameters**: -### Dynamic API Generation +None. -Unlike traditional static APIs, the Polkadot.js API generates its interfaces automatically when connecting to a node. Here's what happens when you connect: +**Example**: -1. The API connects to your node. -2. It retrieves the chain's metadata. -3. Based on this metadata, it creates specific endpoints in this format: `api...
    `. +```bash title="eth_maxPriorityFeePerGas" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_maxPriorityFeePerGas", + "params":[], + "id":1 +}' +``` -### Available API Categories +--- -You can access three main categories of chain interactions: +### eth_sendRawTransaction -- **[Runtime constants](https://polkadot.js.org/docs/api/start/api.consts){target=\_blank}** (`api.consts`): +Submits a raw transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendrawtransaction){target=\_blank}. - - Access runtime constants directly. - - Returns values immediately without function calls. - - **Example**: `api.consts.balances.existentialDeposit` +**Parameters**: -- **[State queries](https://polkadot.js.org/docs/api/start/api.query/){target=\_blank}** (`api.query`): +- **`callData` ++"string"++**: Signed transaction data. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. - - Read chain state. - - **Example**: `api.query.system.account(accountId)` +**Example**: -- **[Transactions](https://polkadot.js.org/docs/api/start/api.tx/){target=\_blank}** (`api.tx`): - - Submit extrinsics (transactions). - - **Example**: `api.tx.balances.transfer(accountId, value)` +```bash title="eth_sendRawTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_sendRawTransaction", + "params":["INSERT_CALL_DATA"], + "id":1 +}' +``` -The available methods and interfaces will automatically reflect what's possible on your connected chain. +Ensure to replace the `INSERT_CALL_DATA` with the proper values. -## Installation +--- -To add the Polkadot.js API to your project, use the following command to install the version `16.4.7` which supports any Polkadot SDK-based chain: +### eth_sendTransaction -=== "npm" - ```bash - npm i @polkadot/api@16.4.7 - ``` +Creates and sends a new transaction. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_sendtransaction){target=\_blank}. -=== "pnpm" - ```bash - pnpm add @polkadot/api@16.4.7 - ``` +**Parameters**: -=== "yarn" - ```bash - yarn add @polkadot/api@16.4.7 - ``` +- **`transaction` ++"object"++**: The transaction object. + - **`from` ++"string"++**: Address sending the transaction. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`to` ++"string"++**: (Optional) Recipient address. No need to provide this value when deploying a contract. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (optional, default: `90000`) gas limit for execution. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Amount of Ether to send. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`data` ++"string"++**: (Optional) Contract bytecode or encoded method call. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`nonce` ++"string"++**: (Optional) Transaction nonce. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. -For more detailed information about installation, see the [Installation](https://polkadot.js.org/docs/api/start/install/){target=\_blank} section in the official Polkadot.js API documentation. +**Example**: -## Get Started +```bash title="eth_sendTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_sendTransaction", + "params":[{ + "from": "INSERT_SENDER_ADDRESS", + "to": "INSERT_RECIPIENT_ADDRESS", + "gas": "INSERT_GAS_LIMIT", + "gasPrice": "INSERT_GAS_PRICE", + "value": "INSERT_VALUE", + "input": "INSERT_INPUT_DATA", + "nonce": "INSERT_NONCE" + }], + "id":1 +}' +``` -### Creating an API Instance +Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_GAS_LIMIT`, `INSERT_GAS_PRICE`, `INSERT_VALUE`, `INSERT_INPUT_DATA`, and `INSERT_NONCE` with the proper values. -To interact with a Polkadot SDK-based chain, you must establish a connection through an API instance. The API provides methods for querying chain state, sending transactions, and subscribing to updates. +--- -To create an API connection: +### eth_syncing -```js -import { ApiPromise, WsProvider } from '@polkadot/api'; +Returns an object with syncing data or `false` if not syncing. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_syncing){target=\_blank}. -// Create a WebSocket provider -const wsProvider = new WsProvider('wss://rpc.polkadot.io'); +**Parameters**: -// Initialize the API -const api = await ApiPromise.create({ provider: wsProvider }); +None. -// Verify the connection by getting the chain's genesis hash -console.log('Genesis Hash:', api.genesisHash.toHex()); +**Example**: +```bash title="eth_syncing" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"eth_syncing", + "params":[], + "id":1 +}' ``` -!!!warning - All `await` operations must be wrapped in an async function or block since the API uses promises for asynchronous operations. - -### Reading Chain Data - -The API provides several ways to read data from the chain. You can access: - -- **Constants**: Values that are fixed in the runtime and don't change without a runtime upgrade. - - ```js - // Get the minimum balance required for a new account - const minBalance = api.consts.balances.existentialDeposit.toNumber(); - - ``` - -- **State**: Current chain state that updates with each block. +--- - ```js - // Example address - const address = '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE'; +### net_listening - // Get current timestamp - const timestamp = await api.query.timestamp.now(); +Returns `true` if the client is currently listening for network connections, otherwise `false`. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_listening){target=\_blank}. - // Get account information - const { nonce, data: balance } = await api.query.system.account(address); +**Parameters**: - console.log(` - Timestamp: ${timestamp} - Free Balance: ${balance.free} - Nonce: ${nonce} - `); +None. - ``` +**Example**: -### Sending Transactions +```bash title="net_listening" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_listening", + "params":[], + "id":1 +}' +``` -Transactions (also called extrinsics) modify the chain state. Before sending a transaction, you need: +--- -- A funded account with sufficient balance to pay transaction fees. -- The account's keypair for signing. +### net_peerCount -To make a transfer: +Returns the number of peers currently connected to the client. -```js -// Assuming you have an `alice` keypair from the Keyring -const recipient = 'INSERT_RECIPIENT_ADDRESS'; -const amount = 'INSERT_VALUE'; // Amount in the smallest unit (e.g., Planck for DOT) +**Parameters**: -// Sign and send a transfer -const txHash = await api.tx.balances - .transfer(recipient, amount) - .signAndSend(alice); +None. -console.log('Transaction Hash:', txHash); +**Example**: +```bash title="net_peerCount" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_peerCount", + "params":[], + "id":1 +}' ``` -The `alice` keypair in the example comes from a `Keyring` object. For more details about managing keypairs, see the [Keyring documentation](https://polkadot.js.org/docs/keyring){target=\_blank}. +--- -## Where to Go Next +### net_version -For more detailed information about the Polkadot.js API, check the [official documentation](https://polkadot.js.org/docs/){target=\_blank}. +Returns the current network ID as a string. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#net_version){target=\_blank}. +**Parameters**: ---- +None. -Page Title: Python Substrate Interface +**Example**: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/py-substrate-interface/ -- Summary: Learn how to connect to Polkadot SDK-based nodes, query data, submit transactions, and manage blockchain interactions using the Python Substrate Interface. +```bash title="net_version" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"net_version", + "params":[], + "id":1 +}' +``` -# Python Substrate Interface +--- -## Introduction +### system_health -The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for: +Returns information about the health of the system. -- Querying on-chain storage. -- Composing and submitting extrinsics. -- SCALE encoding/decoding. -- Interacting with Substrate runtime metadata. -- Managing blockchain interactions through convenient utility methods. +**Parameters**: -## Installation +None. -Install the library using `pip`: +**Example**: -```py -pip install substrate-interface +```bash title="system_health" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"system_health", + "params":[], + "id":1 +}' ``` -For more installation details, see the [Installation](https://jamdottech.github.io/py-polkadot-sdk/getting-started/installation/){target=\_blank} section in the official Python Substrate Interface documentation. - -## Get Started - -This guide will walk you through the basic operations with the Python Substrate Interface: connecting to a node, reading chain state, and submitting transactions. +--- -### Establishing Connection +### web3_clientVersion -The first step is to establish a connection to a Polkadot SDK-based node. You can connect to either a local or remote node: +Returns the current client version. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#web3_clientversion){target=\_blank}. -```py -from substrateinterface import SubstrateInterface +**Parameters**: -# Connect to a node using websocket -substrate = SubstrateInterface( - # For local node: "ws://127.0.0.1:9944" - # For Polkadot: "wss://rpc.polkadot.io" - # For Kusama: "wss://kusama-rpc.polkadot.io" - url="INSERT_WS_URL" -) +None. -# Verify connection -print(f"Connected to chain: {substrate.chain}") +**Example**: +```bash title="web3_clientVersion" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"web3_clientVersion", + "params":[], + "id":1 +}' ``` -### Reading Chain State - -You can query various on-chain storage items. To retrieve data, you need to specify three key pieces of information: - -- **Pallet name**: Module or pallet that contains the storage item you want to access. -- **Storage item**: Specific storage entry you want to query within the pallet. -- **Required parameters**: Any parameters needed to retrieve the desired data. +--- -Here's an example of how to check an account's balance and other details: +### debug_traceBlockByNumber -```py -# ... +Traces a block's execution by its number and returns a detailed execution trace for each transaction. -# Query account balance and info -account_info = substrate.query( - module="System", # The pallet name - storage_function="Account", # The storage item - params=["INSERT_ADDRESS"], # Account address in SS58 format -) +**Parameters**: -# Access account details from the result -free_balance = account_info.value["data"]["free"] -reserved = account_info.value["data"]["reserved"] -nonce = account_info.value["nonce"] +- **`blockValue` ++"string"++**: The block number or tag to trace. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`options` ++"object"++**: (Optional) An object containing tracer options. + - **`tracer` ++"string"++**: The name of the tracer to use (e.g., `"callTracer"`, `"opTracer"`). + - Other tracer-specific options may be supported. -print( - f""" - Account Details: - - Free Balance: {free_balance} - - Reserved: {reserved} - - Nonce: {nonce} - """ -) +**Example**: +```bash title="debug_traceBlockByNumber" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceBlockByNumber", + "params":["INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "id":1 +}' ``` -### Submitting Transactions - -To modify the chain state, you need to submit transactions (extrinsics). Before proceeding, ensure you have: - -- A funded account with sufficient balance to pay transaction fees. -- Access to the account's keypair. +Ensure to replace `INSERT_BLOCK_VALUE` with a proper block number if needed. -Here's how to create and submit a balance transfer: +--- -```py -#... +### debug_traceTransaction -# Compose the transfer call -call = substrate.compose_call( - call_module="Balances", # The pallet name - call_function="transfer_keep_alive", # The extrinsic function - call_params={ - 'dest': 'INSERT_ADDRESS', # Recipient's address - 'value': 'INSERT_VALUE' # Amount in smallest unit (e.g., Planck for DOT) - } -) +Traces the execution of a single transaction by its hash and returns a detailed execution trace. -# Create a signed extrinsic -extrinsic = substrate.create_signed_extrinsic( - call=call, keypair=keypair # Your keypair for signing -) +**Parameters**: -# Submit and wait for inclusion -receipt = substrate.submit_extrinsic( - extrinsic, wait_for_inclusion=True # Wait until the transaction is in a block -) +- **`transactionHash` ++"string"++**: The hash of the transaction to trace. Must be a [32 byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. +- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). -if receipt.is_success: - print( - f""" - Transaction successful: - - Extrinsic Hash: {receipt.extrinsic_hash} - - Block Hash: {receipt.block_hash} - """ - ) -else: - print(f"Transaction failed: {receipt.error_message}") +**Example**: +```bash title="debug_traceTransaction" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceTransaction", + "params":["INSERT_TRANSACTION_HASH", {"tracer": "callTracer"}], + "id":1 +}' ``` -The `keypair` object is essential for signing transactions. See the [Keypair](https://jamdottech.github.io/py-polkadot-sdk/reference/keypair/){target=\_blank} documentation for more details. - -## Where to Go Next - -Now that you understand the basics, you can: - -- Explore more complex queries and transactions. -- Learn about batch transactions and utility functions. -- Discover how to work with custom pallets and types. +Ensure to replace the `INSERT_TRANSACTION_HASH` with the proper value. -For comprehensive reference materials and advanced features, see the [Python Substrate Interface](https://jamdottech.github.io/py-polkadot-sdk/){target=\_blank} documentation. +--- +### debug_traceCall ---- +Executes a new message call and returns a detailed execution trace without creating a transaction on the blockchain. -Page Title: Randomness +**Parameters**: -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/randomness/ -- Summary: Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. +- **`transaction` ++"object"++**: The transaction call object, similar to `eth_call` parameters. + - **`to` ++"string"++**: Recipient address of the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`data` ++"string"++**: Hash of the method signature and encoded parameters. Must be a [data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`from` ++"string"++**: (Optional) Sender's address for the call. Must be a [20-byte data](https://ethereum.org/developers/docs/apis/json-rpc/#unformatted-data-encoding){target=\_blank} string. + - **`gas` ++"string"++**: (Optional) Gas limit to execute the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`gasPrice` ++"string"++**: (Optional) Gas price per unit of gas. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. + - **`value` ++"string"++**: (Optional) Value in wei to send with the call. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string. +- **`blockValue` ++"string"++**: (Optional) Block tag or block number to execute the call at. Must be a [quantity](https://ethereum.org/developers/docs/apis/json-rpc/#quantities-encoding){target=\_blank} string or a [default block parameter](https://ethereum.org/developers/docs/apis/json-rpc/#default-block){target=\_blank}. +- **`options` ++"object"++**: (Optional) An object containing tracer options (e.g., `tracer: "callTracer"`). -# Randomness +**Example**: -## Introduction +```bash title="debug_traceCall" +curl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \ +-H "Content-Type: application/json" \ +--data '{ + "jsonrpc":"2.0", + "method":"debug_traceCall", + "params":[{ + "from": "INSERT_SENDER_ADDRESS", + "to": "INSERT_RECIPIENT_ADDRESS", + "data": "INSERT_ENCODED_CALL" + }, "INSERT_BLOCK_VALUE", {"tracer": "callTracer"}], + "id":1 +}' +``` -Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as "random" numbers on a computer are actually pseudo-random. These numbers rely on an initial "seed," which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\_blank}, [heart rates](https://mdpi.altmetric.com/details/47574324){target=\_blank}, or even [lava lamps](https://en.wikipedia.org/wiki/Lavarand){target=\_blank}. While this may seem random, given the same "seed," the same sequence of numbers will always be generated. +Ensure to replace the `INSERT_SENDER_ADDRESS`, `INSERT_RECIPIENT_ADDRESS`, `INSERT_ENCODED_CALL`, and `INSERT_BLOCK_VALUE` with the proper value. -In a global blockchain network, relying on real-world entropy for randomness isn’t feasible because these inputs vary by time and location. If nodes use different inputs, blockchains can fork. Hence, real-world randomness isn't suitable for use as a seed in blockchain systems. +--- -Currently, two primary methods for generating randomness in blockchains are used: [`RANDAO`](#randao) and [`VRF`](#vrf) (Verifiable Random Function). Polkadot adopts the `VRF` approach for its randomness. +## Response Format -## VRF +All responses follow the standard JSON-RPC 2.0 format: -A Verifiable Random Function (VRF) is a cryptographic function that generates a random number and proof that ensures the submitter produced the number. This proof allows anyone to verify the validity of the random number. +```json +{ + "jsonrpc": "2.0", + "id": 1, + "result": ... // The return value varies by method +} +``` -Polkadot's VRF is similar to the one used in [**Ouroboros Praos**](https://eprint.iacr.org/2017/573.pdf){target=\_blank}, which secures randomness for block production in systems like [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe){target=\_blank} (Polkadot’s block production mechanism). +## Error Handling -The key difference is that Polkadot's VRF doesn’t rely on a central clock—avoiding the issue of whose clock to trust. Instead, it uses its own past results and slot numbers to simulate time and determine future outcomes. +If an error occurs, the response will include an error object: -### How VRF Works +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32000, + "message": "Error message here" + } +} +``` -Slots on Polkadot are discrete units of time, each lasting six seconds, and can potentially hold a block. Multiple slots form an epoch, with 2400 slots making up one four-hour epoch. -In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: +--- -1. A "secret key," unique to each validator, is used for the die roll. -2. An epoch randomness value, derived from the hash of VRF outputs from blocks two epochs ago (N-2), so past randomness influences the current epoch (N). -3. The current slot number. +Page Title: Oracles -This process helps maintain fair randomness across the network. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md +- Canonical (HTML): https://docs.polkadot.com/parachains/integrations/oracles/ +- Summary: Learn about blockchain oracles, the essential bridges connecting blockchains with real-world data for decentralized applications in the Polkadot ecosystem. -Here is a graphical representation: +# Oracles -![](/images/reference/parachains/randomness/randomness-01.webp) +## What is a Blockchain Oracle? -The VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). +Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the "blockchain oracle problem." Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain. -The result is checked by the validator against a protocol threshold. If it's below the threshold, the validator becomes a candidate for block production in that slot. +While simple oracle implementations may rely on a single trusted provider, more sophisticated solutions use decentralized networks where multiple providers stake assets and reach consensus on data validity. Typical applications include DeFi price feeds, weather data for insurance contracts, and cross-chain asset verification. -The validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`. +## Oracle Implementations -So, VRF can be expressed like: +
    -`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)` +- __Acurast__ -Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. + --- -After executing the VRF, the `RESULT` is compared to a protocol-defined `THRESHOLD`. If the `RESULT` is below the `THRESHOLD`, the validator becomes a valid candidate to propose a block for that slot. Otherwise, the validator skips the slot. + Acurast is a decentralized, serverless cloud platform that uses a distributed network of mobile devices for oracle services, addressing centralized trust and data ownership issues. In the Polkadot ecosystem, it allows developers to define off-chain data and computation needs, which are processed by these devices acting as decentralized oracle nodes, delivering results to Substrate (Wasm) and EVM environments. -As a result, there may be multiple validators eligible to propose a block for a slot. In this case, the block accepted by other nodes will prevail, provided it is on the chain with the latest finalized block as determined by the GRANDPA finality gadget. It's also possible for no block producers to be available for a slot, in which case the AURA consensus takes over. AURA is a fallback mechanism that randomly selects a validator to produce a block, running in parallel with BABE and only stepping in when no block producers exist for a slot. Otherwise, it remains inactive. + [:octicons-arrow-right-24: Reference](https://acurast.com/){target=\_blank} -Because validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. +
    -To verify resolution of this issue and that Polkadot block times remain near constant-time, see the [PoS Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} page of this documentation. -## RANDAO +--- -An alternative on-chain randomness method is Ethereum's RANDAO, where validators perform thousands of hashes on a seed and publish the final hash during a round. The collective input from all validators forms the random number, and as long as one honest validator participates, the randomness is secure. +Page Title: Overview of FRAME -To enhance security, RANDAO can optionally be combined with a Verifiable Delay Function (VDF), ensuring that randomness can't be predicted or manipulated during computation. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md +- Canonical (HTML): https://docs.polkadot.com/parachains/customize-runtime/ +- Summary: Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. -For more information about RANDAO, see the [Randomness - RANDAO](https://eth2book.info/capella/part2/building_blocks/randomness/){target=\_blank} section of the Upgrading Ethereum documentation. +# Customize Your Runtime -## VDFs +## Introduction -Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. +A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a runtime suited to your blockchain's purpose. -They produce a unique result that can be quickly verified publicly. When combined with RANDAO, feeding RANDAO's output into a VDF introduces a delay that nullifies an attacker's chance to influence the randomness. +This overview explains how runtime customization works, introduces the building blocks you'll use, and guides you through the key patterns for extending your runtime. -However, VDF likely requires specialized ASIC devices to run separately from standard nodes. +## Understanding Your Runtime -!!!warning - While only one is needed to secure the system, and they will be open-source and inexpensive, running VDF devices involves significant costs without direct incentives, adding friction for blockchain users. +The runtime is the core logic of your blockchain—it processes transactions, manages state, and enforces the rules that govern your network. When a transaction arrives at your blockchain, the [`frame_executive`](https://paritytech.github.io/polkadot-sdk/master/frame_executive/index.html){target=\_blank} pallet receives it and routes it to the appropriate pallet for execution. -## Additional Resources +Think of your runtime as a collection of specialized modules, each handling a different aspect of your blockchain. Need token balances? Use the Balances pallet. Want governance? Add the Governance pallets. Need something custom? Create your own pallet. By mixing and matching these modules, you build a runtime that's efficient, secure, and tailored to your use case. -For more information about the reasoning for choices made along with proofs, see Polkadot's research on blockchain randomness and sortition in the [Block production](https://research.web3.foundation/Polkadot/protocols/block-production){target=\_blank} entry of the Polkadot Wiki. +## Runtime Architecture -For a discussion with Web3 Foundation researchers about when and under what conditions Polkadot's randomness can be utilized, see the [Discussion on Randomness used in Polkadot](https://github.com/use-ink/ink/issues/57){target=\_blank} issue on GitHub. +The following diagram shows how FRAME components work together to form your runtime: +![](/images/parachains/customize-runtime/index/frame-overview-01.webp) ---- +The main components are: -Page Title: Register a Local Asset +- **`frame_executive`**: Routes all incoming transactions to the correct pallet for execution. +- **Pallets**: Domain-specific modules that implement your blockchain's features and business logic. +- **`frame_system`**: Provides core runtime primitives and storage. +- **`frame_support`**: Utilities and macros that simplify pallet development. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md -- Canonical (HTML): https://docs.polkadot.com/chain-interactions/token-operations/register-local-asset/ -- Summary: Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. +## Building Blocks: Pallets -# Register a Local Asset on Asset Hub +[Pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\_blank} are the fundamental units of runtime customization. Each pallet encapsulates specific functionality and can be independently developed, tested, and integrated. -## Introduction +A pallet can implement virtually any blockchain feature you need: -As detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation. +- Expose new transactions that users can submit. +- Store data on-chain. +- Enforce business rules and validation logic. +- Emit events to notify users of state changes. +- Handle errors gracefully. -This guide will take you through the steps of registering a local asset on the Asset Hub parachain. +### Pre-Built Pallets vs. Custom Pallets -## Prerequisites +FRAME provides a comprehensive library of [pre-built pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame){target=\_blank} for common blockchain features, including consensus, staking, balances, governance, and more. These pallets are battle-tested, optimized, and ready to use. -Before you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and a funded wallet with DOT or KSM. +However, you're not limited to pre-built functionality. When pre-built pallets don't meet your needs, you can create custom pallets with entirely custom logic. The real power of FRAME is the flexibility to use pre-built modules for standard features while building your own for unique requirements. -- For Polkadot Asset Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata. -- For Kusama Asset Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata. +### Pallet Structure -You need to ensure that your Asset Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees. +FRAME uses Rust macros extensively, allowing you to focus on your pallet's logic while the framework handles boilerplate and integration code. -## Steps to Register a Local Asset +A typical pallet looks like this: -To register a local asset on the Asset Hub parachain, follow these steps: +```rust +pub use pallet::*; -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. +#[frame_support::pallet] +pub mod pallet { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; - - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`. - - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider. + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); -2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. + #[pallet::config] // snip + #[pallet::event] // snip + #[pallet::error] // snip + #[pallet::storage] // snip + #[pallet::call] // snip +} +``` - ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) +Every pallet can implement these core macros: -3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column. +- **`#[frame_support::pallet]`**: Marks your module as a FRAME pallet. +- **`#[pallet::pallet]`**: Designates the struct that holds pallet metadata. +- **`#[pallet::config]`**: Defines configuration and associated types. +- **`#[pallet::event]`**: Defines events emitted by your pallet. +- **`#[pallet::error]`**: Defines error types your pallet can return. +- **`#[pallet::storage]`**: Defines on-chain storage items. +- **`#[pallet::call]`**: Defines dispatchable functions (transactions). - ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) +For a comprehensive reference, see the [`pallet_macros` documentation](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/index.html){target=\_blank}. -4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. +## How Runtime Customization Works - ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) +Customizing your runtime typically follows these patterns: -5. Fill in the required fields in the **Create Asset** form: +**Adding Pre-Built Pallets**: Select pallets from the FRAME library and integrate them into your runtime configuration. This is the fastest way to add functionality. - 1. **creator account**: The account to be used for creating this asset and setting up the initial metadata. - 2. **asset name**: The descriptive name of the asset you are registering. - 3. **asset symbol**: The symbol that will be used to represent the asset. - 4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface. - 5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested. - 6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id. - 7. Click on the **Next** button. - - ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp) +**Creating Custom Pallets**: Write custom pallets for features that don't exist in the pre-built library. Custom pallets follow the same structure as pre-built ones and integrate seamlessly. -6. Choose the accounts for the roles listed below: +**Combining Multiple Pallets**: Layer multiple pallets together to create complex behaviors. Pallets can call each other and share storage when needed. - 1. **admin account**: The account designated for continuous administration of the token. - 2. **issuer account**: The account that will be used for issuing this token. - 3. **freezer account**: The account that will be used for performing token freezing operations. - 4. Click on the **Create** button. +**Configuring Pallet Parameters**: Most pallets are configurable—you can adjust their behavior through configuration traits without modifying their code. - ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp) +The following diagram illustrates how pallets combine to form a complete runtime: -7. Click on the **Sign and Submit** button to complete the asset registration process. +![](/images/parachains/customize-runtime/index/frame-overview-02.webp) - ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) +## Starting Templates -## Verify Asset Registration +The easiest way to begin customizing your runtime is with a starter template. These templates provide a pre-configured foundation so you can focus on customization rather than setup. -After completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets){target=\_blank} section of the Polkadot.js Apps interface. +- **[Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank}**: The recommended choice for most developers, it includes pre-configured pallets for common features (balances, block production, governance), a complete runtime setup, and built-in parachain consensus support. This template offers the best balance of features and learning opportunities. -![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp) +- **[Polkadot SDK Minimal Template](https://github.com/paritytech/polkadot-sdk-minimal-template){target=\_blank}**: Provides a bare-bones runtime with only essential components. Choose this if you want maximum flexibility and prefer building from a clean slate. -!!! tip - Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field. +- **[Polkadot SDK Solochain Template](https://github.com/paritytech/polkadot-sdk/tree/master/templates/solochain){target=\_blank}**: Designed for building standalone blockchains with moderate features, simple consensus, and several core pallets. Use this if you want a sovereign blockchain independent of a relay chain. -In this way, you have successfully registered a local asset on the Asset Hub parachain. +- **[OpenZeppelin Runtime Templates](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}**: Provides security-focused configurations following industry best practices. The [generic-template](https://github.com/OpenZeppelin/polkadot-runtime-templates/tree/main/generic-template){target=\_blank} includes curated pallet selections and production-ready defaults—ideal if security is your top priority. -For an in-depth explanation about Asset Hub and its features, see the [Asset Hub](/chain-interactions/token-operations/convert-assets/){target=\_blank} entry in the Polkadot Wiki. +## Key Customization Scenarios -## Test Setup Environment +This section covers the most common customization patterns you'll encounter: -You can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank} documentation. +- **[Add Existing Pallets to Your Runtime](/parachains/customize-runtime/add-existing-pallets/)**: Integrate pre-built pallets from the FRAME library with minimal configuration. -To set up a test environment, execute the following command: +- **[Add Multiple Instances of a Pallet](/parachains/customize-runtime/add-pallet-instances/)**: Run multiple instances of the same pallet with different configurations—useful for multi-token systems or parallel features. -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` +- **[Add Smart Contract Functionality](/parachains/customize-runtime/add-smart-contract-functionality/)**: Enable smart contract execution on your parachain using Contracts pallets. -The above command will spawn a lazy fork of Polkadot Asset Hub with the latest block data from the network. If you need to test Kusama Asset Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. +- **[Create Custom Pallets](/parachains/customize-runtime/pallet-development/create-a-pallet/)**: Build entirely custom pallets for features unique to your blockchain. -An Asset Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet. +- **[Test Your Runtime](/parachains/customize-runtime/pallet-development/pallet-testing/)**: Unit test pallets and mock complete runtimes to ensure everything works correctly. --- -Page Title: Set Up the Polkadot SDK Parachain Template +Page Title: Run a Parachain Network -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md -- Canonical (HTML): https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/ -- Summary: Learn how to set up and run the Polkadot SDK Parachain Template locally, creating a ready-to-customize foundation for your parachain. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md +- Canonical (HTML): https://docs.polkadot.com/parachains/testing/run-a-parachain-network/ +- Summary: Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. -# Set Up the Polkadot SDK Parachain Template +# Run a Parachain Network Using Zombienet ## Introduction -The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs. - -Among these, the [Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a preconfigured runtime with commonly used pallets, making it an ideal starting point for most parachain development projects. +Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance. -This guide walks you through the full process of working with this template. You will: +This guide will outline the different installation methods for Zombienet, provide step-by-step instructions for setting up on various platforms, and highlight essential provider-specific features and requirements. -- Set up the Polkadot SDK Parachain Template. -- Understand the project structure and key components. -- Verify your template is ready for development. -- Run the parachain template locally in development mode. +By following this guide, Zombienet will be up and running quickly, ready to streamline your blockchain testing and development workflows. -By the end of this guide, you'll have a working template ready to customize and deploy as a parachain. +## Install Zombienet -## Prerequisites +Zombienet releases are available on the [Zombienet repository](https://github.com/paritytech/zombienet){target=\_blank}. -Before getting started, ensure you have done the following: +Multiple options are available for installing Zombienet, depending on the user's preferences and the environment where it will be used. The following section will guide you through the installation process for each option. -- Completed the [Install Polkadot SDK](/parachains/install-polkadot-sdk/){target=\_blank} guide and successfully installed [Rust](https://www.rust-lang.org/){target=\_blank} and the required packages to set up your development environment. +=== "Use the executable" -For this tutorial series, you need to use Rust `1.86`. Newer versions of the compiler may not work with this parachain template version. + Install Zombienet using executables by visiting the [latest release](https://github.com/paritytech/zombienet/releases){target=\_blank} page and selecting the appropriate asset for your operating system. You can download the executable and move it to a directory in your PATH. -Run the following commands to set up the correct Rust version: + Each release includes executables for Linux and macOS. Executables are generated using [pkg](https://github.com/vercel/pkg){target=\_blank}, which allows the Zombienet CLI to operate without requiring Node.js to be installed. -=== "macOS" + Then, ensure the downloaded file is executable: ```bash - rustup install 1.86 - rustup default 1.86 - rustup target add wasm32-unknown-unknown --toolchain 1.86-aarch64-apple-darwin - rustup component add rust-src --toolchain 1.86-aarch64-apple-darwin + chmod +x zombienet-macos-arm64 ``` -=== "Ubuntu" + Finally, you can run the following command to check if the installation was successful. If so, it will display the version of the installed Zombienet: ```bash - rustup toolchain install 1.86.0 - rustup default 1.86.0 - rustup target add wasm32-unknown-unknown --toolchain 1.86.0 - rustup component add rust-src --toolchain 1.86.0 + ./zombienet-macos-arm64 version ``` -## Polkadot SDK Utility Tools - -This tutorial requires two essential tools: + If you want to add the `zombienet` executable to your PATH, you can move it to a directory in your PATH, such as `/usr/local/bin`: -- [**Chain spec builder**](https://crates.io/crates/staging-chain-spec-builder/10.0.0){target=\_blank}: A Polkadot SDK utility for generating chain specifications. Refer to the [Generate Chain Specs](/develop/parachains/deployment/generate-chain-specs/){target=\_blank} documentation for detailed usage. - - Install it by executing the following command: - ```bash - cargo install --locked staging-chain-spec-builder@10.0.0 + mv zombienet-macos-arm64 /usr/local/bin/zombienet ``` - This command installs the `chain-spec-builder` binary. - -- [**Polkadot Omni Node**](https://crates.io/crates/polkadot-omni-node/0.5.0){target=\_blank}: A white-labeled binary, released as a part of Polkadot SDK that can act as the collator of a parachain in production, with all the related auxiliary functionalities that a normal collator node has: RPC server, archiving state, etc. Moreover, it can also run the Wasm blob of the parachain locally for testing and development. - - To install it, run the following command: + Now you can refer to the `zombienet` executable directly. ```bash - cargo install --locked polkadot-omni-node@0.5.0 + zombienet version ``` - This command installs the `polkadot-omni-node` binary. - -## Clone the Template - -The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a ready-to-use development environment for building with the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. Follow these steps to set up the template: +=== "Use Nix" -1. Clone the template repository: + For Nix users, the Zombienet repository provides a [`flake.nix`](https://github.com/paritytech/zombienet/blob/main/flake.nix){target=\_blank} file to install Zombienet making it easy to incorporate Zombienet into Nix-based projects. + + To install Zombienet utilizing Nix, users can run the following command, triggering the fetching of the flake and subsequently installing the Zombienet package: ```bash - git clone https://github.com/paritytech/polkadot-sdk-parachain-template.git parachain-template + nix run github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION -- \ + spawn INSERT_ZOMBIENET_CONFIG_FILE_NAME.toml ``` -2. Navigate into the project directory: + Replace the `INSERT_ZOMBIENET_VERSION` with the desired version of Zombienet and the `INSERT_ZOMBIENET_CONFIG_FILE_NAME` with the name of the configuration file you want to use. + + To run the command above, you need to have [Flakes](https://nixos.wiki/wiki/Flakes#Enable_flakes){target=\_blank} enabled. + Alternatively, you can also include the Zombienet binary in the PATH for the current shell using the following command: + ```bash - cd parachain-template + nix shell github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION ``` -## Explore the Project Structure - -Before building the template, take a moment to familiarize yourself with its structure. Understanding this organization will help you navigate the codebase as you develop your parachain. - -The template follows a standard Polkadot SDK project layout: - -```text -parachain-template/ -├── node/ # Node implementation and client -├── pallets/ # Custom pallets for your parachain -├── runtime/ # Runtime configuration and logic -├── Cargo.toml # Workspace configuration -└── README.md # Documentation -``` - -Key directories explained: - -- **runtime/**: Contains your parachain's state transition function and pallet configuration. This is where you'll define what your blockchain can do. -- **node/**: Houses the client implementation that runs your blockchain, handles networking, and manages the database. -- **pallets/**: Where you'll create custom business logic modules (pallets) for your specific use case. -- **Cargo.toml**: The workspace configuration that ties all components together. - -!!!note - The runtime is compiled to WebAssembly (Wasm), enabling forkless upgrades. The node binary remains constant while the runtime can be updated on-chain. - -## Compile the Runtime - -Now that you understand the template structure, let's compile the runtime to ensure everything is working correctly. +=== "Use Docker" -1. Compile the runtime: + Zombienet can also be run using Docker. The Zombienet repository provides a Docker image that can be used to run the Zombienet CLI. To run Zombienet using Docker, you can use the following command: ```bash - cargo build --release --locked + docker run -it --rm \ + -v $(pwd):/home/nonroot/zombie-net/host-current-files \ + paritytech/zombienet ``` - !!!tip - Initial compilation may take several minutes, depending on your machine specifications. Use the `--release` flag for improved runtime performance compared to the default `--debug` build. If you need to troubleshoot issues, the `--debug` build provides better diagnostics. - - For production deployments, consider using a dedicated `--profile production` flag - this can provide an additional 15-30% performance improvement over the standard `--release` profile. - -2. Upon successful compilation, you should see output indicating the build was successful. The compiled runtime will be located at: - - `./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm` - -## Verify the Build - -After compilation completes, verify that the runtime was created successfully by checking for the Wasm blob: - -```bash -ls -la ./target/release/wbuild/parachain-template-runtime/ -``` - -You should see the `parachain_template_runtime.compact.compressed.wasm` file in the output, confirming the build was successful. - -## Run the Node Locally - -After successfully compiling your runtime, you can spin up a local chain and produce blocks. This process will start your local parachain using the Polkadot Omni Node and allow you to interact with it. You'll first need to generate a chain specification that defines your network's identity, initial connections, and genesis state, providing the foundational configuration for how your nodes connect and what initial state they agree upon. - -Follow these steps to launch your node in development mode: + The command above will run the Zombienet CLI inside a Docker container and mount the current directory to the `/home/nonroot/zombie-net/host-current-files` directory. This allows Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path. -1. Generate the chain specification file of your parachain: + Inside the Docker container, you can run the Zombienet CLI commands. First, you need to set up Zombienet to download the necessary binaries: ```bash - chain-spec-builder create -t development \ - --relay-chain paseo \ - --para-id 1000 \ - --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ - named-preset development + npm run zombie -- setup polkadot polkadot-parachain ``` -2. Start the Omni Node with the generated chain spec. You'll start it in development mode (without a relay chain config), producing and finalizing blocks: + After that, you need to add those binaries to the PATH: ```bash - polkadot-omni-node --chain ./chain_spec.json --dev + export PATH=/home/nonroot/zombie-net:$PATH ``` - The `--dev` option does the following: - - - Deletes all active data (keys, blockchain database, networking information) when stopped. - - Ensures a clean working state each time you restart the node. - -3. Verify that your node is running by reviewing the terminal output. You should see log messages indicating block production and finalization. - -4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output. - -The details of the log output will be explored in a later tutorial. For now, knowing that your node is running and producing blocks is sufficient. - -## Interact with the Node - -When running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} interface, follow these steps: - -1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner: - - ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp) - -2. Connect to your local node: + Finally, you can run the Zombienet CLI commands. For example, to spawn a network using a specific configuration file, you can run the following command: - 1. Scroll to the bottom and select **Development**. - 2. Choose **Custom**. - 3. Enter `ws://localhost:9944` in the **custom endpoint** input field. - 4. Click the **Switch** button. - - ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp) + ```bash + npm run zombie -- -p native spawn host-current-files/minimal.toml + ``` -3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain. - - ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp) + The command above mounts the current directory to the `/workspace` directory inside the Docker container, allowing Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path. -You are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\_blank} available on the Polkadot Wiki. +## Providers -## Stop the Node +Zombienet supports different backend providers for running the nodes. At this moment, [Kubernetes](https://kubernetes.io/){target=\_blank}, [Podman](https://podman.io/){target=\_blank}, and local providers are supported, which can be declared as `kubernetes`, `podman`, or `native`, respectively. -When you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time. +To use a particular provider, you can specify it in the network file or use the `--provider` flag in the CLI: -To stop the local node: +```bash +zombienet spawn network.toml --provider INSERT_PROVIDER +``` -1. Return to the terminal window where the node output is displayed. -2. Press `Control-C` to stop the running process. -3. Verify that your terminal returns to the prompt in the `parachain-template` directory. +Alternatively, you can set the provider in the network file: -## Where to Go Next +```toml +[settings] +provider = "INSERT_PROVIDER" +... +``` -
    +It's important to note that each provider has specific requirements and associated features. The following sections cover each provider's requirements and added features. -- Tutorial __Deploy to Polkadot__ +### Kubernetes - --- +Kubernetes is a portable, extensible, open-source platform for managing containerized workloads and services. Zombienet is designed to be compatible with a variety of Kubernetes clusters, including: - Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks. +- [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine){target=\_blank} +- [Docker Desktop](https://docs.docker.com/desktop/features/kubernetes/){target=\_blank} +- [kind](https://kind.sigs.k8s.io/){target=\_blank} - [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md) +#### Requirements + +To effectively interact with your cluster, you'll need to ensure that [`kubectl`](https://kubernetes.io/docs/reference/kubectl/){target=\_blank} is installed on your system. This Kubernetes command-line tool allows you to run commands against Kubernetes clusters. If you don't have `kubectl` installed, you can follow the instructions provided in the [Kubernetes documentation](https://kubernetes.io/docs/tasks/tools/#kubectl){target=\_blank}. -
    +To create resources such as namespaces, pods, and CronJobs within the target cluster, you must grant your user or service account the appropriate permissions. These permissions are essential for managing and deploying applications effectively within Kubernetes. +#### Features + +If available, Zombienet uses the Prometheus operator to oversee monitoring and visibility. This configuration ensures that only essential networking-related pods are deployed. Using the Prometheus operator, Zombienet improves its ability to monitor and manage network activities within the Kubernetes cluster efficiently. ---- +### Podman -Page Title: Sidecar REST API +Podman is a daemonless container engine for developing, managing, and running Open Container Initiative (OCI) containers and container images on Linux-based systems. Zombienet supports Podman rootless as a provider on Linux machines. Although Podman has support for macOS through an internal virtual machine (VM), the Zombienet provider code requires Podman to run natively on Linux. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/sidecar/ -- Summary: Learn about Substrate API Sidecar, a REST service that provides endpoints for interacting with Polkadot SDK-based chains and simplifies blockchain interactions. +#### Requirements + +To use Podman as a provider, you need to have Podman installed on your system. You can install Podman by following the instructions provided on the [Podman website](https://podman.io/getting-started/installation){target=\_blank}. -# Sidecar API +#### Features + +Using Podman, Zombienet deploys additional pods to enhance the monitoring and visibility of the active network. Specifically, pods for [Prometheus](https://prometheus.io/){target=\_blank}, [Tempo](https://grafana.com/docs/tempo/latest/operations/monitor/){target=\_blank}, and [Grafana](https://grafana.com/){target=\_blank} are included in the deployment. Grafana is configured with Prometheus and Tempo as data sources. -## Introduction +Upon launching Zombienet, access to these monitoring services is facilitated through specific URLs provided in the output: -The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more. +- **Prometheus**: `http://127.0.0.1:34123` +- **Tempo**: `http://127.0.0.1:34125` +- **Grafana**: `http://127.0.0.1:41461` -Sidecar functions as a caching layer between your application and a Polkadot SDK-based node, offering standardized REST endpoints that simplify interactions without requiring complex, direct RPC calls. This approach is especially valuable for developers who prefer REST APIs or build applications in languages with limited WebSocket support. +It's important to note that Grafana is deployed with default administrator access. + +When network operations cease, either from halting a running spawn with the `Ctrl+C` command or test completion, Zombienet automatically removes all associated pods. -Some of the key features of the Sidecar API include: +### Local Provider -- **REST API interface**: Provides a familiar REST API interface for interacting with Polkadot SDK-based chains. -- **Standardized endpoints**: Offers consistent endpoint formats across different chain implementations. -- **Caching layer**: Acts as a caching layer to improve performance and reduce direct node requests. -- **Multiple chain support**: Works with any Polkadot SDK-based chain, including Polkadot, Kusama, and custom chains. +The Zombienet local provider, also called native, enables you to run nodes as local processes in your environment. -## Prerequisites +#### Requirements + +You must have the necessary binaries for your network (such as `polkadot` and `polkadot-parachain`). These binaries should be available in your PATH, allowing Zombienet to spawn the nodes as local processes. -Sidecar API requires Node.js version 18.14 LTS or higher. Verify your Node.js version: +To install the necessary binaries, you can use the Zombienet CLI command: ```bash -node --version +zombienet setup polkadot polkadot-parachain ``` -If you need to install or update Node.js, visit the [official Node.js website](https://nodejs.org/){target=\_blank} to download and install the latest LTS version. - -## Installation - -To install Substrate API Sidecar, use one of the following commands: - -=== "npm" +This command will download and prepare the necessary binaries for Zombienet's use. - ```bash - npm install -g @substrate/api-sidecar - ``` +If you need to use a custom binary, ensure the binary is available in your PATH. You can also specify the binary path in the network configuration file. The following example uses the custom [OpenZeppelin template](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\_blank}: -=== "pnpm" +First, clone the OpenZeppelin template repository using the following command: - ```bash - pnpm install -g @substrate/api-sidecar - ``` +```bash +git clone https://github.com/OpenZeppelin/polkadot-runtime-templates \ +&& cd polkadot-runtime-templates/generic-template +``` -=== "yarn" +Next, run the command to build the custom binary: - ```bash - yarn global add @substrate/api-sidecar - ``` +```bash +cargo build --release +``` -You can confirm the installation by running: +Finally, add the custom binary to your PATH as follows: ```bash -substrate-api-sidecar --version +export PATH=$PATH:INSERT_PATH_TO_RUNTIME_TEMPLATES/parachain-template-node/target/release ``` -For more information about the Sidecar API installation, see the [installation and usage](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#npm-package-installation-and-usage){target=\_blank} section of the Sidecar API README. +Alternatively, you can specify the binary path in the network configuration file. The local provider exclusively utilizes the command configuration for nodes, which supports both relative and absolute paths. You can employ the `default_command` configuration to specify the binary for spawning all nodes in the relay chain. + +```toml +[relaychain] +chain = "rococo-local" +default_command = "./bin-v1.6.0/polkadot" -## Usage +[parachain] +id = 1000 -To use the Sidecar API, you have two options: + [parachain.collators] + name = "collator01" + command = "./target/release/parachain-template-node" +``` -- **Local node**: Run a node locally, which Sidecar will connect to by default, requiring no additional configuration. To start, run the following: +#### Features - ```bash - substrate-api-sidecar - ``` +The local provider does not offer any additional features. -- **Remote node**: Connect Sidecar to a remote node by specifying the RPC endpoint for that chain. For example, to gain access to the Polkadot Asset Hub associated endpoints. +## Configure Zombienet - ```bash - SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io substrate-api-sidecar - ``` +Effective network configuration is crucial for deploying and managing blockchain systems. Zombienet simplifies this process by offering versatile configuration options in both JSON and TOML formats. Whether setting up a simple test network or a complex multi-node system, Zombienet's tools provide the flexibility to customize every aspect of your network's setup. - For more configuration details, see the [Configuration](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#configuration){target=\_blank} section of the Sidecar API documentation. +The following sections will explore the structure and usage of Zombienet configuration files, explain key settings for network customization, and walk through CLI commands and flags to optimize your development workflow. -Once the Sidecar API is running, you’ll see output similar to this: +### Configuration Files -
    - SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io substrate-api-sidecar -
    - SAS: - 📦 LOG: - ✅ LEVEL: "info" - ✅ JSON: false - ✅ FILTER_RPC: false - ✅ STRIP_ANSI: false - ✅ WRITE: false - ✅ WRITE_PATH: "/opt/homebrew/lib/node_modules/@substrate/api-sidecar/build/src/logs" - ✅ WRITE_MAX_FILE_SIZE: 5242880 - ✅ WRITE_MAX_FILES: 5 - 📦 SUBSTRATE: - ✅ URL: "wss://polkadot-asset-hub-rpc.polkadot.io" - ✅ TYPES_BUNDLE: undefined - ✅ TYPES_CHAIN: undefined - ✅ TYPES_SPEC: undefined - ✅ TYPES: undefined - ✅ CACHE_CAPACITY: undefined - 📦 EXPRESS: - ✅ BIND_HOST: "127.0.0.1" - ✅ PORT: 8080 - ✅ KEEP_ALIVE_TIMEOUT: 5000 - 📦 METRICS: - ✅ ENABLED: false - ✅ PROM_HOST: "127.0.0.1" - ✅ PROM_PORT: 9100 - ✅ LOKI_HOST: "127.0.0.1" - ✅ LOKI_PORT: 3100 - ✅ INCLUDE_QUERYPARAMS: false -
    - 2024-11-06 08:06:01 info: Version: 19.3.0 - 2024-11-06 08:06:02 warn: API/INIT: RPC methods not decorated: chainHead_v1_body, chainHead_v1_call, chainHead_v1_continue, chainHead_v1_follow, chainHead_v1_header, chainHead_v1_stopOperation, chainHead_v1_storage, chainHead_v1_unfollow, chainHead_v1_unpin, chainSpec_v1_chainName, chainSpec_v1_genesisHash, chainSpec_v1_properties, transactionWatch_v1_submitAndWatch, transactionWatch_v1_unwatch, transaction_v1_broadcast, transaction_v1_stop - 2024-11-06 08:06:02 info: Connected to chain Polkadot Asset Hub on the statemint client at wss://polkadot-asset-hub-rpc.polkadot.io - 2024-11-06 08:06:02 info: Listening on http://127.0.0.1:8080/ - 2024-11-06 08:06:02 info: Check the root endpoint (http://127.0.0.1:8080/) to see the available endpoints for the current node -
    -With Sidecar running, you can access the exposed endpoints via a browser, [`Postman`](https://www.postman.com/){target=\_blank}, [`curl`](https://curl.se/){target=\_blank}, or your preferred tool. +The network configuration file can be either JSON or TOML format. The Zombienet repository also provides a collection of [example configuration files](https://github.com/paritytech/zombienet/tree/main/examples){target=\_blank} that can be used as a reference. -### Endpoints +Each section may include provider-specific keys that aren't recognized by other providers. For example, if you use the local provider, any references to images for nodes will be disregarded. -Sidecar API provides a set of REST endpoints that allow you to query different aspects of the chain, including blocks, accounts, and transactions. Each endpoint offers specific insights into the chain’s state and activities. +### CLI Usage -For example, to retrieve the version of the node, use the `/node/version` endpoint: +Zombienet provides a CLI that allows interaction with the tool. The CLI can receive commands and flags to perform different kinds of operations. These operations use the following syntax: ```bash -curl -X 'GET' \ - 'http://127.0.0.1:8080/node/version' \ - -H 'accept: application/json' +zombienet ``` -Alternatively, you can access `http://127.0.0.1:8080/node/version` directly in a browser since it’s a `GET` request. +The following sections will guide you through the primary usage of the Zombienet CLI and the available commands and flags. + +#### CLI Commands -In response, you’ll see output similar to this (assuming you’re connected to Polkadot Asset Hub): +- **`spawn `**: Spawn the network defined in the [configuration file](#configuration-files). +- **`test `**: Run tests on the spawned network using the assertions and tests defined in the [test file](/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/#the-test-file){target=\_blank}. +- **`setup `**: Set up the Zombienet development environment to download and use the `polkadot` or `polkadot-parachain` executable. +- **`convert `**: Transforms a [polkadot-launch](https://github.com/paritytech/polkadot-launch){target=\_blank} configuration file with a `.js` or `.json` extension into a Zombienet configuration file. +- **`version`**: Prints Zombienet version. +- **`help`**: Prints help information. -
    - curl -X 'GET' 'http://127.0.0.1:8080/node/version' -H 'accept: application/json' -
    - { - "clientVersion": "1.16.1-835e0767fe8", - "clientImplName": "statemint", - "chain": "Polkadot Asset Hub" - } -
    -For a complete list of available endpoints and their documentation, visit the [Sidecar API list endpoints](https://paritytech.github.io/substrate-api-sidecar/dist/){target=\_blank}. You can learn about the endpoints and how to use them in your applications. +#### CLI Flags -## Where to Go Next +You can use the following flags to customize the behavior of the CLI: -To dive deeper, refer to the [official Sidecar documentation](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#substrateapi-sidecar){target=\_blank}. This provides a comprehensive guide to the available configurations and advanced usage. +- **`-p`, `--provider`**: Override the [provider](#providers) to use. +- **`-d`, `--dir`**: Specify a directory path for placing the network files instead of using the default temporary path. +- **`-f`, `--force`**: Force override all prompt commands. +- **`-l`, `--logType`**: Type of logging on the console. Defaults to `table`. +- **`-m`, `--monitor`**: Start as monitor and don't auto clean up network. +- **`-c`, `--spawn-concurrency`**: Number of concurrent spawning processes to launch. Defaults to `1`. +- **`-h`, `--help`**: Display help for command. +### Settings ---- +Through the keyword `settings`, it's possible to define the general settings for the network. The available keys are: -Page Title: Smart Contracts Cookbook Index +- **`global_volumes?`** ++"GlobalVolume[]"++: A list of global volumes to use. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/ -- Summary: Explore our full collection of tutorials and guides to learn step-by-step how to build, deploy, and work with smart contracts on Polkadot. + ??? child "`GlobalVolume` interface definition" + ```js + export interface GlobalVolume { + name: string; + fs_type: string; + mount_path: string; + } + ``` -# Smart Contracts Cookbook +- **`bootnode`** ++"boolean"++: Add bootnode to network. Defaults to `true`. +- **`bootnode_domain?`** ++"string"++: Domain to use for bootnode. +- **`timeout`** ++"number"++: Global timeout to use for spawning the whole network. +- **`node_spawn_timeout?`** ++"number"++: Timeout to spawn pod/process. +- **`grafana?`** ++"boolean"++: Deploy an instance of Grafana. +- **`prometheus?`** ++"boolean"++: Deploy an instance of Prometheus. +- **`telemetry?`** ++"boolean"++: Enable telemetry for the network. +- **`jaeger_agent?`** ++"string"++: The Jaeger agent endpoint passed to the nodes. Only available on Kubernetes. +- **`tracing_collator_url?`** ++"string"++: The URL of the tracing collator used to query by the tracing assertion. Should be tempo query compatible. +- **`tracing_collator_service_name?`** ++"string"++: Service name for tempo query frontend. Only available on Kubernetes. Defaults to `tempo-tempo-distributed-query-frontend`. +- **`tracing_collator_service_namespace?`** ++"string"++: Namespace where tempo is running. Only available on Kubernetes. Defaults to `tempo`. +- **`tracing_collator_service_port?`** ++"number"++: Port of the query instance of tempo. Only available on Kubernetes. Defaults to `3100`. +- **`enable_tracing?`** ++"boolean"++: Enable the tracing system. Only available on Kubernetes. Defaults to `true`. +- **`provider`** ++"string"++: Provider to use. Default is `kubernetes`". +- **`polkadot_introspector?`** ++"boolean"++: Deploy an instance of polkadot-introspector. Only available on Podman and Kubernetes. Defaults to `false`. +- **`backchannel?`** ++"boolean"++: Deploy an instance of backchannel server. Only available on Kubernetes. Defaults to `false`. +- **`image_pull_policy?`** ++"string"++: Image pull policy to use in the network. Possible values are `Always`, `IfNotPresent`, and `Never`. +- **`local_ip?`** ++"string"++: IP used for exposing local services (rpc/metrics/monitors). Defaults to `"127.0.0.1"`. +- **`global_delay_network_global_settings?`** ++"number"++: Delay in seconds to apply to the network. +- **`node_verifier?`** ++"string"++: Specify how to verify node readiness or deactivate by using `None`. Possible values are `None` and `Metric`. Defaults to `Metric`. -Welcome to the Polkadot smart contracts cookbook index. +For example, the following configuration file defines a minimal example for the settings: -This page contains a list of all relevant tutorials and guides to help you get started coding smart contracts and dApps in Polkadot. +=== "TOML" + ```toml title="base-example.toml" + [settings] + timeout = 1000 + bootnode = false + provider = "kubernetes" + backchannel = false + # ... + ``` +=== "JSON" -## Get Tokens from the Faucet + ```json title="base-example.json" + { + "settings": { + "timeout": 1000, + "bootnode": false, + "provider": "kubernetes", + "backchannel": false, + "...": {} + }, + "...": {} + } -| Title | Difficulty | Tools | Description | -|------------------------------------|:-----------:|-------|-----------------------------------------------------------------------------------------------------------------------| -| [Faucet](/smart-contracts/faucet/) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. | + ``` -## EVM/PVM Smart Contracts +### Relay Chain Configuration -| Title | Difficulty | Tools | Description | -|---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. | -| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | +You can use the `relaychain` keyword to define further parameters for the relay chain at start-up. The available keys are: -## Port Ethereum DApps +- **`default_command?`** ++"string"++: The default command to run. Defaults to `polkadot`. +- **`default_image?`** ++"string"++: The default Docker image to use. +- **`default_resources?`** ++"Resources"++: Represents the resource limits/reservations the nodes need by default. Only available on Kubernetes. -| Title | Difficulty | Tools | Description | -|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| -| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` +- **`default_db_snapshot?`** ++"string"++: The default database snapshot to use. +- **`default_prometheus_prefix`** ++"string"++: A parameter for customizing the metric's prefix. Defaults to `substrate`. +- **`default_substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version. ---- + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } + ``` -Page Title: Smart Contracts Overview +- **`default_keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. +- **`chain`** ++"string"++: The chain name. +- **`chain_spec_path?`** ++"string"++: Path to the chain spec file. Should be the plain version to allow customizations. +- **`chain_spec_command?`** ++"string"++: Command to generate the chain spec. It can't be used in combination with `chain_spec_path`. +- **`default_args?`** ++"string[]"++: An array of arguments to use as default to pass to the command. +- **`default_overrides?`** ++"Override[]"++: An array of overrides to upload to the node. -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md -- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ -- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. + ??? child "`Override` interface definition" + ```js + export interface Override { + local_path: string; + remote_name: string; + } + ``` -# Smart Contracts on Polkadot +- **`random_nominators_count?`** ++"number"++: If set and the stacking pallet is enabled, Zombienet will generate the input quantity of nominators and inject them into the genesis. +- **`max_nominations`** ++"number"++: The max number of nominations allowed by a nominator. Should match the value set in the runtime. Defaults to `24`. +- **`nodes?`** ++"Node[]"++: An array of nodes to spawn. It is further defined in the [Node Configuration](#node-configuration) section. +- **`node_groups?`** ++"NodeGroup[]"++: An array of node groups to spawn. It is further defined in the [Node Group Configuration](#node-group-configuration) section. +- **`total_node_in_group?`** ++"number"++: The total number of nodes in the group. Defaults to `1`. +- **`genesis`** ++"JSON"++: The genesis configuration. +- **`default_delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. -## Introduction + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` -Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. +#### Node Configuration -Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. +One specific key capable of receiving more subkeys is the `nodes` key. This key is used to define further parameters for the nodes. The available keys: -These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. +- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). +- **`image?`** ++"string"++: Override default Docker image to use for this node. +- **`command?`** ++"string"++: Override default command to run. +- **`command_with_args?`** ++"string"++: Override default command and arguments. +- **`args?`** ++"string[]"++: Arguments to be passed to the command. +- **`env?`** ++"envVars[]"++: Environment variables to set in the container. -## Native Smart Contracts + ??? child "`envVars` interface definition" + ```js + export interface EnvVars { + name: string; + value: string; + } + ``` -### Introduction +- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. +- **`db_snapshot?`** ++"string"++: Database snapshot to use. +- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. -Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } + ``` -### Smart Contract Development +- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. -The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` -Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. +- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. +- **`validator`** ++"boolean"++: Pass the `--validator` flag to the command. Defaults to `true`. +- **`invulnerable`** ++"boolean"++: If true, add the node to invulnerables in the chain spec. Defaults to `false`. +- **`balance`** ++"number"++: Balance to set in balances for node's account. Defaults to `2000000000000`. +- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. +- **`add_to_bootnodes?`** ++"boolean"++: Add this node to the bootnode list. Defaults to `false`. +- **`ws_port?`** ++"number"++: WS port to use. +- **`rpc_port?`** ++"number"++: RPC port to use. +- **`prometheus_port?`** ++"number"++: Prometheus port to use. +- **`p2p_cert_hash?`** ++"string"++: Libp2p certhash to use with webRTC transport. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -### Technical Architecture + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` -PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: +The following configuration file defines a minimal example for the relay chain, including the `nodes` key: -- Enhanced performance for smart contract execution. -- Improved gas efficiency for complex operations. -- Native compatibility with Polkadot's runtime environment. -- Optimized storage and state management. +=== "TOML" -### Development Tools and Resources + ```toml title="relaychain-example-nodes.toml" + [relaychain] + default_command = "polkadot" + default_image = "polkadot-debug:master" + chain = "rococo-local" + chain_spec_path = "INSERT_PATH_TO_CHAIN_SPEC" + default_args = ["--chain", "rococo-local"] -Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: + [[relaychain.nodes]] + name = "alice" + validator = true + balance = 1000000000000 -- Contract development in Solidity or Rust. -- Support for standard Ethereum development libraries. -- Integration with widely used development environments. -- Access to blockchain explorers and indexing solutions. -- Compatibility with contract monitoring and management tools. + [[relaychain.nodes]] + name = "bob" + validator = true + balance = 1000000000000 + # ... -### Cross-Chain Capabilities + ``` -Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. +=== "JSON" -### Use Cases + ```json title="relaychain-example-nodes.json" + { + "relaychain": { + "default_command": "polkadot", + "default_image": "polkadot-debug:master", + "chain": "rococo-local", + "chain_spec_path": "INSERT_PATH_TO_CHAIN-SPEC.JSON", + "default_args": ["--chain", "rococo-local"], + "nodes": [ + { + "name": "alice", + "validator": true, + "balance": 1000000000000 + }, + { + "name": "bob", + "validator": true, + "balance": 1000000000000 + } + ] + } + } -Polkadot Hub's smart contract platform is suitable for a wide range of applications: + ``` -- DeFi protocols leveraging _cross-chain capabilities_. -- NFT platforms utilizing Polkadot's native token standards. -- Governance systems integrated with Polkadot's democracy mechanisms. -- Cross-chain bridges and asset management solutions. +#### Node Group Configuration -## Other Smart Contract Environments +The `node_groups` key defines further parameters for the node groups. The available keys are: -Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: +- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). +- **`image?`** ++"string"++: Override default Docker image to use for this node. +- **`command?`** ++"string"++: Override default command to run. +- **`args?`** ++"string[]"++: Arguments to be passed to the command. +- **`env?`** ++"envVars[]"++: Environment variables to set in the container. + + ??? child "`envVars` interface definition" + ```js + export interface EnvVars { + name: string; + value: string; + } + ``` -- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). +- **`overrides?`** ++"Override[]"++: Array of overrides definitions. -- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. + ??? child "`Override` interface definition" + ```js + export interface Override { + local_path: string; + remote_name: string; + } + ``` +- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. +- **`db_snapshot?`** ++"string"++: Database snapshot to use. +- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. -Each environment provides unique advantages based on developer preferences and application requirements. + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } + ``` -## Where to Go Next +- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. -Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` -Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. +- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. +- **`count`** ++"number | string"++: Number of nodes to launch for this group. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -
    + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` -- Guide __Libraries__ +The following configuration file defines a minimal example for the relay chain, including the `node_groups` key: - --- +=== "TOML" - Explore essential libraries to optimize smart contract development and interaction. + ```toml title="relaychain-example-node-groups.toml" + [relaychain] + default_command = "polkadot" + default_image = "polkadot-debug:master" + chain = "rococo-local" + chain_spec_path = "INSERT_PATH_TO_CHAIN_SPEC" + default_args = ["--chain", "rococo-local"] - [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) + [[relaychain.node_groups]] + name = "group-1" + count = 2 + image = "polkadot-debug:master" + command = "polkadot" + args = ["--chain", "rococo-local"] + # ... -- Guide __Dev Environments__ + ``` - --- +=== "JSON" - Set up your development environment for seamless contract deployment and testing. + ```json title="relaychain-example-node-groups.json" + { + "relaychain": { + "default_command": "polkadot", + "default_image": "polkadot-debug:master", + "chain": "rococo-local", + "chain_spec_path": "INSERT_PATH_TO_CHAIN-SPEC.JSON", + "default_args": ["--chain", "rococo-local"], + "node_groups": [ + { + "name": "group-1", + "count": 2, + "image": "polkadot-debug:master", + "command": "polkadot", + "args": ["--chain", "rococo-local"] + } + ], + "...": {} + }, + "...": {} + } - [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) + ``` -
    +### Parachain Configuration +The `parachain` keyword defines further parameters for the parachain. The available keys are: ---- +- **`id`** ++"number"++: The id to assign to this parachain. Must be unique. +- **`chain?`** ++"string"++: The chain name. +- **`force_decorator?`** ++"string"++: Force the use of a specific decorator. +- **`genesis?`** ++"JSON"++: The genesis configuration. +- **`balance?`** ++"number"++: Balance to set in balances for parachain's account. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -Page Title: Subxt Rust API + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/subxt/ -- Summary: Subxt is a Rust library for type-safe interaction with Polkadot SDK blockchains, enabling transactions, state queries, runtime API access, and more. +- **`add_to_genesis?`** ++"boolean"++: Flag to add parachain to genesis or register in runtime. Defaults to `true`. +- **`register_para?`** ++"boolean"++: Flag to specify whether the para should be registered. The `add_to_genesis` flag must be set to false for this flag to have any effect. Defaults to `true`. +- **`onboard_as_parachain?`** ++"boolean"++: Flag to specify whether the para should be onboarded as a parachain, rather than remaining a parathread. Defaults to `true`. +- **`genesis_wasm_path?`** ++"string"++: Path to the Wasm file to use. +- **`genesis_wasm_generator?`** ++"string"++: Command to generate the Wasm file. +- **`genesis_state_path?`** ++"string"++: Path to the state file to use. +- **`genesis_state_generator?`** ++"string"++: Command to generate the state file. +- **`chain_spec_path?`** ++"string"++: Path to the chain spec file. +- **`chain_spec_command?`** ++"string"++: Command to generate the chain spec. +- **`cumulus_based?`** ++"boolean"++: Flag to use cumulus command generation. Defaults to `true`. +- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. +- **`prometheus_prefix?`** ++"string"++: Parameter for customizing the metric's prefix for all parachain nodes/collators. Defaults to `substrate`. +- **`collator?`** ++"Collator"++: Further defined in the [Collator Configuration](#collator-configuration) section. +- **`collator_groups?`** ++"CollatorGroup[]"++: An array of collator groups to spawn. It is further defined in the [Collator Groups Configuration](#collator-groups-configuration) section. + +For example, the following configuration file defines a minimal example for the parachain: -# Subxt Rust API +=== "TOML" -## Introduction + ```toml title="parachain-example.toml" + [parachain] + id = 100 + add_to_genesis = true + cumulus_based = true + genesis_wasm_path = "INSERT_PATH_TO_WASM" + genesis_state_path = "INSERT_PATH_TO_STATE" + # ... -Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability. + ``` -## Prerequisites +=== "JSON" -Before using subxt, ensure you have the following requirements: + ```json title="parachain-example.json" + { + "parachain": { + "id": 100, + "add_to_genesis": true, + "cumulus_based": true, + "genesis_wasm_path": "INSERT_PATH_TO_WASM", + "genesis_state_path": "INSERT_PATH_TO_STATE", + "...": {} + }, + "...": {} + } -- Rust and Cargo installed on your system. You can install them using [Rustup](https://rustup.rs/){target=\_blank}. -- A Rust project initialized. If you don't have one, create it with: - ```bash - cargo new my_project && cd my_project ``` -## Installation - -To use subxt in your project, you must install the necessary dependencies. Each plays a specific role in enabling interaction with the blockchain: +#### Collator Configuration -1. **Install the subxt CLI**: [`subxt-cli`](https://crates.io/crates/subxt-cli){target=\_blank} is a command-line tool that provides utilities for working with Polkadot SDK metadata. In the context of subxt, it is essential to download chain metadata, which is required to generate type-safe Rust interfaces for interacting with the blockchain. Install it using the following: +One specific key capable of receiving more subkeys is the `collator` key. This key defines further parameters for the nodes. The available keys are: - ```bash - cargo install subxt-cli@0.44.0 - ``` +- **`name`** ++"string"++: Name of the collator. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). +- **`image?`** ++"string"++: Image to use for the collator. +- **`command_with_args?`** ++"string"++: Overrides both command and arguments for the collator. +- **`validator`** ++"boolean"++: Pass the `--validator` flag to the command. Defaults to `true`. +- **`invulnerable`** ++"boolean"++: If true, add the collator to invulnerables in the chain spec. Defaults to `false`. +- **`balance`** ++"number"++: Balance to set in balances for collator's account. Defaults to `2000000000000`. +- **`bootnodes?`** ++"string[]"++: Array of bootnodes to use. +- **`add_to_bootnodes?`** ++"boolean"++: Add this collator to the bootnode list. Defaults to `false`. +- **`ws_port?`** ++"number"++: WS port to use. +- **`rpc_port?`** ++"number"++: RPC port to use. +- **`prometheus_port?`** ++"number"++: Prometheus port to use. +- **`p2p_port?`** ++"number"++: P2P port to use. +- **`p2p_cert_hash?`** ++"string"++: Libp2p certhash to use with webRTC transport. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -2. **Add core dependencies**: These dependencies are essential for interacting with the blockchain. + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` - - **[subxt](https://crates.io/crates/subxt){target=\_blank}**: The main library for communicating with Polkadot SDK nodes. It handles RPC requests, encoding/decoding, and type generation. +- **`command?`** ++"string"++: Override default command to run. +- **`args?`** ++"string[]"++: Arguments to be passed to the command. +- **`env?`** ++"envVars[]"++: Environment variables to set in the container. - ```bash - cargo add subxt@0.44.0 + ??? child "`envVars` interface definition" + ```js + export interface EnvVars { + name: string; + value: string; + } ``` - - **[subxt-signer](https://crates.io/crates/subxt-signer){target=\_blank}**: Provides cryptographic functionality for signing transactions. Without this, you can only read data but cannot submit transactions. +- **`overrides?`** ++"Override[]"++: Array of overrides definitions. - ```bash - cargo add subxt-signer@0.44.0 + ??? child "`Override` interface definition" + ```js + export interface Override { + local_path: string; + remote_name: string; + } ``` - - **[tokio](https://crates.io/crates/tokio){target=\_blank}**: An asynchronous runtime for Rust. Since blockchain operations are async, Tokio enables the efficient handling of network requests. The `rt` feature enables Tokio's runtime, including the current-thread single-threaded scheduler, which is necessary for async execution. The `macros` feature provides procedural macros like `#[tokio::main]` to simplify runtime setup. +- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. +- **`db_snapshot?`** ++"string"++: Database snapshot to use. +- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. - ```bash - cargo add tokio@1.44.2 --features rt,macros + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } ``` - After adding the dependencies, your `Cargo.toml` should look like this: +- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. - ```toml - [package] - name = "my_project" - version = "0.1.0" - edition = "2021" + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` - [dependencies] - subxt = "0.41.0" - subxt-signer = "0.41.0" - tokio = { version = "1.44.2", features = ["rt", "macros"] } +- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. - ``` +The configuration file below defines a minimal example for the collator: -## Get Started +=== "TOML" -This guide will walk you through the fundamental operations of subxt, from setting up your environment to executing transactions and querying blockchain state. + ```toml title="collator-example.toml" + [parachain] + id = 100 + add_to_genesis = true + cumulus_based = true + genesis_wasm_path = "INSERT_PATH_TO_WASM" + genesis_state_path = "INSERT_PATH_TO_STATE" -### Download Chain Metadata + [[parachain.collators]] + name = "alice" + image = "polkadot-parachain" + command = "polkadot-parachain" + # ... -Before interacting with a blockchain, you need to retrieve its metadata. This metadata defines storage structures, extrinsics, and other runtime details. Use the `subxt-cli` tool to download the metadata, replacing `INSERT_NODE_URL` with the URL of the node you want to interact with: + ``` -```bash -subxt metadata --url INSERT_NODE_URL > polkadot_metadata.scale -``` +=== "JSON" -### Generate Type-Safe Interfaces + ```json title="collator-example.json" + { + "parachain": { + "id": 100, + "add_to_genesis": true, + "cumulus_based": true, + "genesis_wasm_path": "INSERT_PATH_TO_WASM", + "genesis_state_path": "INSERT_PATH_TO_STATE", + "collators": [ + { + "name": "alice", + "image": "polkadot-parachain", + "command": "polkadot-parachain", + "...": {} + } + ] + }, + "...": {} + } -Use the `#[subxt::subxt]` macro to generate a type-safe Rust interface from the downloaded metadata: + ``` -```rust -// Generate an interface that we can use from the node's metadata. -#[subxt::subxt(runtime_metadata_path = "./polkadot_metadata.scale")] -pub mod polkadot {} -``` +#### Collator Groups Configuration -Once subxt interfaces are generated, you can interact with your node in the following ways. You can use the links below to view the related subxt documentation: +The `collator_groups` key defines further parameters for the collator groups. The available keys are: -- **[Transactions](https://docs.rs/subxt/latest/subxt/book/usage/transactions/index.html){target=\_blank}**: Builds and submits transactions, monitors their inclusion in blocks, and retrieves associated events. -- **[Storage](https://docs.rs/subxt/latest/subxt/book/usage/storage/index.html){target=\_blank}**: Enables querying of node storage data. -- **[Events](https://docs.rs/subxt/latest/subxt/book/usage/events/index.html){target=\_blank}**: Retrieves events emitted from recent blocks. -- **[Constants](https://docs.rs/subxt/latest/subxt/book/usage/constants/index.html){target=\_blank}**: Accesses constant values stored in nodes that remain unchanged across a specific runtime version. -- **[Blocks](https://docs.rs/subxt/latest/subxt/book/usage/blocks/index.html){target=\_blank}**: Loads recent blocks or subscribes to new/finalized blocks, allowing examination of extrinsics, events, and storage at those blocks. -- **[Runtime APIs](https://docs.rs/subxt/latest/subxt/book/usage/runtime_apis/index.html){target=\_blank}**: Makes calls into pallet runtime APIs to fetch data. -- **[Custom values](https://docs.rs/subxt/latest/subxt/book/usage/custom_values/index.html){target=\_blank}**: Accesses "custom values" contained within metadata. -- **[Raw RPC calls](https://docs.rs/subxt/latest/subxt/book/usage/rpc/index.html){target=\_blank}**: Facilitates raw RPC requests to compatible nodes. +- **`name`** ++"string"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`). +- **`image?`** ++"string"++: Override default Docker image to use for this node. +- **`command?`** ++"string"++: Override default command to run. +- **`args?`** ++"string[]"++: Arguments to be passed to the command. +- **`env?`** ++"envVars[]"++: Environment variables to set in the container. -### Initialize the Subxt Client + ??? child "`envVars` interface definition" + ```js + export interface EnvVars { + name: string; + value: string; + } + ``` -To interact with a blockchain node using subxt, create an asynchronous main function and initialize the client. Replace `INSERT_NODE_URL` with the URL of your target node: +- **`overrides?`** ++"Override[]"++: Array of overrides definitions. -```rust -use std::str::FromStr; -use subxt::utils::AccountId32; -use subxt::{OnlineClient, PolkadotConfig}; -use subxt_signer::{bip39::Mnemonic,sr25519::Keypair}; + ??? child "`Override` interface definition" + ```js + export interface Override { + local_path: string; + remote_name: string; + } + ``` -// Generate an interface that we can use from the node's metadata. -#[subxt::subxt(runtime_metadata_path = "./polkadot_metadata.scale")] -pub mod polkadot {} +- **`prometheus_prefix?`** ++"string"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`. +- **`db_snapshot?`** ++"string"++: Database snapshot to use. +- **`substrate_cli_args_version?`** ++"SubstrateCliArgsVersion"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead. -#[tokio::main(flavor = "current_thread")] -async fn main() -> Result<(), Box> { - // Define the node URL. - const NODE_URL: &str = "INSERT_NODE_URL"; + ??? child "`SubstrateCliArgsVersion` enum definition" + ```js + export enum SubstrateCliArgsVersion { + V0 = 0, + V1 = 1, + V2 = 2, + V3 = 3, + } + ``` - // Initialize the Subxt client to interact with the blockchain. - let api = OnlineClient::::from_url(NODE_URL).await?; +- **`resources?`** ++"Resources"++: Represent the resources limits/reservations needed by the node. - // Your code here... + ??? child "`Resources` interface definition" + ```js + export interface Resources { + resources: { + requests?: { + memory?: string; + cpu?: string; + }; + limits?: { + memory?: string; + cpu?: string; + }; + }; + } + ``` - Ok(()) -} -``` +- **`keystore_key_types?`** ++"string[]"++: Defines which keystore keys should be created. +- **`count`** ++"number | string"++: Number of nodes to launch for this group. +- **`delay_network_settings?`** ++"DelayNetworkSettings"++: Sets the expected configuration to delay the network. -### Read Chain Data + ??? child "`DelayNetworkSettings` interface definition" + ```js + export interface DelayNetworkSettings { + latency: string; + correlation?: string; // should be parsable as float by k8s + jitter?: string; + } + ``` -subxt provides multiple ways to access on-chain data: +For instance, the configuration file below defines a minimal example for the collator groups: -- **Constants**: Constants are predefined values in the runtime that remain unchanged unless modified by a runtime upgrade. +=== "TOML" - For example, to retrieve the existential deposit, use: - - ```rust - // A query to obtain some constant. - let constant_query = polkadot::constants().balances().existential_deposit(); + ```toml title="collator-groups-example.toml" + [parachain] + id = 100 + add_to_genesis = true + cumulus_based = true + genesis_wasm_path = "INSERT_PATH_TO_WASM" + genesis_state_path = "INSERT_PATH_TO_STATE" - // Obtain the value. - let value = api.constants().at(&constant_query)?; + [[parachain.collator_groups]] + name = "group-1" + count = 2 + image = "polkadot-parachain" + command = "polkadot-parachain" + # ... - println!("Existential deposit: {:?}", value); ``` -- **State**: State refers to the current chain data, which updates with each block. +=== "JSON" - To fetch account information, replace `INSERT_ADDRESS` with the address you want to fetch data from and use: + ```json title="collator-groups-example.json" + { + "parachain": { + "id": 100, + "add_to_genesis": true, + "cumulus_based": true, + "genesis_wasm_path": "INSERT_PATH_TO_WASM", + "genesis_state_path": "INSERT_PATH_TO_STATE", + "collator_groups": [ + { + "name": "group-1", + "count": 2, + "image": "polkadot-parachain", + "command": "polkadot-parachain", + "...": {} + } + ] + }, + "...": {} + } - ```rust - // Define the target account address. - const ADDRESS: &str = "INSERT_ADDRESS"; - let account = AccountId32::from_str(ADDRESS).unwrap(); - - // Build a storage query to access account information. - let storage_query = polkadot::storage().system().account(&account.into()); - - // Fetch the latest state for the account. - let result = api - .storage() - .at_latest() - .await? - .fetch(&storage_query) - .await? - .unwrap(); - - println!("Account info: {:?}", result); ``` -### Submit Transactions - -To submit a transaction, you must construct an extrinsic, sign it with your private key, and send it to the blockchain. Replace `INSERT_DEST_ADDRESS` with the recipient's address, `INSERT_AMOUNT` with the amount to transfer, and `INSERT_SECRET_PHRASE` with the sender's mnemonic phrase: - -```rust - // Define the recipient address and transfer amount. - const DEST_ADDRESS: &str = "INSERT_DEST_ADDRESS"; - const AMOUNT: u128 = INSERT_AMOUNT; - - // Convert the recipient address into an `AccountId32`. - let dest = AccountId32::from_str(DEST_ADDRESS).unwrap(); - - // Build the balance transfer extrinsic. - let balance_transfer_tx = polkadot::tx() - .balances() - .transfer_allow_death(dest.into(), AMOUNT); - - // Load the sender's keypair from a mnemonic phrase. - const SECRET_PHRASE: &str = "INSERT_SECRET_PHRASE"; - let mnemonic = Mnemonic::parse(SECRET_PHRASE).unwrap(); - let sender_keypair = Keypair::from_phrase(&mnemonic, None).unwrap(); - - // Sign and submit the extrinsic, then wait for it to be finalized. - let events = api - .tx() - .sign_and_submit_then_watch_default(&balance_transfer_tx, &sender_keypair) - .await? - .wait_for_finalized_success() - .await?; - - // Check for a successful transfer event. - if let Some(event) = events.find_first::()? { - println!("Balance transfer successful: {:?}", event); - } -``` +### XCM Configuration -## Where to Go Next +You can use the `hrmp_channels` keyword to define further parameters for the XCM channels at start-up. The available keys are: -Now that you've covered the basics dive into the official [subxt documentation](https://docs.rs/subxt/latest/subxt/book/index.html){target=\_blank} for comprehensive reference materials and advanced features. +- **`hrmp_channels`** ++"HrmpChannelsConfig[]"++: Array of Horizontal Relay-routed Message Passing (HRMP) channel configurations. + ??? child "`HrmpChannelsConfig` interface definition" + ```js + export interface HrmpChannelsConfig { + sender: number; + recipient: number; + max_capacity: number; + max_message_size: number; + } + ``` + Each of the `HrmpChannelsConfig` keys are defined as follows: ---- + - **`sender` ++"number"++**: Parachain ID of the sender. + - **`recipient` ++"number"++**: Parachain ID of the recipient. + - **`max_capacity` ++"number"++**: Maximum capacity of the HRMP channel. + - **`max_message_size` ++"number"++**: Maximum message size allowed in the HRMP channel. -Page Title: Technical Reference Overview +## Where to Go Next -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md -- Canonical (HTML): https://docs.polkadot.com/reference/ -- Summary: Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. +
    -## Introduction +- External __Zombienet Support__ -The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need. + --- -Polkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\_blank} to the [governance](/reference/glossary#governance){target=\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants. + [Parity Technologies](https://www.parity.io/){target=\_blank} has designed and developed this framework, now maintained by the Zombienet team. -This guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem. + For further support and information, refer to the following contact points: -## Polkadot Hub + [:octicons-arrow-right-24: Zombienet repository](https://github.com/paritytech/zombienet){target=\_blank} -[Polkadot Hub](/reference/polkadot-hub/){target=\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain. + [:octicons-arrow-right-24: Element public channel](https://matrix.to/#/!FWyuEyNvIFygLnWNMh:parity.io?via=parity.io&via=matrix.org&via=web3.foundation){target=\_blank} -The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: -- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications. -- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem. -- **Staking**: Participate in network security and earn rewards by staking DOT. -- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov. -- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities. -- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem. -- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations. +- Tutorial __Spawn a Basic Chain with Zombienet__ -## Parachains + --- -[Parachains](/reference/parachains/){target=\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers: + Learn to spawn, connect to and monitor a basic blockchain network with Zombienet, using customizable configurations for streamlined development and debugging. -- **Accounts**: Deep dive into account types, storage, and management on parachains. -- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms. -- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus. -- **Chain data**: Explore data structures, storage layouts, and state management. -- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains. -- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility. -- **Networks**: Learn about networking protocols and peer-to-peer communication. -- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\_blank}, the standard for cross-chain communication. -- **Randomness**: Understand how randomness is generated and used in Polkadot chains. -- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. + [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/spawn-basic-chain/) -## On-Chain Governance +
    -[On-Chain governance](/reference/governance/){target=\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details: -- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums. -- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity. -- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance. -- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system. +--- -## Glossary +Page Title: Set Up the Polkadot SDK Parachain Template -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md +- Canonical (HTML): https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/ +- Summary: Learn how to set up and run the Polkadot SDK Parachain Template locally, creating a ready-to-customize foundation for your parachain. -- Blockchain concepts (blocks, transactions, state) -- Consensus mechanisms (validators, collators, finality) -- Polkadot-specific terms (relay chain, parachain, XCM, FRAME) -- Network components (nodes, runtimes, storage) -- Governance terminology (origins, tracks, referendums) +# Set Up the Polkadot SDK Parachain Template -## Tools +## Introduction -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: +The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs. -- **Light clients**: Lightweight solutions for interacting with the network without running full nodes. -- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\_blank} and [PAPI](/reference/tools/papi/){target=\_blank} for building applications. -- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\_blank} and other Rust-based libraries for SDK development. -- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\_blank} for Python developers. -- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\_blank}, and [Omninode](/reference/tools/omninode/){target=\_blank} for smart contract and parachain testing. -- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\_blank} for substrate interaction. -- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\_blank} for XCM integration and asset transfers. +Among these, the [Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a preconfigured runtime with commonly used pallets, making it an ideal starting point for most parachain development projects. -## Where to Go Next +This guide walks you through the full process of working with this template. You will: -For detailed exploration of specific areas, proceed to any of the main sections: +- Set up the Polkadot SDK Parachain Template. +- Understand the project structure and key components. +- Verify your template is ready for development. +- Run the parachain template locally in development mode. -
    +By the end of this guide, you'll have a working template ready to customize and deploy as a parachain. -- Learn **Polkadot Hub** +## Prerequisites - --- +Before getting started, ensure you have done the following: - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. +- Completed the [Install Polkadot SDK](/parachains/install-polkadot-sdk/){target=\_blank} guide and successfully installed [Rust](https://www.rust-lang.org/){target=\_blank} and the required packages to set up your development environment. - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) +For this tutorial series, you need to use Rust `1.86`. Newer versions of the compiler may not work with this parachain template version. -- Learn **Parachains** +Run the following commands to set up the correct Rust version: - --- +=== "macOS" - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. + ```bash + rustup install 1.86 + rustup default 1.86 + rustup target add wasm32-unknown-unknown --toolchain 1.86-aarch64-apple-darwin + rustup component add rust-src --toolchain 1.86-aarch64-apple-darwin + ``` - [:octicons-arrow-right-24: Reference](/reference/parachains/) +=== "Ubuntu" -- Learn **On-Chain Governance** + ```bash + rustup toolchain install 1.86.0 + rustup default 1.86.0 + rustup target add wasm32-unknown-unknown --toolchain 1.86.0 + rustup component add rust-src --toolchain 1.86.0 + ``` - --- +## Polkadot SDK Utility Tools - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. +This tutorial requires two essential tools: - [:octicons-arrow-right-24: Reference](/reference/governance/) +- [**Chain spec builder**](https://crates.io/crates/staging-chain-spec-builder/10.0.0){target=\_blank}: A Polkadot SDK utility for generating chain specifications. Refer to the [Generate Chain Specs](/develop/parachains/deployment/generate-chain-specs/){target=\_blank} documentation for detailed usage. + + Install it by executing the following command: + + ```bash + cargo install --locked staging-chain-spec-builder@10.0.0 + ``` -- Guide **Glossary** + This command installs the `chain-spec-builder` binary. - --- +- [**Polkadot Omni Node**](https://crates.io/crates/polkadot-omni-node/0.5.0){target=\_blank}: A white-labeled binary, released as a part of Polkadot SDK that can act as the collator of a parachain in production, with all the related auxiliary functionalities that a normal collator node has: RPC server, archiving state, etc. Moreover, it can also run the Wasm blob of the parachain locally for testing and development. - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. + To install it, run the following command: - [:octicons-arrow-right-24: Reference](/reference/glossary/) + ```bash + cargo install --locked polkadot-omni-node@0.5.0 + ``` -- Guide **Tools** + This command installs the `polkadot-omni-node` binary. - --- +## Clone the Template - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. +The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\_blank} provides a ready-to-use development environment for building with the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. Follow these steps to set up the template: - [:octicons-arrow-right-24: Reference](/reference/tools/) +1. Clone the template repository: -
    + ```bash + git clone https://github.com/paritytech/polkadot-sdk-parachain-template.git parachain-template + ``` +2. Navigate into the project directory: ---- + ```bash + cd parachain-template + ``` -Page Title: Transactions +## Explore the Project Structure -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/ -- Summary: Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. +Before building the template, take a moment to familiarize yourself with its structure. Understanding this organization will help you navigate the codebase as you develop your parachain. -# Transactions +The template follows a standard Polkadot SDK project layout: -## Introduction +```text +parachain-template/ +├── node/ # Node implementation and client +├── pallets/ # Custom pallets for your parachain +├── runtime/ # Runtime configuration and logic +├── Cargo.toml # Workspace configuration +└── README.md # Documentation +``` -Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions. +Key directories explained: -This guide walks you through the different transaction types and how they're formatted, validated, and processed within the Polkadot ecosystem. You'll also learn how to customize transaction formats and construct transactions for FRAME-based runtimes, ensuring a complete understanding of how transactions are built and executed in Polkadot SDK-based chains. +- **runtime/**: Contains your parachain's state transition function and pallet configuration. This is where you'll define what your blockchain can do. +- **node/**: Houses the client implementation that runs your blockchain, handles networking, and manages the database. +- **pallets/**: Where you'll create custom business logic modules (pallets) for your specific use case. +- **Cargo.toml**: The workspace configuration that ties all components together. -## What Is a Transaction? +!!!note + The runtime is compiled to WebAssembly (Wasm), enabling forkless upgrades. The node binary remains constant while the runtime can be updated on-chain. -In the Polkadot SDK, transactions represent operations that modify the chain's state, bundled into blocks for execution. The term extrinsic is often used to refer to any data that originates outside the runtime and is included in the chain. While other blockchain systems typically refer to these operations as "transactions," the Polkadot SDK adopts the broader term "extrinsic" to capture the wide variety of data types that can be added to a block. +## Compile the Runtime -There are three primary types of transactions (extrinsics) in the Polkadot SDK: +Now that you understand the template structure, let's compile the runtime to ensure everything is working correctly. -- **Signed transactions**: Signed by the submitting account, often carrying transaction fees. -- **Unsigned transactions**: Submitted without a signature, often requiring custom validation logic. -- **Inherent transactions**: Typically inserted directly into blocks by block authoring nodes, without gossiping between peers. +1. Compile the runtime: -Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. + ```bash + cargo build --release --locked + ``` -### Signed Transactions + !!!tip + Initial compilation may take several minutes, depending on your machine specifications. Use the `--release` flag for improved runtime performance compared to the default `--debug` build. If you need to troubleshoot issues, the `--debug` build provides better diagnostics. + + For production deployments, consider using a dedicated `--profile production` flag - this can provide an additional 15-30% performance improvement over the standard `--release` profile. -Signed transactions require an account's signature and typically involve submitting a request to execute a runtime call. The signature serves as a form of cryptographic proof that the sender has authorized the action, using their private key. These transactions often involve a transaction fee to cover the cost of execution and incentivize block producers. +2. Upon successful compilation, you should see output indicating the build was successful. The compiled runtime will be located at: + + `./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm` -Signed transactions are the most common type of transaction and are integral to user-driven actions, such as token transfers. For instance, when you transfer tokens from one account to another, the sending account must sign the transaction to authorize the operation. +## Verify the Build -For example, the [`pallet_balances::Call::transfer_allow_death`](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/pallet/struct.Pallet.html#method.transfer_allow_death){target=\_blank} extrinsic in the Balances pallet allows you to transfer tokens. Since your account initiates this transaction, your account key is used to sign it. You'll also be responsible for paying the associated transaction fee, with the option to include an additional tip to incentivize faster inclusion in the block. +After compilation completes, verify that the runtime was created successfully by checking for the Wasm blob: -### Unsigned Transactions +```bash +ls -la ./target/release/wbuild/parachain-template-runtime/ +``` -Unsigned transactions do not require a signature or account-specific data from the sender. Unlike signed transactions, they do not come with any form of economic deterrent, such as fees, which makes them susceptible to spam or replay attacks. Custom validation logic must be implemented to mitigate these risks and ensure these transactions are secure. +You should see the `parachain_template_runtime.compact.compressed.wasm` file in the output, confirming the build was successful. -Unsigned transactions typically involve scenarios where including a fee or signature is unnecessary or counterproductive. However, due to the absence of fees, they require careful validation to protect the network. For example, [`pallet_im_online::Call::heartbeat`](https://paritytech.github.io/polkadot-sdk/master/pallet_im_online/pallet/struct.Pallet.html#method.heartbeat){target=\_blank} extrinsic allows validators to send a heartbeat signal, indicating they are active. Since only validators can make this call, the logic embedded in the transaction ensures that the sender is a validator, making the need for a signature or fee redundant. +## Run the Node Locally -Unsigned transactions are more resource-intensive than signed ones because custom validation is required, but they play a crucial role in certain operational scenarios, especially when regular user accounts aren't involved. +After successfully compiling your runtime, you can spin up a local chain and produce blocks. This process will start your local parachain using the Polkadot Omni Node and allow you to interact with it. You'll first need to generate a chain specification that defines your network's identity, initial connections, and genesis state, providing the foundational configuration for how your nodes connect and what initial state they agree upon. -### Inherent Transactions +Follow these steps to launch your node in development mode: -Inherent transactions are a specialized type of unsigned transaction that is used primarily for block authoring. Unlike signed or other unsigned transactions, inherent transactions are added directly by block producers and are not broadcasted to the network or stored in the transaction queue. They don't require signatures or the usual validation steps and are generally used to insert system-critical data directly into blocks. +1. Generate the chain specification file of your parachain: -A key example of an inherent transaction is inserting a timestamp into each block. The [`pallet_timestamp::Call::now`](https://paritytech.github.io/polkadot-sdk/master/pallet_timestamp/pallet/struct.Pallet.html#method.now-1){target=\_blank} extrinsic allows block authors to include the current time in the block they are producing. Since the block producer adds this information, there is no need for transaction validation, like signature verification. The validation in this case is done indirectly by the validators, who check whether the timestamp is within an acceptable range before finalizing the block. + ```bash + chain-spec-builder create -t development \ + --relay-chain paseo \ + --para-id 1000 \ + --runtime ./target/release/wbuild/parachain-template-runtime/parachain_template_runtime.compact.compressed.wasm \ + named-preset development + ``` -Another example is the [`paras_inherent::Call::enter`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/paras_inherent/pallet/struct.Pallet.html#method.enter){target=\_blank} extrinsic, which enables parachain collator nodes to send validation data to the relay chain. This inherent transaction ensures that the necessary parachain data is included in each block without the overhead of gossiped transactions. +2. Start the Omni Node with the generated chain spec. You'll start it in development mode (without a relay chain config), producing and finalizing blocks: -Inherent transactions serve a critical role in block authoring by allowing important operational data to be added directly to the chain without needing the validation processes required for standard transactions. + ```bash + polkadot-omni-node --chain ./chain_spec.json --dev + ``` -## Transaction Formats + The `--dev` option does the following: -Understanding the structure of signed and unsigned transactions is crucial for developers building on Polkadot SDK-based chains. Whether you're optimizing transaction processing, customizing formats, or interacting with the transaction pool, knowing the format of extrinsics, Polkadot's term for transactions, is essential. + - Deletes all active data (keys, blockchain database, networking information) when stopped. + - Ensures a clean working state each time you restart the node. -### Types of Transaction Formats +3. Verify that your node is running by reviewing the terminal output. You should see log messages indicating block production and finalization. -In Polkadot SDK-based chains, extrinsics can fall into three main categories: +4. Confirm that your blockchain is producing new blocks by checking if the number after `finalized` is increasing in the output. -- **Unchecked extrinsics**: Typically used for signed transactions that require validation. They contain a signature and additional data, such as a nonce and information for fee calculation. Unchecked extrinsics are named as such because they require validation checks before being accepted into the transaction pool. -- **Checked extrinsics**: Typically used for inherent extrinsics (unsigned transactions); these don't require signature verification. Instead, they carry information such as where the extrinsic originates and any additional data required for the block authoring process. -- **Opaque extrinsics**: Used when the format of an extrinsic is not yet fully committed or finalized. They are still decodable, but their structure can be flexible depending on the context. +The details of the log output will be explored in a later tutorial. For now, knowing that your node is running and producing blocks is sufficient. -### Signed Transaction Data Structure +## Interact with the Node -A signed transaction typically includes the following components: +When running the template node, it's accessible by default at `ws://localhost:9944`. To interact with your node using the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} interface, follow these steps: -- **Signature**: Verifies the authenticity of the transaction sender. -- **Call**: The actual function or method call the transaction is requesting (for example, transferring funds). -- **Nonce**: Tracks the number of prior transactions sent from the account, helping to prevent replay attacks. -- **Tip**: An optional incentive to prioritize the transaction in block inclusion. -- **Additional data**: Includes details such as spec version, block hash, and genesis hash to ensure the transaction is valid within the correct runtime and chain context. +1. Open [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} in your web browser and click the network icon (which should be the Polkadot logo) in the top left corner: + + ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-01.webp) -Here's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime: +2. Connect to your local node: -``` code - + + -``` + 1. Scroll to the bottom and select **Development**. + 2. Choose **Custom**. + 3. Enter `ws://localhost:9944` in the **custom endpoint** input field. + 4. Click the **Switch** button. + + ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-02.webp) -Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. +3. Once connected, you should see **parachain-template-runtime** in the top left corner, with the interface displaying information about your local blockchain. + + ![](/images/parachains/launch-a-parachain/set-up-the-parachain-template/parachain-template-03.webp) -### Signed Extensions +You are now connected to your local node and can interact with it through the Polkadot.js Apps interface. This tool enables you to explore blocks, execute transactions, and interact with your blockchain's features. For in-depth guidance on using the interface effectively, refer to the [Polkadot.js Guides](https://wiki.polkadot.com/general/polkadotjs/){target=\_blank} available on the Polkadot Wiki. -Polkadot SDK also provides the concept of [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}, which allow developers to extend extrinsics with additional data or validation logic before they are included in a block. The [`SignedExtension`](https://paritytech.github.io/try-runtime-cli/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} set helps enforce custom rules or protections, such as ensuring the transaction's validity or calculating priority. +## Stop the Node -The transaction queue regularly calls signed extensions to verify a transaction's validity before placing it in the ready queue. This safeguard ensures transactions won't fail in a block. Signed extensions are commonly used to enforce validation logic and protect the transaction pool from spam and replay attacks. +When you're done exploring your local node, you can stop it to remove any state changes you've made. Since you started the node with the `--dev` option, stopping the node will purge all persistent block data, allowing you to start fresh the next time. -In FRAME, a signed extension can hold any of the following types by default: +To stop the local node: -- **[`AccountId`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/types_common/type.AccountId.html){target=\_blank}**: To encode the sender's identity. -- **[`Call`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Call){target=\_blank}**: To encode the pallet call to be dispatched. This data is used to calculate transaction fees. -- **[`AdditionalSigned`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.AdditionalSigned){target=\_blank}**: To handle any additional data to go into the signed payload allowing you to attach any custom logic prior to dispatching a transaction. -- **[`Pre`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Pre){target=\_blank}**: To encode the information that can be passed from before a call is dispatched to after it gets dispatched. +1. Return to the terminal window where the node output is displayed. +2. Press `Control-C` to stop the running process. +3. Verify that your terminal returns to the prompt in the `parachain-template` directory. -Signed extensions can enforce checks like: +## Where to Go Next -- **[`CheckSpecVersion`](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/extensions/check_spec_version.rs.html){target=\_blank}**: Ensures the transaction is compatible with the runtime's current version. -- **[`CheckWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.CheckWeight.html){target=\_blank}**: Calculates the weight (or computational cost) of the transaction, ensuring the block doesn't exceed the maximum allowed weight. +
    -These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. +- Tutorial __Deploy to Polkadot__ -## Transaction Construction + --- -Building transactions in the Polkadot SDK involves constructing a payload that can be verified, signed, and submitted for inclusion in a block. Each runtime in the Polkadot SDK has its own rules for validating and executing transactions, but there are common patterns for constructing a signed transaction. + Learn how to deploy your parachain template to a relay chain testnet. Configure your chain specification, register as a parachain, and start producing blocks. -### Construct a Signed Transaction + [:octicons-arrow-right-24: Get Started](/parachains/launch-a-parachain/deploy-to-polkadot.md) -A signed transaction in the Polkadot SDK includes various pieces of data to ensure security, prevent replay attacks, and prioritize processing. Here's an overview of how to construct one: +
    -1. **Construct the unsigned payload**: Gather the necessary information for the call, including: - - **Pallet index**: Identifies the pallet where the runtime function resides. - - **Function index**: Specifies the particular function to call in the pallet. - - **Parameters**: Any additional arguments required by the function call. +--- -2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: +Page Title: Smart Contracts Cookbook Index - - **Transaction nonce**: Unique identifier to prevent replay attacks. - - **Era information**: Defines how long the transaction is valid before it's dropped from the pool. - - **Block hash**: Ensures the transaction doesn't execute on the wrong chain or fork. +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/cookbook/ +- Summary: Explore our full collection of tutorials and guides to learn step-by-step how to build, deploy, and work with smart contracts on Polkadot. -3. **Sign the payload**: Using the sender's private key, sign the payload to ensure that the transaction can only be executed by the account holder. -4. **Serialize the signed payload**: Once signed, the transaction must be serialized into a binary format, ensuring the data is compact and easy to transmit over the network. -5. **Submit the serialized transaction**: Finally, submit the serialized transaction to the network, where it will enter the transaction pool and wait for processing by an authoring node. +# Smart Contracts Cookbook -The following is an example of how a signed transaction might look: +Welcome to the Polkadot smart contracts cookbook index. -``` rust -node_runtime::UncheckedExtrinsic::new_signed( - function.clone(), // some call - sp_runtime::AccountId32::from(sender.public()).into(), // some sending account - node_runtime::Signature::Sr25519(signature.clone()), // the account's signature - extra.clone(), // the signed extensions -) -``` +This page contains a list of all relevant tutorials and guides to help you get started coding smart contracts and dApps in Polkadot. -### Transaction Encoding -Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: -- **`[1]`**: Compact encoded length in bytes of the entire transaction. -- **`[2]`**: A u8 containing 1 byte to indicate whether the transaction is signed or unsigned (1 bit) and the encoded transaction version ID (7 bits). -- **`[3]`**: If signed, this field contains an account ID, an SR25519 signature, and some extra data. -- **`[4]`**: Encoded call data, including pallet and function indices and any required arguments. -This encoded format ensures consistency and efficiency in processing transactions across the network. By adhering to this format, applications can construct valid transactions and pass them to the network for execution. +## Get Tokens from the Faucet -To learn more about how compact encoding works using SCALE, see the [SCALE Codec](https://github.com/paritytech/parity-scale-codec){target=\_blank} README on GitHub. +| Title | Difficulty | Tools | Description | +|------------------------------------|:-----------:|-------|-----------------------------------------------------------------------------------------------------------------------| +| [Faucet](/smart-contracts/faucet/) | 🟢 Beginner | N/A | Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. | -### Customize Transaction Construction +## EVM/PVM Smart Contracts -Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: +| Title | Difficulty | Tools | Description | +|---------------------------------------------------------------------------------------------------|:-----------:|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Deploy an ERC-20 to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-erc20/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Polkadot Remix IDE. | +| [Deploy an NFT to Polkadot Hub](/smart-contracts/cookbook/smart-contracts/deploy-nft/remix/) | 🟢 Beginner | EVM Wallet, Polkadot Remix IDE | Deploy an NFT on Polkadot Hub using PolkaVM and OpenZeppelin. Learn how to compile, deploy, and interact with your contract using Polkadot Remix IDE. | -- **Custom pallets**: You can define new pallets with custom function calls, each with its own parameters and validation logic. -- **Signed extensions**: Developers can implement custom extensions that modify how transactions are prioritized, validated, or included in blocks. +## Port Ethereum DApps -By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. +| Title | Difficulty | Tools | Description | +|-------------------------------------------------------------------------------------|:---------------:|---------|----------------------------------------------------------------------------------------------------------------------------------| +| [Deploying Uniswap V2 on Polkadot](/smart-contracts/cookbook/eth-dapps/uniswap-v2/) | 🟡 Intermediate | Hardhat | Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. | -## Lifecycle of a Transaction -In the Polkadot SDK, transactions are often referred to as extrinsics because the data in transactions originates outside of the runtime. These transactions contain data that initiates changes to the chain state. The most common type of extrinsic is a signed transaction, which is cryptographically verified and typically incurs a fee. This section focuses on how signed transactions are processed, validated, and ultimately included in a block. +--- -### Define Transaction Properties +Page Title: Smart Contracts Overview -The Polkadot SDK runtime defines key transaction properties, such as: +- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-overview.md +- Canonical (HTML): https://docs.polkadot.com/smart-contracts/overview/ +- Summary: Learn about smart contract development capabilities in the Polkadot ecosystem, either by leveraging Polkadot Hub or other alternatives. -- **Transaction validity**: Ensures the transaction meets all runtime requirements. -- **Signed or unsigned**: Identifies whether a transaction needs to be signed by an account. -- **State changes**: Determines how the transaction modifies the state of the chain. +# Smart Contracts on Polkadot -Pallets, which compose the runtime's logic, define the specific transactions that your chain supports. When a user submits a transaction, such as a token transfer, it becomes a signed transaction, verified by the user's account signature. If the account has enough funds to cover fees, the transaction is executed, and the chain's state is updated accordingly. +!!! smartcontract "PolkaVM Preview Release" + PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. +## Introduction -### Process on a Block Authoring Node +Polkadot offers developers multiple approaches to building and deploying smart contracts within its ecosystem. As a multi-chain network designed for interoperability, Polkadot provides various environments optimized for different developer preferences and application requirements. From native smart contract support on Polkadot Hub to specialized parachain environments, developers can choose the platform that best suits their technical needs while benefiting from Polkadot's shared security model and cross-chain messaging capabilities. -In Polkadot SDK-based networks, some nodes are authorized to author blocks. These nodes validate and process transactions. When a transaction is sent to a node that can produce blocks, it undergoes a lifecycle that involves several stages, including validation and execution. Non-authoring nodes gossip the transaction across the network until an authoring node receives it. The following diagram illustrates the lifecycle of a transaction that's submitted to a network and processed by an authoring node. +Whether you're looking for Ethereum compatibility through EVM-based parachains like [Moonbeam](https://docs.moonbeam.network/){target=\_blank}, [Astar](https://docs.astar.network/){target=\_blank}, and [Acala](https://evmdocs.acala.network/){target=\_blank} or prefer PolkaVM-based development with [ink!](https://use.ink/docs/v6/){target=\_blank}, the Polkadot ecosystem accommodates a range of diverse developers. -![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } +These guides explore the diverse smart contract options available in the Polkadot ecosystem, helping developers understand the unique advantages of each approach and make informed decisions about where to deploy their decentralized applications. -### Validate and Queue +## Native Smart Contracts -Once a transaction reaches an authoring node, it undergoes an initial validation process to ensure it meets specific conditions defined in the runtime. This validation includes checks for: +### Introduction -- **Correct nonce**: Ensures the transaction is sequentially valid for the account. -- **Sufficient funds**: Confirms the account can cover any associated transaction fees. -- **Signature validity**: Verifies that the sender's signature matches the transaction data. +Polkadot Hub enables smart contract deployment and execution through PolkaVM, a cutting-edge virtual machine designed specifically for the Polkadot ecosystem. This native integration allows developers to deploy smart contracts directly on Polkadot's system chain while maintaining compatibility with Ethereum development tools and workflows. -After these checks, valid transactions are placed in the transaction pool, where they are queued for inclusion in a block. The transaction pool regularly re-validates queued transactions to ensure they remain valid before being processed. To reach consensus, two-thirds of the nodes must agree on the order of the transactions executed and the resulting state change. Transactions are validated and queued on the local node in a transaction pool to prepare for consensus. +### Smart Contract Development -#### Transaction Pool +The smart contract platform on Polkadot Hub combines _Polkadot's robust security and scalability_ with the extensive Ethereum development ecosystem. Developers can utilize familiar Ethereum libraries for contract interactions and leverage industry-standard development environments for writing and testing smart contracts. -The transaction pool is responsible for managing valid transactions. It ensures that only transactions that pass initial validity checks are queued. Transactions that fail validation, expire, or become invalid for other reasons are removed from the pool. +Polkadot Hub provides _full Ethereum JSON-RPC API compatibility_, ensuring seamless integration with existing development tools and services. This compatibility enables developers to maintain their preferred workflows while building on Polkadot's native infrastructure. -The transaction pool organizes transactions into two queues: +### Technical Architecture -- **Ready queue**: Transactions that are valid and ready to be included in a block. -- **Future queue**: Transactions that are not yet valid but could be in the future, such as transactions with a nonce too high for the current state. +PolkaVM, the underlying virtual machine, utilizes a RISC-V-based register architecture _optimized for the Polkadot ecosystem_. This design choice offers several advantages: -Details on how the transaction pool validates transactions, including fee and signature handling, can be found in the [`validate_transaction`](https://paritytech.github.io/polkadot-sdk/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction){target=\_blank} method. +- Enhanced performance for smart contract execution. +- Improved gas efficiency for complex operations. +- Native compatibility with Polkadot's runtime environment. +- Optimized storage and state management. -#### Invalid Transactions +### Development Tools and Resources -If a transaction is invalid, for example, due to an invalid signature or insufficient funds, it is rejected and won't be added to the block. Invalid transactions might be rejected for reasons such as: +Polkadot Hub supports a comprehensive suite of development tools familiar to Ethereum developers. The platform integrates with popular development frameworks, testing environments, and deployment tools. Key features include: -- The transaction has already been included in a block. -- The transaction's signature does not match the sender. -- The transaction is too large to fit in the current block. +- Contract development in Solidity or Rust. +- Support for standard Ethereum development libraries. +- Integration with widely used development environments. +- Access to blockchain explorers and indexing solutions. +- Compatibility with contract monitoring and management tools. -### Transaction Ordering and Priority +### Cross-Chain Capabilities -When a node is selected as the next block author, it prioritizes transactions based on weight, length, and tip amount. The goal is to fill the block with high-priority transactions without exceeding its maximum size or computational limits. Transactions are ordered as follows: +Smart contracts deployed on Polkadot Hub can leverage Polkadot's [cross-consensus messaging (XCM) protocol](/parachains/interoperability/get-started/){target=\_blank} protocol to seamlessly _transfer tokens and call functions on other blockchain networks_ within the Polkadot ecosystem, all without complex bridging infrastructure or third-party solutions. For further references, check the [Interoperability](/develop/interoperability/){target=\_blank} section. -- **Inherents first**: Inherent transactions, such as block timestamp updates, are always placed first. -- **Nonce-based ordering**: Transactions from the same account are ordered by their nonce. -- **Fee-based ordering**: Among transactions with the same nonce or priority level, those with higher fees are prioritized. +### Use Cases -### Transaction Execution +Polkadot Hub's smart contract platform is suitable for a wide range of applications: -Once a block author selects transactions from the pool, the transactions are executed in priority order. As each transaction is processed, the state changes are written directly to the chain's storage. It's important to note that these changes are not cached, meaning a failed transaction won't revert earlier state changes, which could leave the block in an inconsistent state. +- DeFi protocols leveraging _cross-chain capabilities_. +- NFT platforms utilizing Polkadot's native token standards. +- Governance systems integrated with Polkadot's democracy mechanisms. +- Cross-chain bridges and asset management solutions. -Events are also written to storage. Runtime logic should not emit an event before performing the associated actions. If the associated transaction fails after the event was emitted, the event will not revert. +## Other Smart Contract Environments -## Transaction Mortality +Beyond Polkadot Hub's native PolkaVM support, the ecosystem offers two main alternatives for smart contract development: -Transactions in the network can be configured as either mortal (with expiration) or immortal (without expiration). Every transaction payload contains a block checkpoint (reference block number and hash) and an era/validity period that determines how many blocks after the checkpoint the transaction remains valid. +- **EVM-compatible parachains**: Provide access to Ethereum's extensive developer ecosystem, smart contract portability, and established tooling like Hardhat, Remix, Foundry, and OpenZeppelin. The main options include Moonbeam (the first full Ethereum-compatible parachain serving as an interoperability hub), Astar (featuring dual VM support for both EVM and WebAssembly contracts), and Acala (DeFi-focused with enhanced Acala EVM+ offering advanced DeFi primitives). -When a transaction is submitted, the network validates it against these parameters. If the transaction is not included in a block within the specified validity window, it is automatically removed from the transaction queue. +- **Rust (ink!)**: ink! is a Rust-based framework that can compile to PolkaVM. It uses [`#[ink(...)]`](https://use.ink/docs/v6/macros-attributes/){target=\_blank} attribute macros to create Polkadot SDK-compatible PolkaVM bytecode, offering strong memory safety from Rust, an advanced type system, high-performance PolkaVM execution, and platform independence with sandboxed security. -- **Mortal transactions**: Have a finite lifespan and will expire after a specified number of blocks. For example, a transaction with a block checkpoint of 1000 and a validity period of 64 blocks will be valid from blocks 1000 to 1064. -- **Immortal transactions**: Never expire and remain valid indefinitely. To create an immortal transaction, set the block checkpoint to 0 (genesis block), use the genesis hash as a reference, and set the validity period to 0. +Each environment provides unique advantages based on developer preferences and application requirements. -However, immortal transactions pose significant security risks through replay attacks. If an account is reaped (balance drops to zero, account removed) and later re-funded, malicious actors can replay old immortal transactions. +## Where to Go Next -The blockchain maintains only a limited number of prior block hashes for reference validation, called `BlockHashCount`. If your validity period exceeds `BlockHashCount`, the effective validity period becomes the minimum of your specified period and the block hash count. +Developers can use their existing Ethereum development tools and connect to Polkadot Hub's RPC endpoints. The platform's Ethereum compatibility layer ensures a smooth transition for teams already building on Ethereum-compatible chains. -## Unique Identifiers for Extrinsics +Subsequent sections of this guide provide detailed information about specific development tools, advanced features, and best practices for building on Polkadot Hub. -Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. +
    -Key differences from traditional blockchains: +- Guide __Libraries__ -- Transaction hashes serve only as fingerprints of transaction information. -- Multiple valid transactions can share the same hash. -- Hash uniqueness assumptions lead to serious issues. + --- -For example, when an account is reaped (removed due to insufficient balance) and later recreated, it resets to nonce 0, allowing identical transactions to be valid at different points: + Explore essential libraries to optimize smart contract development and interaction. -| Block | Extrinsic Index | Hash | Origin | Nonce | Call | Result | -|-------|----------------|------|-----------|-------|---------------------|-------------------------------| -| 100 | 0 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Account A reaped | -| 150 | 5 | 0x02 | Account B | 4 | Transfer 7 DOT to A | Account A created (nonce = 0) | -| 200 | 2 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Successful transaction | + [:octicons-arrow-right-24: Reference](/smart-contracts/libraries/ethers-js/) -Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. +- Guide __Dev Environments__ -Additional complexity comes from Polkadot SDK's origin abstraction. Origins can represent collectives, governance bodies, or other non-account entities that don't maintain nonces like regular accounts and might dispatch identical calls multiple times with the same hash values. Each execution occurs in different chain states with different results. + --- -The correct way to uniquely identify an extrinsic on a Polkadot SDK-based chain is to use the block ID (height or hash) and the extrinsic index. Since the Polkadot SDK defines blocks as headers plus ordered arrays of extrinsics, the index position within a canonical block provides guaranteed uniqueness. + Set up your development environment for seamless contract deployment and testing. -## Additional Resources + [:octicons-arrow-right-24: Reference](/smart-contracts/dev-environments/local-dev-node/) -For a video overview of the lifecycle of transactions and the types of transactions that exist, see the [Transaction lifecycle](https://www.youtube.com/watch?v=3pfM0GOp02c){target=\_blank} seminar from Parity Tech. +
    --- @@ -10718,351 +6077,6 @@ The system maintains precise conversion mechanisms between: This ensures accurate fee calculation while maintaining compatibility with existing Ethereum tools and workflows. ---- - -Page Title: Transactions Weights and Fees - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md -- Canonical (HTML): https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/ -- Summary: Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. - -# Transactions Weights and Fees - -## Introductions - -When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop the network from producing new blocks. To protect blockchain resources from being drained or overloaded, you need to manage how they are made available and how they are consumed. The resources to be aware of include: - -- Memory usage -- Storage input and output -- Computation -- Transaction and block size -- State database size - -The Polkadot SDK provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource. Two of the most important mechanisms available to block authors are weights and transaction fees. - -[Weights](/reference/glossary/#weight){target=\_blank} manage the time it takes to validate a block and characterize the time it takes to execute the calls in the block's body. By controlling the execution time a block can consume, weights set limits on storage input, output, and computation. - -Some of the weight allowed for a block is consumed as part of the block's initialization and finalization. The weight might also be used to execute mandatory inherent extrinsic calls. To help ensure blocks don’t consume too much execution time and prevent malicious users from overloading the system with unnecessary calls, weights are combined with transaction fees. - -[Transaction fees](/reference/parachains/blocks-transactions-fees/transactions/#transaction-fees){target=\_blank} provide an economic incentive to limit execution time, computation, and the number of calls required to perform operations. Transaction fees are also used to make the blockchain economically sustainable because they are typically applied to transactions initiated by users and deducted before a transaction request is executed. - -## How Fees are Calculated - -The final fee for a transaction is calculated using the following parameters: - -- **`base fee`**: This is the minimum amount a user pays for a transaction. It is declared a base weight in the runtime and converted to a fee using the [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} conversion. -- **`weight fee`**: A fee proportional to the execution time (input and output and computation) that a transaction consumes. -- **`length fee`**: A fee proportional to the encoded length of the transaction. -- **`tip`**: An optional tip to increase the transaction’s priority, giving it a higher chance to be included in the transaction queue. - -The base fee and proportional weight and length fees constitute the inclusion fee. The inclusion fee is the minimum fee that must be available for a transaction to be included in a block. - -```text -inclusion fee = base fee + weight fee + length fee -``` - -Transaction fees are withdrawn before the transaction is executed. After the transaction is executed, the weight can be adjusted to reflect the resources used. If a transaction uses fewer resources than expected, the transaction fee is corrected, and the adjusted transaction fee is deposited. - -## Using the Transaction Payment Pallet - -The [Transaction Payment pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/transaction-payment){target=\_blank} provides the basic logic for calculating the inclusion fee. You can also use the Transaction Payment pallet to: - -- Convert a weight value into a deductible fee based on a currency type using [`Config::WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank}. -- Update the fee for the next block by defining a multiplier based on the chain’s final state at the end of the previous block using [`Config::FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank}. -- Manage the withdrawal, refund, and deposit of transaction fees using [`Config::OnChargeTransaction`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.OnChargeTransaction){target=\_blank}. - -You can learn more about these configuration traits in the [Transaction Payment documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_payment/index.html){target=\_blank}. - -### Understanding the Inclusion Fee - -The formula for calculating the inclusion fee is as follows: - -```text -inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] -``` - -And then, for calculating the final fee: - -```text -final_fee = inclusion_fee + tip -``` - -In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. - -- The `base_fee` derived from the base weight covers inclusion overhead like signature verification. -- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic. -- The `weight_fee` fee is calculated using two parameters: - - The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics. - - The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity. - -To convert the weight to `Currency`, the runtime must define a `WeightToFee` struct that implements a conversion function, [`Convert`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/struct.Pallet.html#method.weight_to_fee){target=\_blank}. - -Note that the extrinsic sender is charged the inclusion fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution. - -### Accounts with an Insufficient Balance - -If an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum existential deposit—then you should ensure the transaction is canceled so that no fee is deducted and the transaction does not begin execution. - -The Polkadot SDK doesn't enforce this rollback behavior. However, this scenario would be rare because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block. - -### Fee Multipliers - -The inclusion fee formula always results in the same fee for the same input. However, weight can be dynamic and—based on how [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} is defined—the final fee can include some degree of variability. -The Transaction Payment pallet provides the [`FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank} configurable parameter to account for this variability. - -The Polkadot network inspires the default update function and implements a targeted adjustment in which a target saturation level of block weight is defined. If the previous block is more saturated, the fees increase slightly. Similarly, if the last block has fewer transactions than the target, fees are decreased by a small amount. For more information about fee multiplier adjustments, see the [Web3 Research Page](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank}. - -## Transactions with Special Requirements - -Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: - -- Bonds are a type of fee that might be returned or slashed after some on-chain event. For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior. -- Deposits are fees that might be returned later. For example, you might require users to pay a deposit to execute an operation that uses storage. The user’s deposit could be returned if a subsequent operation frees up storage. -- Burn operations are used to pay for a transaction based on its internal logic. For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased state size. -- Limits enable you to enforce constant or configurable limits on specific operations. For example, the default [Staking pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/staking){target=\_blank} only allows nominators to nominate 16 validators to limit the complexity of the validator election process. - -It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. - -## Default Weight Annotations - -All dispatchable functions in the Polkadot SDK must specify a weight. The way of doing that is using the annotation-based system that lets you combine fixed values for database read/write weight and/or fixed values based on benchmarks. The most basic example would look like this: - -```rust -#[pallet::weight(100_000)] -fn my_dispatchable() { - // ... -} -``` - -Note that the [`ExtrinsicBaseWeight`](https://crates.parity.io/frame_support/weights/constants/struct.ExtrinsicBaseWeight.html){target=\_blank} is automatically added to the declared weight to account for the costs of simply including an empty extrinsic into a block. - -### Weights and Database Read/Write Operations - -To make weight annotations independent of the deployed database backend, they are defined as a constant and then used in the annotations when expressing database accesses performed by the dispatchable: - -```rust -#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] -fn my_dispatchable() { - // ... -} -``` - -This dispatchable allows one database to read and two to write, in addition to other things that add the additional 20,000. Database access is generally every time a value declared inside the [`#[pallet::storage]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} block is accessed. However, unique accesses are counted because after a value is accessed, it is cached, and reaccessing it does not result in a database operation. That is: - -- Multiple reads of the exact value count as one read. -- Multiple writes of the exact value count as one write. -- Multiple reads of the same value, followed by a write to that value, count as one read and one write. -- A write followed by a read-only counts as one write. - -### Dispatch Classes - -Dispatches are broken into three classes: - -- Normal -- Operational -- Mandatory - -If a dispatch is not defined as `Operational` or `Mandatory` in the weight annotation, the dispatch is identified as `Normal` by default. You can specify that the dispatchable uses another class like this: - -```rust -#[pallet::dispatch((DispatchClass::Operational))] -fn my_dispatchable() { - // ... -} -``` - -This tuple notation also allows you to specify a final argument determining whether the user is charged based on the annotated weight. If you don't specify otherwise, `Pays::Yes` is assumed: - -```rust -#[pallet::dispatch(DispatchClass::Normal, Pays::No)] -fn my_dispatchable() { - // ... -} -``` - -#### Normal Dispatches - -Dispatches in this class represent normal user-triggered transactions. These types of dispatches only consume a portion of a block's total weight limit. For information about the maximum portion of a block that can be consumed for normal dispatches, see [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Normal dispatches are sent to the transaction pool. - -#### Operational Dispatches - -Unlike normal dispatches, which represent the usage of network capabilities, operational dispatches are those that provide network capabilities. Operational dispatches can consume the entire weight limit of a block. They are not bound by the [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Dispatches in this class are given maximum priority and are exempt from paying the [`length_fee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/){target=\_blank}. - -#### Mandatory Dispatches - -Mandatory dispatches are included in a block even if they cause the block to surpass its weight limit. You can only use the mandatory dispatch class for inherent transactions that the block author submits. This dispatch class is intended to represent functions in the block validation process. Because these dispatches are always included in a block regardless of the function weight, the validation process must prevent malicious nodes from abusing the function to craft valid but impossibly heavy blocks. You can typically accomplish this by ensuring that: - -- The operation performed is always light. -- The operation can only be included in a block once. - -To make it more difficult for malicious nodes to abuse mandatory dispatches, they cannot be included in blocks that return errors. This dispatch class serves the assumption that it is better to allow an overweight block to be created than not to allow any block to be created at all. - -### Dynamic Weights - -In addition to purely fixed weights and constants, the weight calculation can consider the input arguments of a dispatchable. The weight should be trivially computable from the input arguments with some basic arithmetic: - -```rust -use frame_support:: { - dispatch:: { - DispatchClass::Normal, - Pays::Yes, - }, - weights::Weight, -}; - -#[pallet::weight(FunctionOf( - |args: (&Vec,)| args.0.len().saturating_mul(10_000), - ) -] -fn handle_users(origin, calls: Vec) { - // Do something per user -} -``` - -## Post Dispatch Weight Correction - -Depending on the execution logic, a dispatchable function might consume less weight than was prescribed pre-dispatch. To correct weight, the function declares a different return type and returns its actual weight: - -```rust -#[pallet::weight(10_000 + 500_000_000)] -fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo { - let was_heavy = do_calculation(input); - - if (was_heavy) { - // None means "no correction" from the weight annotation. - Ok(None.into()) - } else { - // Return the actual weight consumed. - Ok(Some(10_000).into()) - } -} -``` - -## Custom Fees - -You can also define custom fee systems through custom weight functions or inclusion fee functions. - -### Custom Weights - -Instead of using the default weight annotations, you can create a custom weight calculation type using the weights module. The custom weight calculation type must implement the following traits: - -- [`WeighData`](https://crates.parity.io/frame_support/weights/trait.WeighData.html){target=\_blank} to determine the weight of the dispatch. -- [`ClassifyDispatch`](https://crates.parity.io/frame_support/weights/trait.ClassifyDispatch.html){target=\_blank} to determine the class of the dispatch. -- [`PaysFee`](https://crates.parity.io/frame_support/weights/trait.PaysFee.html){target=\_blank} to determine whether the sender of the dispatch pays fees. - -The Polkadot SDK then bundles the output information of the three traits into the [`DispatchInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.DispatchInfo.html){target=\_blank} struct and provides it by implementing the [`GetDispatchInfo`](https://docs.rs/frame-support/latest/frame_support/dispatch/trait.GetDispatchInfo.html){target=\_blank} for all `Call` variants and opaque extrinsic types. This is used internally by the System and Executive modules. - -`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over T, which gets resolved into the tuple of all dispatch arguments except for the origin. The following example illustrates a struct that calculates the weight as `m * len(args)`, where `m` is a given multiplier and args is the concatenated tuple of all dispatch arguments. In this example, the dispatch class is `Operational` if the transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length exceeds 10 bytes. - -```rust -struct LenWeight(u32); -impl WeighData for LenWeight { - fn weigh_data(&self, target: T) -> Weight { - let multiplier = self.0; - let encoded_len = target.encode().len() as u32; - multiplier * encoded_len - } -} - -impl ClassifyDispatch for LenWeight { - fn classify_dispatch(&self, target: T) -> DispatchClass { - let encoded_len = target.encode().len() as u32; - if encoded_len > 100 { - DispatchClass::Operational - } else { - DispatchClass::Normal - } - } -} - -impl PaysFee { - fn pays_fee(&self, target: T) -> Pays { - let encoded_len = target.encode().len() as u32; - if encoded_len > 10 { - Pays::Yes - } else { - Pays::No - } - } -} -``` - -A weight calculator function can also be coerced to the final type of the argument instead of defining it as a vague type that can be encoded. The code would roughly look like this: - -```rust -struct CustomWeight; -impl WeighData<(&u32, &u64)> for CustomWeight { - fn weigh_data(&self, target: (&u32, &u64)) -> Weight { - ... - } -} - -// given a dispatch: -#[pallet::call] -impl, I: 'static> Pallet { - #[pallet::weight(CustomWeight)] - fn foo(a: u32, b: u64) { ... } -} -``` - -In this example, the `CustomWeight` can only be used in conjunction with a dispatch with a particular signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because there aren't any assumptions about ``. - -#### Custom Inclusion Fee - -The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. - -```rust -// Assume this is the balance type -type Balance = u64; - -// Assume we want all the weights to have a `100 + 2 * w` conversion to fees -struct CustomWeightToFee; -impl WeightToFee for CustomWeightToFee { - fn convert(w: Weight) -> Balance { - let a = Balance::from(100); - let b = Balance::from(2); - let w = Balance::from(w); - a + b * w - } -} - -parameter_types! { - pub const ExtrinsicBaseWeight: Weight = 10_000_000; -} - -impl frame_system::Config for Runtime { - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; -} - -parameter_types! { - pub const TransactionByteFee: Balance = 10; -} - -impl transaction_payment::Config { - type TransactionByteFee = TransactionByteFee; - type WeightToFee = CustomWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} - -struct TargetedFeeAdjustment(sp_std::marker::PhantomData); -impl> WeightToFee for TargetedFeeAdjustment { - fn convert(multiplier: Fixed128) -> Fixed128 { - // Don't change anything. Put any fee update info here. - multiplier - } -} -``` - -## Additional Resources - -You now know the weight system, how it affects transaction fee computation, and how to specify weights for your dispatchable calls. The next step is determining the correct weight for your dispatchable operations. You can use Substrate benchmarking functions and frame-benchmarking calls to test your functions with different parameters and empirically determine the proper weight in their worst-case scenarios. - -- [Benchmark](/parachains/customize-runtime/pallet-development/benchmark-pallet/) -- [`SignedExtension`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} -- [Custom weights for the Example pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/examples/basic/src/weights.rs){target=\_blank} -- [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} - - --- Page Title: Troubleshooting Remix IDE @@ -13432,94 +8446,6 @@ Now that you have the foundation for using Web3.py with Polkadot Hub, consider e
    ---- - -Page Title: XCM Tools - -- Source (raw): https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md -- Canonical (HTML): https://docs.polkadot.com/reference/tools/xcm-tools/ -- Summary: Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. - -# XCM Tools - -## Introduction - -As described in the [Interoperability](/develop/interoperability){target=\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem. - -As XCM is central to enabling communication between blockchains, developers need robust tools to help interact with, build, and test XCM messages. Several XCM tools simplify working with the protocol by providing libraries, frameworks, and utilities that enhance the development process, ensuring that applications built within the Polkadot ecosystem can efficiently use cross-chain functionalities. - -## Popular XCM Tools - -### Moonsong Labs XCM Tools - -[Moonsong Labs XCM Tools](https://github.com/Moonsong-Labs/xcm-tools){target=\_blank} provides a collection of scripts for managing and testing XCM operations between Polkadot SDK-based runtimes. These tools allow performing tasks like asset registration, channel setup, and XCM initialization. Key features include: - -- **Asset registration**: Registers assets, setting units per second (up-front fees), and configuring error (revert) codes. -- **XCM initializer**: Initializes XCM, sets default XCM versions, and configures revert codes for XCM-related precompiles. -- **HRMP manipulator**: Manages HRMP channel actions, including opening, accepting, or closing channels. -- **XCM-Transactor-Info-Setter**: Configures transactor information, including extra weight and fee settings. -- **Decode XCM**: Decodes XCM messages on the relay chain or parachains to help interpret cross-chain communication. - -To get started, clone the repository and install the required dependencies: - -```bash -git clone https://github.com/Moonsong-Labs/xcm-tools && -cd xcm-tools && -yarn install -``` - -For a full overview of each script, visit the [scripts](https://github.com/Moonsong-Labs/xcm-tools/tree/main/scripts){target=\_blank} directory or refer to the [official documentation](https://github.com/Moonsong-Labs/xcm-tools/blob/main/README.md){target=\_blank} on GitHub. - -### ParaSpell - -[ParaSpell](/reference/tools/paraspell/){target=\_blank} is a collection of open-source XCM tools that streamline cross-chain asset transfers and interactions across the Polkadot and Kusama ecosystems. It provides developers with an intuitive interface to build, test, and deploy interoperable dApps, featuring message composition, decoding, and practical utilities for parachain interactions that simplify debugging and cross-chain communication optimization. - -### Astar XCM Tools - -The [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks: - -- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command. -- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments. -- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs. - -To start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\_blank} and compile the xcm-tools package: - -```bash -git clone https://github.com/AstarNetwork/Astar && -cd Astar && -cargo build --release -p xcm-tools -``` - -After compiling, verify the setup with the following command: - -```bash -./target/release/xcm-tools --help -``` -For more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\_blank}. - -### Chopsticks - -The Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\_blank} about XCM. - -### Moonbeam XCM SDK - -The [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank} of the origin or destination assets or which extrinsics are used on which networks. - -The SDK consists of two main packages: - -- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem. -- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum. - -Key features include: - -- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection. -- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems. -- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality. -- **Comprehensive documentation**: Includes usage guides and API references for both packages. - -For detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\_blank}. - - --- Page Title: Zero to Hero Smart Contract DApp @@ -13764,7 +8690,7 @@ After deployment, you'll need the contract's Application Binary Interface (ABI) Now that you have your contract deployed, you're ready to build the dApp that will interact with it! -## Set Up the dApp Project +## Set Up the DApp Project Navigate to the root of the project, and create a new Next.js project called `dapp`: diff --git a/.ai/pages/chain-interactions-accounts-create-account.md b/.ai/pages/chain-interactions-accounts-create-account.md deleted file mode 100644 index 7794b8456..000000000 --- a/.ai/pages/chain-interactions-accounts-create-account.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/chain-interactions/accounts/create-account/ ---- - -TODO diff --git a/.ai/pages/chain-interactions-accounts-query-accounts.md b/.ai/pages/chain-interactions-accounts-query-accounts.md deleted file mode 100644 index 00241f7bb..000000000 --- a/.ai/pages/chain-interactions-accounts-query-accounts.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/chain-interactions/accounts/query-accounts/ ---- - -TODO diff --git a/.ai/pages/chain-interactions-query-data-query-rest.md b/.ai/pages/chain-interactions-query-data-query-rest.md deleted file mode 100644 index 1bee0d745..000000000 --- a/.ai/pages/chain-interactions-query-data-query-rest.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/chain-interactions/query-data/query-rest/ ---- - -TODO diff --git a/.ai/pages/chain-interactions-query-data-query-sdks.md b/.ai/pages/chain-interactions-query-data-query-sdks.md deleted file mode 100644 index 538d665ff..000000000 --- a/.ai/pages/chain-interactions-query-data-query-sdks.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/chain-interactions/query-data/query-sdks/ ---- - -TODO diff --git a/.ai/pages/chain-interactions-query-data-runtime-api-calls.md b/.ai/pages/chain-interactions-query-data-runtime-api-calls.md deleted file mode 100644 index 7c9eeaf30..000000000 --- a/.ai/pages/chain-interactions-query-data-runtime-api-calls.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/chain-interactions/query-data/runtime-api-calls/ ---- - -TODO diff --git a/.ai/pages/chain-interactions-send-transactions-calculate-transaction-fees.md b/.ai/pages/chain-interactions-send-transactions-calculate-transaction-fees.md deleted file mode 100644 index 1d2c06486..000000000 --- a/.ai/pages/chain-interactions-send-transactions-calculate-transaction-fees.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/chain-interactions/send-transactions/calculate-transaction-fees/ ---- - -TODO diff --git a/.ai/pages/chain-interactions-send-transactions-interoperability-debug-and-preview-xcms.md b/.ai/pages/chain-interactions-send-transactions-interoperability-debug-and-preview-xcms.md deleted file mode 100644 index ba718c4c6..000000000 --- a/.ai/pages/chain-interactions-send-transactions-interoperability-debug-and-preview-xcms.md +++ /dev/null @@ -1,512 +0,0 @@ ---- -title: Replay and Dry Run XCMs -description: Replay and dry-run XCMs using Chopsticks with full logging enabled. Diagnose issues, trace message flow, and debug complex cross-chain interactions. -url: https://docs.polkadot.com/chain-interactions/send-transactions/interoperability/debug-and-preview-xcms/ ---- - -# Replay and Dry Run XCMs Using Chopsticks - -## Introduction - -In this tutorial, you'll learn how to replay and dry-run XCMs using [Chopsticks](/parachains/testing/fork-a-parachain/){target=\_blank}, a powerful tool for forking live Polkadot SDK-based chains in your local environment. These techniques are essential for: - -- Debugging cross-chain message failures. -- Tracing execution across relay chains and parachains. -- Analyzing weight usage, error types, and message flow. -- Safely simulating XCMs without committing state changes. - -By the end of this guide, you'll be able to set up a local fork, capture and replay real XCMs, and use dry-run features to diagnose and resolve complex cross-chain issues. - -## Prerequisites - -Before you begin, make sure you have: - -- [Chopsticks](/parachains/testing/fork-a-parachain/){target=\_blank} installed (`npm i -g @acala-network/chopsticks`). -- Access to the endpoint or genesis file of the parachain you want to fork. -- The block number or hash where the XCM was sent. -- (Optional) A Chopsticks config file for repeated setups. - -If you haven't forked a chain before, see the [Fork a Chain with Chopsticks guide](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\_blank} or [Fork a Network Locally using Chopsticks](https://wiki.polkadot.com/learn/learn-guides-test-opengov-proposals/#fork-a-network-locally-using-chopsticks){target=\_blank} for step-by-step instructions. - -## Set Up Your Project - -Let's start by creating a dedicated workspace for your XCM replay and dry-run experiments. - -1. Create a new directory and navigate into it: - - ```bash - mkdir -p replay-xcm-tests - cd replay-xcm-tests - ``` - -2. Initialize a new Node project: - - ```bash - npm init -y - ``` - -3. Install Chopsticks globally (recommended to avoid conflicts with local installs): - - ```bash - npm install -g @acala-network/chopsticks@latest - ``` - -4. Install TypeScript and related tooling for local development: - - ```bash - npm install --save-dev typescript @types/node tsx - ``` - -5. Install the required Polkadot packages: - - ```bash - npm install polkadot-api @polkadot-labs/hdkd @polkadot-labs/hdkd-helpers - ``` - -6. Initialize the TypeScript config: - - ```bash - npx tsc --init - ``` - -## Capture the XCM to Replay - -To replay a specific XCM, identify: - -- The source and destination chains involved. -- The block number or height where the XCM was sent. -- Optionally, the call payload (if you plan to simulate it manually via development commands). - -You can use [Polkadot.js Apps](/tutorials/polkadot-sdk/testing/fork-live-chains/#use-polkadotjs-apps){target=\_blank}, [papi console](https://dev.papi.how/){target=\_blank}, or indexers such as [Subscan](https://polkadot.subscan.io/xcm_dashboard){target=\_blank} to locate and inspect the original XCM execution. - -## Fork the Relevant Chains - -Use Chopsticks to [fork the required chains](/tutorials/polkadot-sdk/testing/fork-live-chains/#xcm-testing){target=\_blank} at the appropriate block heights. - -### Set the Block Numbers - -Create/edit a `.env` file with the block heights for each chain. These should be just before the XCM is sent to allow a full replay: - -```text title=".env" -POLKADOT_BLOCK_NUMBER=26481107 -POLKADOT_ASSET_HUB_BLOCK_NUMBER=9079591 -ACALA_BLOCK_NUMBER=8826385 -``` - -### Enable Logging and Wasm Override - -Full execution logs only work if the runtime was compiled with logging enabled. Most live chains are built using the `production` profile, which disables logs. To enable logging, you'll need to override the Wasm with a locally built `release` or `debug` version. The `release` profile is faster to load in Chopsticks. - -1. Clone the `polkadot-fellows/runtimes` repository: - - ```bash - git clone git@github.com:polkadot-fellows/runtimes.git - ``` - -2. Build the Polkadot Asset Hub runtime: - - ```bash - cd runtimes - # Build with the `debug` profile (default): - # cargo build -p asset-hub-polkadot-runtime - - # Build with the `release` profile (faster to load in Chopsticks) - cargo build --release -p asset-hub-polkadot-runtime - ``` - -3. Copy the compiled Wasm to your working directory: - - ```bash - # Assuming you're still in the `runtimes` directory - mkdir -p ../wasms # or your /wasms path - - # Copy the compiled Wasm to your working directory: - - # If built with the `debug` profile: - # cp target/debug/wbuild/asset-hub-polkadot-runtime/asset_hub_polkadot_runtime.wasm ../wasms - - # If built with the `release` profile: - cp target/release/wbuild/asset-hub-polkadot-runtime/asset_hub_polkadot_runtime.compact.compressed.wasm ../wasms - ``` - -4. Download and modify a config file: - - ```bash - # Still in the `runtimes` directory - cd .. # Return to your replay-xcm-tests root - mkdir -p configs - wget https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -O configs/polkadot-asset-hub-override.yaml - ``` - -5. Edit `configs/polkadot-asset-hub-override.yaml` to include: - - {% raw %} - ```yaml title="configs/polkadot-asset-hub-override.yaml" - ... - runtime-log-level: 5 - # wasm-override: wasms/asset_hub_polkadot_runtime.wasm # Uncomment if using the `debug` build - wasm-override: wasms/asset_hub_polkadot_runtime.compact.compressed.wasm # Use this if you built with `release` - ... - ``` - {% endraw %} - -6. Start the forked chains using your custom config: - - ```bash - npx @acala-network/chopsticks xcm \ - -r polkadot \ - -p configs/polkadot-asset-hub-override.yaml \ - -p acala - ``` - - This command starts the relay chain and parachains locally, with full runtime execution logs enabled. Once the chains are running, you should see output indicating that the following RPC endpoints are available: - - - Polkadot Asset Hub RPC on `http://localhost:8000` - - Acala RPC on `http://localhost:8001` - - Polkadot RPC on `http://localhost:8002` - - You'll also see runtime logs such as: - -
    - npx @acala-network/chopsticks xcm \ -r polkadot \ -p configs/polkadot-asset-hub-override.yaml \ -p acala - [09:29:14.988] INFO: Polkadot Asset Hub RPC listening on http://[::]:8000 and ws://[::]:8000 - [09:29:14.988] INFO: Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/acala.yml - [09:29:15.984] INFO: Acala RPC listening on http://[::]:8001 and ws://[::]:8001 - [09:29:15.990] INFO (xcm): Connected parachains [1000,2000] - [09:29:15.990] INFO: Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot.yml - [09:29:16.927] INFO: Polkadot RPC listening on http://[::]:8002 and ws://[::]:8002 - [09:29:16.984] INFO (xcm): Connected relaychain 'Polkadot' with parachain 'Polkadot Asset Hub' - [09:29:17.028] INFO (xcm): Connected relaychain 'Polkadot' with parachain 'Acala' -
    - -## Identify and Extract the XCM - -To replay an XCM, you'll first need to identify the exact extrinsic that triggered it. In this example, we'll use block 9079592 on the Polkadot Asset Hub. - -1. Find and open the block on Subscan to inspect its extrinsics and events. In this case, the block is [9079592](https://assethub-polkadot.subscan.io/block/9079592){target=\_blank}. - -2. Copy the black hash. Look for the block hash at the top of the page. For block 9079592, the hash is: - - ```bash title="Block Hash" - 0xeb5a5737d47367dc1c02b978232283cdb096eb7e51d2eb22366a106a011347f6 - ``` - -3. Explore and view the block in [Polkadot.Js Apps](https://polkadot.js.org/apps){target=\_blank} using this direct link: [Block Hash Explorer](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot-asset-hub-rpc.polkadot.io#/explorer/query/0xeb5a5737d47367dc1c02b978232283cdb096eb7e51d2eb22366a106a011347f6){target=\_blank}. - -4. Locate and decode the XCM extrinsic. Once you've found the extrinsic (e.g., 9079592-2), extract and decode its call data. For example, the call data is: - - ```bash title="Call Data" - 0xad028400fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c820016a30461702adc48213e5c9ee4d15c5a481c578cb5cbc935f0bd11fe8aee489082a745ffbbe94282f91b67daa6cb44920d77c30849c1d25f5f6c3e59015a3e383440055040000011f0803010100411f0300010100fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c8200304000002043205011f0092e81d790000000000 - ``` - -5. From the decoded view, copy the **hex-encoded call** (e.g. `0x1f08...0000`). You'll pass this into `api.txFromCallData(...)` to replay the XCM locally. - -## Replay the XCM - -Once your project is set up, you're ready to replay the XCM locally. - -This is useful for: - -- Diagnosing execution failures or weight limits. -- Inspecting all emitted events. -- Verifying behaviour before submitting a real transaction. - -### Add the Asset Hub Descriptor - -This will let you use type-safe APIs with PAPI: - -```bash -npx papi add assetHub -w ws://localhost:8000 -``` - -The script assumes the Polkadot Asset Hub is served on `ws://localhost:8000`. If you're using a different port or config, update the WebSocket endpoint in the script or descriptor. You can confirm the port by checking your terminal logs or by seeing [Launch Chopsticks](#launch-chopsticks). - -### Create a Replay Script - -Create a file named `replay-xcm.ts` and copy the following code into it: - -```ts -import { Binary, createClient, Transaction } from 'polkadot-api'; -import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat'; -import { getPolkadotSigner } from 'polkadot-api/signer'; -import { getWsProvider } from 'polkadot-api/ws-provider/web'; -import { assetHub } from '@polkadot-api/descriptors'; -import { sr25519CreateDerive } from '@polkadot-labs/hdkd'; -import { - DEV_PHRASE, - entropyToMiniSecret, - mnemonicToEntropy, -} from '@polkadot-labs/hdkd-helpers'; - -const toHuman = (_key: any, value: any) => { - if (typeof value === 'bigint') { - return Number(value); - } - - if (value && typeof value === 'object' && typeof value.asHex === 'function') { - return value.asHex(); - } - - return value; -}; - -function getSigner() { - const entropy = mnemonicToEntropy(DEV_PHRASE); - const miniSecret = entropyToMiniSecret(entropy); - const derive = sr25519CreateDerive(miniSecret); - const alice = derive('//Alice'); - - return getPolkadotSigner(alice.publicKey, 'Sr25519', alice.sign); -} - -async function main() { - const provider = withPolkadotSdkCompat(getWsProvider('ws://localhost:8000')); - const client = createClient(provider); - const api = client.getTypedApi(assetHub); - const aliceSigner = getSigner(); - - const callData = Binary.fromHex( - '0x1f0803010100411f0300010100fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c8200304000002043205011f0092e81d790000000000', - ); - const tx: Transaction = - await api.txFromCallData(callData); - console.log('👀 Executing XCM:', JSON.stringify(tx.decodedCall, toHuman, 2)); - - await new Promise((resolve) => { - const subscription = tx.signSubmitAndWatch(aliceSigner).subscribe((ev) => { - if ( - ev.type === 'finalized' || - (ev.type === 'txBestBlocksState' && ev.found) - ) { - console.log( - `📦 Included in block #${ev.block.number}: ${ev.block.hash}`, - ); - - if (!ev.ok) { - const dispatchError = ev.dispatchError; - if (dispatchError.type === 'Module') { - const modErr: any = dispatchError.value; - console.error( - `❌ Dispatch error in module: ${modErr.type} → ${modErr.value?.type}`, - ); - } else { - console.error( - '❌ Dispatch error:', - JSON.stringify(dispatchError, toHuman, 2), - ); - } - } - - for (const event of ev.events) { - console.log( - '📣 Event:', - event.type, - JSON.stringify(event.value, toHuman, 2), - ); - } - - console.log('✅ Process completed, exiting...'); - subscription.unsubscribe(); - resolve(); - } - }); - }); - - client.destroy(); -} - -main().catch(console.error); - -``` - -### Execute the Replay Script - -Ensure Chopsticks is running and serving a chain that includes `pallet-xcm`, such as a Polkadot Asset Hub fork. Then run: - -```bash -npx tsx replay-xcm.ts -``` - -### Expected Output - -If everything is working, you'll see logs like: - -
    - npx tsx replay-xcm.ts -
    -executing xcm: {
    -  "type": "polkadotxcm",
    -  "value": {
    -    "type": "limited_reserve_transfer_assets",
    -    "value": {
    -      "dest": { "parents": 0, "interior": { "X1": [{ "Parachain": 2006 }] } },
    -      "beneficiary": { "parents": 0, "interior": { "X1": [{ "AccountId32": { "network": null, "id": "0x..." } }] } },
    -      "assets": [{ "id": { "Concrete": { "parents": 0, "interior": "Here" } }, "fun": { "Fungible": 120000000000 } }],
    -      "fee_asset_item": 0,
    -      "weight_limit": { "type": "Unlimited" }
    -    }
    -  }
    -}
    -  
    - 📦 Included in block #9079592: 0x227a11c64f6051ba2e090a13abd17e5f7581640a80f6c03fc2d43fac66ab7949 - 📣 Event: Balances { "type": "Upgraded", "value": { ... } } - 📣 Event: Balances { "type": "Withdraw", "value": { ... } } - 📣 Event: Assets { "type": "Transferred", "value": { ... } } - 📣 Event: PolkadotXcm { "type": "Attempted", "value": { ... } } - 📣 Event: Balances { "type": "Burned", "value": { ... } } - 📣 Event: Balances { "type": "Minted", "value": { ... } } - 📣 Event: PolkadotXcm { "type": "FeesPaid", "value": { ... } } - 📣 Event: XcmpQueue { "type": "XcmpMessageSent", "value": { ... } } - 📣 Event: PolkadotXcm { "type": "Sent", "value": { ... } } - 📣 Event: Balances { "type": "Deposit", "value": { ... } } - 📣 Event: TransactionPayment { "type": "TransactionFeePaid", "value": { ... } } - 📣 Event: System { "type": "ExtrinsicSuccess", "value": { ... } } - ✅ Process completed, exiting... -
    - -## Dry Run the XCM - -To simulate the XCM without actually sending it, you can use the `dry_run_call` method. This lets you check whether the XCM would succeed without modifying any state. - -### Create a Dry Run Script - -Assuming you've the `tx` transaction from the previous step, you can create a new script, `dry-run-call.ts`, then paste in the following code: - -```ts -import { Binary, createClient, Enum } from 'polkadot-api'; -import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat'; -import { getWsProvider } from 'polkadot-api/ws-provider/web'; -import { assetHub } from '@polkadot-api/descriptors'; -import { sr25519CreateDerive } from '@polkadot-labs/hdkd'; -import { - DEV_PHRASE, - entropyToMiniSecret, - mnemonicToEntropy, - ss58Address, -} from '@polkadot-labs/hdkd-helpers'; - -const XCM_VERSION = 5; - -async function main() { - const provider = withPolkadotSdkCompat(getWsProvider('ws://localhost:8000')); - const client = createClient(provider); - const api = client.getTypedApi(assetHub); - - const entropy = mnemonicToEntropy(DEV_PHRASE); - const miniSecret = entropyToMiniSecret(entropy); - const derive = sr25519CreateDerive(miniSecret); - const alice = derive('//Alice'); - const aliceAddress = ss58Address(alice.publicKey); - - const callData = Binary.fromHex( - '0x1f0803010100411f0300010100fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c8200304000002043205011f0092e81d790000000000', - ); - const tx: any = await api.txFromCallData(callData); - const origin = Enum('system', Enum('Signed', aliceAddress)); - const dryRunResult: any = await api.apis.DryRunApi.dry_run_call( - origin, - tx.decodedCall, - XCM_VERSION, - ); - console.dir(dryRunResult.value, { depth: null }); - - client.destroy(); -} - -main().catch(console.error); - -``` - -Ensure your local Chopsticks fork is running and the ports match those used in the script. - -### Execute the Dry Run Script - -```bash -npx tsx dry-run-call.ts -``` - -If successful, the dry run confirms that the XCM would execute correctly: - -
    - npx tsx dry-run-call.ts -
    -execution_result: {
    -  "success": true,
    -  "value": {
    -    "post_info": { "actual_weight": 123456, "pays_fee": "Yes" },
    -    "result": "Ok"
    -  }
    -}
    -emitted_events: [ { "section": "Balances", "method": "Transfer", "data": { "from": "0x...", "to": "0x...", "amount": 1000000000 } } ]
    -local_xcm: { "type": "SomeType", "value": { ... } }
    -forwarded_xcms: []
    -  
    - ✅ Dry run succeeded - ✅ Process completed, exiting... -
    - -If it fails, you'll receive detailed error information: - -
    - npx tsx dry-run-call.ts -
    -execution_result: {
    -  "success": false,
    -  "value": {
    -    "post_info": { "actual_weight": 123456, "pays_fee": "Yes" },
    -    "error": {
    -      "type": "Module",
    -      "value": {
    -        "type": "PolkadotXcm",
    -        "value": { "type": "LocalExecutionIncomplete", "value": null }
    -      }
    -    }
    -  }
    -}
    -  
    - ❌ Dry run failed: LocalExecutionIncomplete - ✅ Process completed, exiting... -
    - -For more information, see: - -- [Dry Run Call](/develop/interoperability/xcm-runtime-apis/#dry-run-call){target=\_blank} to simulate a full extrinsic -- [Dry Run XCM](/develop/interoperability/xcm-runtime-apis/#dry-run-xcm){target=\_blank} to simulate a raw XCM - -## Review and Debug - -Replaying XCMs with full logging provides fine-grained control and visibility into cross-chain message behaviour. Chopsticks makes this possible in a safe, local environment – empowering developers to: - -- Debug complex message flows. -- Identify root causes of XCM failures. -- Improve observability for future integrations. - -## Where to Go Next - -
    - -- External __Chopsticks Repository__ - - --- - - View the official Chopsticks GitHub repository. - - [:octicons-arrow-right-24: Get Started](https://github.com/AcalaNetwork/chopsticks/) - -- Guide __Polkadot XCM Docs__ - - --- - - Learn how to use XCM effectively. - - [:octicons-arrow-right-24: Get Started](/parachains/interoperability/get-started/) - -- Tutorial __XCM Runtime APIs__ - - --- - - Learn how to use XCM Runtime APIs. - - [:octicons-arrow-right-24: Get Started](/develop/interoperability/xcm-runtime-apis/) - -
    diff --git a/.ai/pages/chain-interactions-send-transactions-interoperability-estimate-xcm-fees.md b/.ai/pages/chain-interactions-send-transactions-interoperability-estimate-xcm-fees.md deleted file mode 100644 index af70b2fb4..000000000 --- a/.ai/pages/chain-interactions-send-transactions-interoperability-estimate-xcm-fees.md +++ /dev/null @@ -1,1100 +0,0 @@ ---- -title: XCM Fee Estimation -description: This tutorial demonstrates how to estimate the fees for teleporting assets from the Paseo Asset Hub parachain to the Paseo Bridge Hub chain. -url: https://docs.polkadot.com/chain-interactions/send-transactions/interoperability/estimate-xcm-fees/ ---- - -# XCM Fee Estimation - -## Introduction - -When sending cross-chain messages, ensure that the transaction will be successful not only in the local chain but also in the destination chain and any intermediate chains. - -Sending cross-chain messages requires estimating the fees for the operation. - -This tutorial will demonstrate how to dry-run and estimate the fees for teleporting assets from the Paseo Asset Hub parachain to the Paseo Bridge Hub chain. - -## Fee Mechanism - -There are three types of fees that can be charged when sending a cross-chain message: - -- **Local execution fees**: Fees charged in the local chain for executing the message. -- **Delivery fees**: Fees charged for delivering the message to the destination chain. -- **Remote execution fees**: Fees charged in the destination chain for executing the message. - -If there are multiple intermediate chains, delivery fees and remote execution fees will be charged for each one. - -In this example, you will estimate the fees for teleporting assets from the Paseo Asset Hub parachain to the Paseo Bridge Hub chain. The fee structure will be as follows: - -```mermaid -flowchart LR - AssetHub[Paseo Asset Hub] -->|Delivery Fees| BridgeHub[Paseo Bridge Hub] - AssetHub -->|
    Local
    Execution
    Fees| AssetHub - BridgeHub -->|
    Remote
    Execution
    Fees| BridgeHub -``` - -The overall fees are `local_execution_fees` + `delivery_fees` + `remote_execution_fees`. - -## Environment Setup - -First, you need to set up your environment: - -1. Create a new directory and initialize the project: - - ```bash - mkdir xcm-fee-estimation && \ - cd xcm-fee-estimation - ``` - -2. Initialize the project: - - ```bash - npm init -y - ``` - -3. Install dev dependencies: - - ```bash - npm install --save-dev @types/node@^22.12.0 ts-node@^10.9.2 typescript@^5.7.3 - ``` - -4. Install dependencies: - - ```bash - npm install --save @polkadot-labs/hdkd@^0.0.13 @polkadot-labs/hdkd-helpers@^0.0.13 polkadot-api@1.9.5 - ``` - -5. Create TypeScript configuration: - - ```bash - npx tsc --init - ``` - -6. Generate the types for the Polkadot API for Paseo Bridge Hub and Paseo Asset Hub: - - ```bash - npx papi add paseoAssetHub -n paseo_asset_hub && \ - npx papi add paseoBridgeHub -w wss://bridge-hub-paseo.dotters.network - ``` - -7. Create a new file called `teleport-ah-to-bridge-hub.ts`: - - ```bash - touch teleport-ah-to-bridge-hub.ts - ``` - -8. Import the necessary modules. Add the following code to the `teleport-ah-to-bridge-hub.ts` file: - - ```typescript title="teleport-ah-to-bridge-hub.ts" - import { paseoAssetHub, paseoBridgeHub } from '@polkadot-api/descriptors'; - import { createClient, FixedSizeBinary, Enum } from 'polkadot-api'; - import { getWsProvider } from 'polkadot-api/ws-provider/node'; - import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat'; - import { - XcmVersionedLocation, - XcmVersionedAssetId, - XcmV3Junctions, - XcmV3MultiassetFungibility, - XcmVersionedXcm, - XcmV5Instruction, - XcmV5Junctions, - XcmV5Junction, - XcmV5AssetFilter, - XcmV5WildAsset, - } from '@polkadot-api/descriptors'; - ``` - -9. Define constants and a `main` function where you will implement all the logic: - - ```typescript title="teleport-ah-to-bridge-hub.ts" - // 1 PAS = 10^10 units - const PAS_UNITS = 10_000_000_000n; // 1 PAS - const PAS_CENTS = 100_000_000n; // 0.01 PAS - - // Paseo Asset Hub constants - const PASEO_ASSET_HUB_RPC_ENDPOINT = 'ws://localhost:8001'; - const ASSET_HUB_ACCOUNT = '15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5'; // Alice (Paseo Asset Hub) - - // Bridge Hub destination - const BRIDGE_HUB_RPC_ENDPOINT = 'ws://localhost:8000'; - const BRIDGE_HUB_PARA_ID = 1002; - const BRIDGE_HUB_BENEFICIARY = - async function main() { - // Code will go here - } - ``` - -All the following code explained in the subsequent sections must be added inside the `main` function. - -## Client and API Setup - -Now you are ready to start implementing the logic for the fee estimation for the teleport you want to perform. In this step, you will create the client for the Paseo Asset Hub parachain and generate the typed API to interact with the chain. Follow the steps below: - -Create the API client. You will need to create a client for the Paseo Asset Hub parachain: - -```typescript title="teleport-ah-to-bridge-hub.ts" - // Connect to the Asset Hub parachain - const assetHubClient = createClient( - withPolkadotSdkCompat(getWsProvider(PASEO_ASSET_HUB_RPC_ENDPOINT)), - ); - - // Get the typed API for Asset Hub - const assetHubApi = assetHubClient.getTypedApi(paseoAssetHub); -``` - -Ensure that you replace the endpoint URLs with the actual WebSocket endpoints. This example uses local chopsticks endpoints, but you can use public endpoints or run local nodes. - -## Create the XCM Message - -Now, you can construct a proper XCM message using the new XCM V5 instructions for teleporting from Asset Hub to the Bridge Hub Chain: - -```typescript title="teleport-ah-to-bridge-hub.ts" -function createTeleportXcmToBridgeHub(paraId: number) { - return XcmVersionedXcm.V5([ - // Withdraw PAS from Asset Hub (PAS on parachains is parents:1, interior: Here) - XcmV5Instruction.WithdrawAsset([ - { - id: { parents: 1, interior: XcmV5Junctions.Here() }, - fun: XcmV3MultiassetFungibility.Fungible(1n * PAS_UNITS), // 1 PAS - }, - ]), - // Pay local fees on Asset Hub in PAS - XcmV5Instruction.PayFees({ - asset: { - id: { parents: 1, interior: XcmV5Junctions.Here() }, - fun: XcmV3MultiassetFungibility.Fungible(10n * PAS_CENTS), // 0.01 PAS - }, - }), - // Send to Bridge Hub parachain (parents:1, interior: X1(Parachain(paraId))) - XcmV5Instruction.InitiateTransfer({ - destination: { - parents: 1, - interior: XcmV5Junctions.X1(XcmV5Junction.Parachain(paraId)), - }, - remote_fees: Enum( - 'Teleport', - XcmV5AssetFilter.Definite([ - { - id: { parents: 1, interior: XcmV5Junctions.Here() }, - fun: XcmV3MultiassetFungibility.Fungible(10n * PAS_CENTS), // 0.01 PAS - }, - ]), - ), - preserve_origin: false, - remote_xcm: [ - XcmV5Instruction.DepositAsset({ - assets: XcmV5AssetFilter.Wild(XcmV5WildAsset.AllCounted(1)), - beneficiary: { - parents: 0, - interior: XcmV5Junctions.X1( - XcmV5Junction.AccountId32({ - network: undefined, - id: FixedSizeBinary.fromAccountId32(BRIDGE_HUB_BENEFICIARY), - }), - ), - }, - }), - ], - assets: [ - Enum('Teleport', XcmV5AssetFilter.Wild(XcmV5WildAsset.AllCounted(1))), // Send everything. - ], - }), - ]); -} -``` - -## Fee Estimation Function - -Below is a four-step breakdown of the logic needed to estimate the fees for the teleport. - -First, you need to create the function that will estimate the fees for the teleport: - -```typescript title="teleport-ah-to-bridge-hub.ts" -async function estimateXcmFeesFromAssetHubToBridgeHub( - xcm: any, - assetHubApi: any, -) { - // Code will go here -} -``` - -1. **Local execution fees on Asset Hub**: Compute the XCM weight locally, then convert that weight to PAS using Asset Hub's view of PAS (`parents: 1, interior: Here`). Add the code to the function: - - ```typescript title="teleport-ah-to-bridge-hub.ts" - console.log('=== Fee Estimation Process (Asset Hub → Bridge Hub) ==='); - - // 1. LOCAL EXECUTION FEES on Asset Hub - console.log('1. Calculating local execution fees on Asset Hub...'); - let localExecutionFees = 0n; - - const weightResult = - await assetHubApi.apis.XcmPaymentApi.query_xcm_weight(xcm); - if (weightResult.success) { - console.log('✓ XCM weight (Asset Hub):', weightResult.value); - - // Convert weight to PAS fees from Asset Hub's perspective (parents:1, Here) - const executionFeesResult = - await assetHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee( - weightResult.value, - XcmVersionedAssetId.V4({ - parents: 1, - interior: XcmV3Junctions.Here(), - }), - ); - - if (executionFeesResult.success) { - localExecutionFees = executionFeesResult.value; - console.log( - '✓ Local execution fees (Asset Hub):', - localExecutionFees.toString(), - 'PAS units', - ); - } else { - console.log( - '✗ Failed to calculate local execution fees:', - executionFeesResult.value, - ); - } - } else { - console.log( - '✗ Failed to query XCM weight on Asset Hub:', - weightResult.value, - ); - } - ``` - -2. **Dry-run and delivery fees to Bridge Hub**: Dry-run the XCM on Asset Hub to capture forwarded messages, locate the one targeting Bridge Hub (`parents: 1, interior: Here`), and ask for delivery fees. Add the code to the function: - - ```typescript title="teleport-ah-to-bridge-hub.ts" - // 2. DELIVERY FEES + REMOTE EXECUTION FEES - console.log('\n2. Calculating delivery and remote execution fees...'); - let deliveryFees = 0n; - let remoteExecutionFees = 0n; // Skipped (Bridge Hub descriptor not available) - - // Origin from Asset Hub perspective - const origin = XcmVersionedLocation.V5({ - parents: 0, - interior: XcmV5Junctions.X1( - XcmV5Junction.AccountId32({ - id: FixedSizeBinary.fromAccountId32(ASSET_HUB_ACCOUNT), - network: undefined, - }), - ), - }); - - // Dry run the XCM locally on Asset Hub - const dryRunResult = await assetHubApi.apis.DryRunApi.dry_run_xcm( - origin, - xcm, - ); - - if ( - dryRunResult.success && - dryRunResult.value.execution_result.type === 'Complete' - ) { - console.log('✓ Local dry run on Asset Hub successful'); - - const { forwarded_xcms: forwardedXcms } = dryRunResult.value; - - // Find the XCM message sent to Bridge Hub (parents:1, interior: X1(Parachain(1002))) - const bridgeHubXcmEntry = forwardedXcms.find( - ([location, _]: [any, any]) => - (location.type === 'V4' || location.type === 'V5') && - location.value.parents === 1 && - location.value.interior?.type === 'X1' && - location.value.interior.value?.type === 'Parachain' && - location.value.interior.value.value === BRIDGE_HUB_PARA_ID, - ); - - if (bridgeHubXcmEntry) { - const [destination, messages] = bridgeHubXcmEntry; - const remoteXcm = messages[0]; - - console.log('✓ Found XCM message to Bridge Hub'); - - // Calculate delivery fees from Asset Hub to Bridge Hub - const deliveryFeesResult = - await assetHubApi.apis.XcmPaymentApi.query_delivery_fees( - destination, - remoteXcm, - ); - - if ( - deliveryFeesResult.success && - deliveryFeesResult.value.type === 'V5' && - deliveryFeesResult.value.value[0]?.fun?.type === 'Fungible' - ) { - deliveryFees = deliveryFeesResult.value.value[0].fun.value; - console.log('✓ Delivery fees:', deliveryFees.toString(), 'PAS units'); - } else { - console.log('✗ Failed to calculate delivery fees:', deliveryFeesResult); - } - ``` - -3. **Remote execution fees on Bridge Hub**: Connect to Bridge Hub, recompute the forwarded XCM weight there, and convert weight to PAS (`parents: 0, interior: Here`). Add the code to the function: - - ```typescript title="teleport-ah-to-bridge-hub.ts" - // 3. REMOTE EXECUTION FEES on Bridge Hub - console.log('\n3. Calculating remote execution fees on Bridge Hub'); - try { - const bridgeHubClient = createClient( - withPolkadotSdkCompat(getWsProvider(BRIDGE_HUB_RPC_ENDPOINT)), - ); - const bridgeHubApi = bridgeHubClient.getTypedApi(paseoBridgeHub); - const remoteWeightResult = - await bridgeHubApi.apis.XcmPaymentApi.query_xcm_weight(remoteXcm); - const remoteFeesResult = - await bridgeHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee( - remoteWeightResult.value as { - ref_time: bigint; - proof_size: bigint; - }, - XcmVersionedAssetId.V4({ - parents: 1, - interior: XcmV3Junctions.Here(), - }), - ); - bridgeHubClient.destroy(); - remoteExecutionFees = remoteFeesResult.value as bigint; - console.log( - '✓ Remote execution fees:', - remoteExecutionFees.toString(), - 'PAS units', - ); - } catch (error) { - console.error( - 'Error calculating remote execution fees on Bridge Hub:', - error, - ); - } - } else { - console.log('✗ No XCM message found to Bridge Hub'); - } - } else { - console.log('✗ Local dry run failed on Asset Hub:', dryRunResult.value); - } - ``` - -4. **Sum and return totals**: Aggregate all parts, print a short summary, and return a structured result. Add the code to the function: - - ```typescript title="teleport-ah-to-bridge-hub.ts" - // 4. TOTAL FEES - const totalFees = localExecutionFees + deliveryFees + remoteExecutionFees; - - console.log('\n=== Fee Summary (Asset Hub → Bridge Hub) ==='); - console.log( - 'Local execution fees:', - localExecutionFees.toString(), - 'PAS units', - ); - console.log('Delivery fees:', deliveryFees.toString(), 'PAS units'); - console.log( - 'Remote execution fees:', - remoteExecutionFees.toString(), - 'PAS units', - ); - console.log('TOTAL FEES:', totalFees.toString(), 'PAS units'); - console.log( - 'TOTAL FEES:', - (Number(totalFees) / Number(PAS_UNITS)).toFixed(4), - 'PAS', - ); - - return { - localExecutionFees, - deliveryFees, - remoteExecutionFees, - totalFees, - }; - } - ``` - -The full code for the fee estimation function is the following: - -??? code "Fee Estimation Function" - - ```typescript title="teleport-ah-to-bridge-hub.ts" - async function estimateXcmFeesFromAssetHubToBridgeHub( - xcm: any, - assetHubApi: any, - ) { - console.log('=== Fee Estimation Process (Asset Hub → Bridge Hub) ==='); - - // 1. LOCAL EXECUTION FEES on Asset Hub - console.log('1. Calculating local execution fees on Asset Hub...'); - let localExecutionFees = 0n; - - const weightResult = - await assetHubApi.apis.XcmPaymentApi.query_xcm_weight(xcm); - if (weightResult.success) { - console.log('✓ XCM weight (Asset Hub):', weightResult.value); - - // Convert weight to PAS fees from Asset Hub's perspective (parents:1, Here) - const executionFeesResult = - await assetHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee( - weightResult.value, - XcmVersionedAssetId.V4({ - parents: 1, - interior: XcmV3Junctions.Here(), - }), - ); - - if (executionFeesResult.success) { - localExecutionFees = executionFeesResult.value; - console.log( - '✓ Local execution fees (Asset Hub):', - localExecutionFees.toString(), - 'PAS units', - ); - } else { - console.log( - '✗ Failed to calculate local execution fees:', - executionFeesResult.value, - ); - } - } else { - console.log( - '✗ Failed to query XCM weight on Asset Hub:', - weightResult.value, - ); - } - - // 2. DELIVERY FEES + REMOTE EXECUTION FEES - console.log('\n2. Calculating delivery and remote execution fees...'); - let deliveryFees = 0n; - let remoteExecutionFees = 0n; // Skipped (Bridge Hub descriptor not available) - - // Origin from Asset Hub perspective - const origin = XcmVersionedLocation.V5({ - parents: 0, - interior: XcmV5Junctions.X1( - XcmV5Junction.AccountId32({ - id: FixedSizeBinary.fromAccountId32(ASSET_HUB_ACCOUNT), - network: undefined, - }), - ), - }); - - // Dry run the XCM locally on Asset Hub - const dryRunResult = await assetHubApi.apis.DryRunApi.dry_run_xcm( - origin, - xcm, - ); - - if ( - dryRunResult.success && - dryRunResult.value.execution_result.type === 'Complete' - ) { - console.log('✓ Local dry run on Asset Hub successful'); - - const { forwarded_xcms: forwardedXcms } = dryRunResult.value; - - // Find the XCM message sent to Bridge Hub (parents:1, interior: X1(Parachain(1002))) - const bridgeHubXcmEntry = forwardedXcms.find( - ([location, _]: [any, any]) => - (location.type === 'V4' || location.type === 'V5') && - location.value.parents === 1 && - location.value.interior?.type === 'X1' && - location.value.interior.value?.type === 'Parachain' && - location.value.interior.value.value === BRIDGE_HUB_PARA_ID, - ); - - if (bridgeHubXcmEntry) { - const [destination, messages] = bridgeHubXcmEntry; - const remoteXcm = messages[0]; - - console.log('✓ Found XCM message to Bridge Hub'); - - // Calculate delivery fees from Asset Hub to Bridge Hub - const deliveryFeesResult = - await assetHubApi.apis.XcmPaymentApi.query_delivery_fees( - destination, - remoteXcm, - ); - - if ( - deliveryFeesResult.success && - deliveryFeesResult.value.type === 'V5' && - deliveryFeesResult.value.value[0]?.fun?.type === 'Fungible' - ) { - deliveryFees = deliveryFeesResult.value.value[0].fun.value; - console.log('✓ Delivery fees:', deliveryFees.toString(), 'PAS units'); - } else { - console.log('✗ Failed to calculate delivery fees:', deliveryFeesResult); - } - - // 3. REMOTE EXECUTION FEES on Bridge Hub - console.log('\n3. Calculating remote execution fees on Bridge Hub'); - try { - const bridgeHubClient = createClient( - withPolkadotSdkCompat(getWsProvider(BRIDGE_HUB_RPC_ENDPOINT)), - ); - const bridgeHubApi = bridgeHubClient.getTypedApi(paseoBridgeHub); - const remoteWeightResult = - await bridgeHubApi.apis.XcmPaymentApi.query_xcm_weight(remoteXcm); - const remoteFeesResult = - await bridgeHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee( - remoteWeightResult.value as { - ref_time: bigint; - proof_size: bigint; - }, - XcmVersionedAssetId.V4({ - parents: 1, - interior: XcmV3Junctions.Here(), - }), - ); - bridgeHubClient.destroy(); - remoteExecutionFees = remoteFeesResult.value as bigint; - console.log( - '✓ Remote execution fees:', - remoteExecutionFees.toString(), - 'PAS units', - ); - } catch (error) { - console.error( - 'Error calculating remote execution fees on Bridge Hub:', - error, - ); - } - } else { - console.log('✗ No XCM message found to Bridge Hub'); - } - } else { - console.log('✗ Local dry run failed on Asset Hub:', dryRunResult.value); - } - - // 4. TOTAL FEES - const totalFees = localExecutionFees + deliveryFees + remoteExecutionFees; - - console.log('\n=== Fee Summary (Asset Hub → Bridge Hub) ==='); - console.log( - 'Local execution fees:', - localExecutionFees.toString(), - 'PAS units', - ); - console.log('Delivery fees:', deliveryFees.toString(), 'PAS units'); - console.log( - 'Remote execution fees:', - remoteExecutionFees.toString(), - 'PAS units', - ); - console.log('TOTAL FEES:', totalFees.toString(), 'PAS units'); - console.log( - 'TOTAL FEES:', - (Number(totalFees) / Number(PAS_UNITS)).toFixed(4), - 'PAS', - ); - - return { - localExecutionFees, - deliveryFees, - remoteExecutionFees, - totalFees, - }; - } - ``` - -## Complete Implementation - -Now put it all together in the main function: - -```typescript title="teleport-ah-to-bridge-hub.ts" -async function main() { - // Connect to the Asset Hub parachain - const assetHubClient = createClient( - withPolkadotSdkCompat(getWsProvider(PASEO_ASSET_HUB_RPC_ENDPOINT)), - ); - - // Get the typed API for Asset Hub - const assetHubApi = assetHubClient.getTypedApi(paseoAssetHub); - - try { - // Create the XCM message for teleport (Asset Hub → Bridge Hub) - const xcm = createTeleportXcmToBridgeHub(BRIDGE_HUB_PARA_ID); - - console.log('=== XCM Teleport: Paseo Asset Hub → Bridge Hub ==='); - console.log('From:', ASSET_HUB_ACCOUNT, '(Alice on Asset Hub)'); - console.log('To:', BRIDGE_HUB_BENEFICIARY, '(Beneficiary on Bridge Hub)'); - console.log('Amount:', '1 PAS'); - console.log(''); - - // Estimate all fees - const fees = await estimateXcmFeesFromAssetHubToBridgeHub(xcm, assetHubApi); - void fees; // prevent unused var under isolatedModules - - // Create the execute transaction on Asset Hub - const tx = assetHubApi.tx.PolkadotXcm.execute({ - message: xcm, - max_weight: { - ref_time: 6000000000n, - proof_size: 65536n, - }, - }); - - console.log('\n=== Transaction Details ==='); - console.log('Transaction hex:', (await tx.getEncodedData()).asHex()); - console.log('Ready to submit!'); - } catch (error) { - console.log('Error stack:', (error as Error).stack); - console.error('Error occurred:', (error as Error).message); - if ((error as Error).cause) { - console.dir((error as Error).cause, { depth: null }); - } - } finally { - // Ensure client is always destroyed - assetHubClient.destroy(); - } -} -``` - -## Full Code - -The full code for the complete implementation is the following: - -??? code "Teleport from Asset Hub to Bridge Hub" - - ```typescript title="teleport-ah-to-bridge-hub.ts" - import { paseoAssetHub, paseoBridgeHub } from '@polkadot-api/descriptors'; - import { createClient, FixedSizeBinary, Enum } from 'polkadot-api'; - import { getWsProvider } from 'polkadot-api/ws-provider/node'; - import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat'; - import { - XcmVersionedLocation, - XcmVersionedAssetId, - XcmV3Junctions, - XcmV3MultiassetFungibility, - XcmVersionedXcm, - XcmV5Instruction, - XcmV5Junctions, - XcmV5Junction, - XcmV5AssetFilter, - XcmV5WildAsset, - } from '@polkadot-api/descriptors'; - - // 1 PAS = 10^10 units - const PAS_UNITS = 10_000_000_000n; // 1 PAS - const PAS_CENTS = 100_000_000n; // 0.01 PAS - - // Paseo Asset Hub constants - const PASEO_ASSET_HUB_RPC_ENDPOINT = 'ws://localhost:8001'; - const ASSET_HUB_ACCOUNT = '15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5'; // Alice (Paseo Asset Hub) - - // Bridge Hub destination - const BRIDGE_HUB_RPC_ENDPOINT = 'ws://localhost:8000'; - const BRIDGE_HUB_PARA_ID = 1002; - const BRIDGE_HUB_BENEFICIARY = - '14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3'; // Bob (Bridge Hub) - - // Create the XCM message for teleport (Asset Hub → Bridge Hub) - function createTeleportXcmToBridgeHub(paraId: number) { - return XcmVersionedXcm.V5([ - // Withdraw PAS from Asset Hub (PAS on parachains is parents:1, interior: Here) - XcmV5Instruction.WithdrawAsset([ - { - id: { parents: 1, interior: XcmV5Junctions.Here() }, - fun: XcmV3MultiassetFungibility.Fungible(1n * PAS_UNITS), // 1 PAS - }, - ]), - // Pay local fees on Asset Hub in PAS - XcmV5Instruction.PayFees({ - asset: { - id: { parents: 1, interior: XcmV5Junctions.Here() }, - fun: XcmV3MultiassetFungibility.Fungible(10n * PAS_CENTS), // 0.01 PAS - }, - }), - // Send to Bridge Hub parachain (parents:1, interior: X1(Parachain(paraId))) - XcmV5Instruction.InitiateTransfer({ - destination: { - parents: 1, - interior: XcmV5Junctions.X1(XcmV5Junction.Parachain(paraId)), - }, - remote_fees: Enum( - 'Teleport', - XcmV5AssetFilter.Definite([ - { - id: { parents: 1, interior: XcmV5Junctions.Here() }, - fun: XcmV3MultiassetFungibility.Fungible(10n * PAS_CENTS), // 0.01 PAS - }, - ]), - ), - preserve_origin: false, - remote_xcm: [ - XcmV5Instruction.DepositAsset({ - assets: XcmV5AssetFilter.Wild(XcmV5WildAsset.AllCounted(1)), - beneficiary: { - parents: 0, - interior: XcmV5Junctions.X1( - XcmV5Junction.AccountId32({ - network: undefined, - id: FixedSizeBinary.fromAccountId32(BRIDGE_HUB_BENEFICIARY), - }), - ), - }, - }), - ], - assets: [ - Enum('Teleport', XcmV5AssetFilter.Wild(XcmV5WildAsset.AllCounted(1))), // Send everything. - ], - }), - ]); - } - - async function estimateXcmFeesFromAssetHubToBridgeHub( - xcm: any, - assetHubApi: any, - ) { - console.log('=== Fee Estimation Process (Asset Hub → Bridge Hub) ==='); - - // 1. LOCAL EXECUTION FEES on Asset Hub - console.log('1. Calculating local execution fees on Asset Hub...'); - let localExecutionFees = 0n; - - const weightResult = - await assetHubApi.apis.XcmPaymentApi.query_xcm_weight(xcm); - if (weightResult.success) { - console.log('✓ XCM weight (Asset Hub):', weightResult.value); - - // Convert weight to PAS fees from Asset Hub's perspective (parents:1, Here) - const executionFeesResult = - await assetHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee( - weightResult.value, - XcmVersionedAssetId.V4({ - parents: 1, - interior: XcmV3Junctions.Here(), - }), - ); - - if (executionFeesResult.success) { - localExecutionFees = executionFeesResult.value; - console.log( - '✓ Local execution fees (Asset Hub):', - localExecutionFees.toString(), - 'PAS units', - ); - } else { - console.log( - '✗ Failed to calculate local execution fees:', - executionFeesResult.value, - ); - } - } else { - console.log( - '✗ Failed to query XCM weight on Asset Hub:', - weightResult.value, - ); - } - - // 2. DELIVERY FEES + REMOTE EXECUTION FEES - console.log('\n2. Calculating delivery and remote execution fees...'); - let deliveryFees = 0n; - let remoteExecutionFees = 0n; // Skipped (Bridge Hub descriptor not available) - - // Origin from Asset Hub perspective - const origin = XcmVersionedLocation.V5({ - parents: 0, - interior: XcmV5Junctions.X1( - XcmV5Junction.AccountId32({ - id: FixedSizeBinary.fromAccountId32(ASSET_HUB_ACCOUNT), - network: undefined, - }), - ), - }); - - // Dry run the XCM locally on Asset Hub - const dryRunResult = await assetHubApi.apis.DryRunApi.dry_run_xcm( - origin, - xcm, - ); - - if ( - dryRunResult.success && - dryRunResult.value.execution_result.type === 'Complete' - ) { - console.log('✓ Local dry run on Asset Hub successful'); - - const { forwarded_xcms: forwardedXcms } = dryRunResult.value; - - // Find the XCM message sent to Bridge Hub (parents:1, interior: X1(Parachain(1002))) - const bridgeHubXcmEntry = forwardedXcms.find( - ([location, _]: [any, any]) => - (location.type === 'V4' || location.type === 'V5') && - location.value.parents === 1 && - location.value.interior?.type === 'X1' && - location.value.interior.value?.type === 'Parachain' && - location.value.interior.value.value === BRIDGE_HUB_PARA_ID, - ); - - if (bridgeHubXcmEntry) { - const [destination, messages] = bridgeHubXcmEntry; - const remoteXcm = messages[0]; - - console.log('✓ Found XCM message to Bridge Hub'); - - // Calculate delivery fees from Asset Hub to Bridge Hub - const deliveryFeesResult = - await assetHubApi.apis.XcmPaymentApi.query_delivery_fees( - destination, - remoteXcm, - ); - - if ( - deliveryFeesResult.success && - deliveryFeesResult.value.type === 'V5' && - deliveryFeesResult.value.value[0]?.fun?.type === 'Fungible' - ) { - deliveryFees = deliveryFeesResult.value.value[0].fun.value; - console.log('✓ Delivery fees:', deliveryFees.toString(), 'PAS units'); - } else { - console.log('✗ Failed to calculate delivery fees:', deliveryFeesResult); - } - - // 3. REMOTE EXECUTION FEES on Bridge Hub - console.log('\n3. Calculating remote execution fees on Bridge Hub'); - try { - const bridgeHubClient = createClient( - withPolkadotSdkCompat(getWsProvider(BRIDGE_HUB_RPC_ENDPOINT)), - ); - const bridgeHubApi = bridgeHubClient.getTypedApi(paseoBridgeHub); - const remoteWeightResult = - await bridgeHubApi.apis.XcmPaymentApi.query_xcm_weight(remoteXcm); - const remoteFeesResult = - await bridgeHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee( - remoteWeightResult.value as { - ref_time: bigint; - proof_size: bigint; - }, - XcmVersionedAssetId.V4({ - parents: 1, - interior: XcmV3Junctions.Here(), - }), - ); - bridgeHubClient.destroy(); - remoteExecutionFees = remoteFeesResult.value as bigint; - console.log( - '✓ Remote execution fees:', - remoteExecutionFees.toString(), - 'PAS units', - ); - } catch (error) { - console.error( - 'Error calculating remote execution fees on Bridge Hub:', - error, - ); - } - } else { - console.log('✗ No XCM message found to Bridge Hub'); - } - } else { - console.log('✗ Local dry run failed on Asset Hub:', dryRunResult.value); - } - - // 4. TOTAL FEES - const totalFees = localExecutionFees + deliveryFees + remoteExecutionFees; - - console.log('\n=== Fee Summary (Asset Hub → Bridge Hub) ==='); - console.log( - 'Local execution fees:', - localExecutionFees.toString(), - 'PAS units', - ); - console.log('Delivery fees:', deliveryFees.toString(), 'PAS units'); - console.log( - 'Remote execution fees:', - remoteExecutionFees.toString(), - 'PAS units', - ); - console.log('TOTAL FEES:', totalFees.toString(), 'PAS units'); - console.log( - 'TOTAL FEES:', - (Number(totalFees) / Number(PAS_UNITS)).toFixed(4), - 'PAS', - ); - - return { - localExecutionFees, - deliveryFees, - remoteExecutionFees, - totalFees, - }; - } - - async function main() { - // Connect to the Asset Hub parachain - const assetHubClient = createClient( - withPolkadotSdkCompat(getWsProvider(PASEO_ASSET_HUB_RPC_ENDPOINT)), - ); - - // Get the typed API for Asset Hub - const assetHubApi = assetHubClient.getTypedApi(paseoAssetHub); - - try { - // Create the XCM message for teleport (Asset Hub → Bridge Hub) - const xcm = createTeleportXcmToBridgeHub(BRIDGE_HUB_PARA_ID); - - console.log('=== XCM Teleport: Paseo Asset Hub → Bridge Hub ==='); - console.log('From:', ASSET_HUB_ACCOUNT, '(Alice on Asset Hub)'); - console.log('To:', BRIDGE_HUB_BENEFICIARY, '(Beneficiary on Bridge Hub)'); - console.log('Amount:', '1 PAS'); - console.log(''); - - // Estimate all fees - const fees = await estimateXcmFeesFromAssetHubToBridgeHub(xcm, assetHubApi); - void fees; // prevent unused var under isolatedModules - - // Create the execute transaction on Asset Hub - const tx = assetHubApi.tx.PolkadotXcm.execute({ - message: xcm, - max_weight: { - ref_time: 6000000000n, - proof_size: 65536n, - }, - }); - - console.log('\n=== Transaction Details ==='); - console.log('Transaction hex:', (await tx.getEncodedData()).asHex()); - console.log('Ready to submit!'); - } catch (error) { - console.log('Error stack:', (error as Error).stack); - console.error('Error occurred:', (error as Error).message); - if ((error as Error).cause) { - console.dir((error as Error).cause, { depth: null }); - } - } finally { - // Ensure client is always destroyed - assetHubClient.destroy(); - } - } - - main().catch(console.error); - - ``` - -## Running the Script - -Before running the script, you can use chopsticks to fork the Paseo Asset Hub and Paseo Bridge Hub chains locally. To do so, you can use the following files and commands: - -1. Create a new directory called `.chopsticks` and add the files: - - ??? code "paseo-bridge-hub.yml" - - {% raw %} - ```yaml title=".chopsticks/paseo-bridge-hub.yml" - endpoint: wss://bridge-hub-paseo.dotters.network - mock-signature-host: true - block: ${env.PASEO_BRIDGE_HUB_BLOCK_NUMBER} - db: ./db.sqlite - - import-storage: - Sudo: - Key: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY # Alice - System: - Account: - - - - - - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY - - providers: 1 - data: - free: '10000000000000000000' - ``` - {% endraw %} - - ??? code "paseo-asset-hub.yml" - - {% raw %} - ```yaml title=".chopsticks/paseo-asset-hub.yml" - endpoint: wss://asset-hub-paseo-rpc.n.dwellir.com - mock-signature-host: true - block: ${env.PASEO_ASSET_HUB_BLOCK_NUMBER} - db: ./db.sqlite - - import-storage: - Sudo: - Key: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY # Alice - System: - Account: - - - - - - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY - - providers: 1 - data: - free: '10000000000000000000' - ``` - {% endraw %} - -2. Run the following command to fork the Paseo Bridge Hub chain: - - ```bash - chopsticks --config=.chopsticks/paseo-bridge-hub.yml - ``` - - After running the command, you will see the following output: - -
    - chopsticks --config=.chopsticks/paseo-bridge-hub.yml - [15:55:22.770] INFO: Paseo Bridge Hub RPC listening on http://[::]:8000 and ws://[::]:8000 - app: "chopsticks" -
    - -3. Run the following command to fork the Paseo Asset Hub chain: - - ```bash - chopsticks --config=.chopsticks/paseo-asset-hub.yml - ``` - - After running the commands, you will see the following output: - -
    - chopsticks --config=.chopsticks/paseo-asset-hub.yml - [15:55:22.770] INFO: Paseo Asset Hub Testnet RPC listening on http://[::]:8001 and ws://[::]:8001 - app: "chopsticks" -
    - -4. Run the script: - - ```bash - npx ts-node teleport-ah-to-bridge-hub.ts - ``` - -After running the script, you will see the following output: - -
    - npx ts-node teleport-ah-to-bridge-hub.ts -
    -=== XCM Teleport: Paseo Asset Hub → Bridge Hub ===
    -From: 15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5 (Alice on Asset Hub)
    -To: 14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3 (Beneficiary on Bridge Hub)
    -Amount: 1 PAS
    -
    -=== Fee Estimation Process (Asset Hub → Bridge Hub) ===
    -1. Calculating local execution fees on Asset Hub...
    -✓ XCM weight (Asset Hub): { ref_time: 1462082000n, proof_size: 19578n }
    -✓ Local execution fees (Asset Hub): 97890000 PAS units
    -
    -2. Calculating delivery and remote execution fees...
    -✓ Local dry run on Asset Hub successful
    -✓ Found XCM message to Bridge Hub
    -✓ Delivery fees: 305150000 PAS units
    -
    -3. Calculating remote execution fees on Bridge Hub
    -✓ Remote execution fees: 17965000 PAS units
    -
    -=== Fee Summary (Asset Hub → Bridge Hub) ===
    -Local execution fees: 97890000 PAS units
    -Delivery fees: 305150000 PAS units
    -Remote execution fees: 17965000 PAS units
    -TOTAL FEES: 421005000 PAS units
    -TOTAL FEES: 0.0421 PAS
    -
    -=== Transaction Details ===
    -Transaction hex: 0x1f03050c00040100000700e40b54023001000002286bee31010100a90f0100000401000002286bee000400010204040d010204000101008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480700bca0650102000400
    -Ready to submit!
    -
    -
    -
    - -## Conclusion - -This approach provides accurate fee estimation for XCM teleports from Asset Hub to Bridge Hub Chain by properly simulating execution on both chains and utilizing dedicated runtime APIs for fee calculation. The fee breakdown helps you understand the cost structure of reverse cross-chain operations (parachain → bridge hub chain) and ensures your transactions have sufficient funds to complete successfully. - -The key insight is understanding how asset references change based on the perspective of each chain in the XCM ecosystem, which is crucial for proper fee estimation and XCM construction. diff --git a/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-out-of-polkadot.md b/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-out-of-polkadot.md deleted file mode 100644 index 8ac3036a2..000000000 --- a/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-out-of-polkadot.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/chain-interactions/send-transactions/interoperability/transfer-assets-out-of-polkadot/ ---- - -TODO diff --git a/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-parachains.md b/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-parachains.md deleted file mode 100644 index 8b85b616f..000000000 --- a/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-parachains.md +++ /dev/null @@ -1,882 +0,0 @@ ---- -title: Transfer Assets Between Parachains -description: A step-by-step guide to using the ParaSpell XCM SDK to build, verify, and execute a transfer from one Parachain to another. -url: https://docs.polkadot.com/chain-interactions/send-transactions/interoperability/transfer-assets-parachains/ ---- - -# Transfer Assets Between Parachains - -## Introduction - -This guide walks you through transferring tokens between two parachains using the [ParaSpell XCM SDK](/reference/tools/paraspell/){target=\_blank}. This example utilizes [Asset Hub](/polkadot-protocol/architecture/system-chains/asset-hub/){target=\_blank} and the [People Chain](/polkadot-protocol/architecture/system-chains/people/){target=\_blank}. However, the same approach can be applied to transfers between other parachains. - -For development purposes, this guide will use the [Polkadot TestNet](/develop/networks/#paseo){target=\_blank}, so the transferred token will be PAS. - -In this guide, you will: - -- Build an XCM transfer transaction using ParaSpell XCM SDK. -- Perform a dry run to validate the transfer. -- Verify the [Existential Deposit (ED)](/reference/glossary/#existential-deposit){target=\_blank} requirement on the destination chain. -- Retrieve information regarding the transfer, along with fee estimates. -- Submit the transaction. - -### Prerequisites - -Before you begin, ensure you have the following: - -- Knowledge of the [fundamentals of Polkadot](/parachains/get-started/){target=\_blank}. -- Basic understanding of [XCM](/parachains/interoperability/get-started/){target=\_blank}. -- Basic familiarity with JavaScript or TypeScript. -- Installed [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\_blank}, a JavaScript and TypeScript package manager. - -## Initialize Your Project - -Create the project folder: - -```bash -mkdir paraspell-transfer && \ -cd paraspell-transfer -``` - -Initialize the JavaScript project: - -```bash -npm init -y -``` - -Install dev dependencies: - -```bash -npm install --save-dev @types/node@^22.12.0 tsx@^4.20.6 typescript@^5.7.3 -``` - -Install the required dependencies: - -```bash -npm install --save @paraspell/sdk@11.12.6 polkadot-api@1.20.0 @polkadot-labs/hdkd-helpers@0.0.26 @polkadot-labs/hdkd@0.0.25 -``` - -Now add the following setup code to `index.ts`: - -```ts title="index.ts" -import { Builder, hasDryRunSupport } from '@paraspell/sdk'; -import { - entropyToMiniSecret, - mnemonicToEntropy, - ss58Address, -} from '@polkadot-labs/hdkd-helpers'; -import { getPolkadotSigner } from 'polkadot-api/signer'; -import { sr25519CreateDerive } from '@polkadot-labs/hdkd'; -import { inspect } from 'util'; - -// PAS token has 10 decimals -const PAS_UNITS = 10_000_000_000n; - -const SEED_PHRASE = - 'INSERT_YOUR_SEED_PHRASE'; - -// Create Sr25519 signer from mnemonic -function getSigner() { - const entropy = mnemonicToEntropy(SEED_PHRASE); - const miniSecret = entropyToMiniSecret(entropy); - const derive = sr25519CreateDerive(miniSecret); - const keyPair = derive(''); - return getPolkadotSigner(keyPair.publicKey, 'Sr25519', keyPair.sign); -} - -const RECIPIENT_ADDRESS = ss58Address(getSigner().publicKey); -const SENDER_ADDRESS = ss58Address(getSigner().publicKey); -``` - -Replace the `INSERT_YOUR_SEED_PHRASE` with the seed phrase from your Polkadot development account. - -Be sure to fund this account with some PAS tokens on the Paseo Asset Hub using the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1000){target=_blank}. - -!!!warning "Security Warning" - Never commit your mnemonic phrase to production code. Use environment variables or secure key management systems. - -## Build a Token Transfer Transaction - -The next step is to build the transaction that you intend to execute. - -In this example, you will transfer 10 PAS tokens from Paseo's Asset Hub to Paseo's People Chain system parachain. - -Add the ParaSpell transaction code to your `index.ts` file: - -```ts title="index.ts" -async function transfer() { - const signer = getSigner(); - - const tx = await Builder() - .from('AssetHubPaseo') - .to('PeoplePaseo') - .currency({ - symbol: 'PAS', - amount: 10n * PAS_UNITS, // 10 PAS - }) - .address(RECIPIENT_ADDRESS) - .build(); - - console.log('Built transaction:', inspect(tx, { colors: true, depth: null })); - - const result = await tx.signAndSubmit(signer); - console.log(inspect(result, { colors: true, depth: null })); - process.exit(0); -} -``` - -Do not execute it just yet. You will perform a dry run of this transaction first to ensure it works as expected. - -## Perform a Dry Run - -Dry runs simulate the transaction without broadcasting it, allowing you to confirm success in advance. - -Add the following dry run code to your `index.ts` script: - -```ts title="index.ts" -async function dryRunTransfer() { - if (!hasDryRunSupport('AssetHubPaseo')) { - console.log('Dry run is not supported on AssetHubPaseo.'); - return; - } - - const tx = await Builder() - .from('AssetHubPaseo') - .to('PeoplePaseo') - .currency({ - symbol: 'PAS', - amount: 10n * PAS_UNITS, - }) - .address(RECIPIENT_ADDRESS) - .senderAddress(SENDER_ADDRESS) - .dryRun(); - - console.log(inspect(tx, { colors: true, depth: null })); - process.exit(0); -} - -dryRunTransfer(); -``` -Run the script using the following command: - -```bash -npx tsx index.ts -``` - -The result of the dry run will look similar to the following example output: - -
    - npx tsx index.ts - { - failureReason: undefined, - failureChain: undefined, - origin: { - success: true, - fee: 17965000n, - currency: 'PAS', - asset: { - symbol: 'PAS', - isNative: true, - decimals: 10, - existentialDeposit: '100000000', - location: { parents: 1, interior: { Here: null } }, - isFeeAsset: true, - amount: 100000000000n - }, - weight: undefined, - forwardedXcms: [ - { - type: 'V3', - value: { - parents: 1, - interior: { type: 'X1', value: { type: 'Parachain', value: 1004 } } - } - }, - [ - { - type: 'V3', - value: [ - { - type: 'ReceiveTeleportedAsset', - value: [ - { - id: { - type: 'Concrete', - value: { - parents: 1, - interior: { type: 'Here', value: undefined } - } - }, - fun: { type: 'Fungible', value: 100000000000n } - } - ] - }, - { type: 'ClearOrigin', value: undefined }, - { - type: 'BuyExecution', - value: { - fees: { - id: { - type: 'Concrete', - value: { - parents: 1, - interior: { type: 'Here', value: undefined } - } - }, - fun: { type: 'Fungible', value: 100000000000n } - }, - weight_limit: { type: 'Unlimited', value: undefined } - } - }, - { - type: 'DepositAsset', - value: { - assets: { - type: 'Wild', - value: { type: 'AllCounted', value: 1 } - }, - beneficiary: { - parents: 0, - interior: { - type: 'X1', - value: { - type: 'AccountId32', - value: { - network: undefined, - id: FixedSizeBinary { - asText: [Function (anonymous)], - asHex: [Function (anonymous)], - asOpaqueHex: [Function (anonymous)], - asBytes: [Function (anonymous)], - asOpaqueBytes: [Function (anonymous)] - } - } - } - } - } - } - }, - { - type: 'SetTopic', - value: FixedSizeBinary { - asText: [Function (anonymous)], - asHex: [Function (anonymous)], - asOpaqueHex: [Function (anonymous)], - asBytes: [Function (anonymous)], - asOpaqueBytes: [Function (anonymous)] - } - } - ] - } - ] - ], - destParaId: 1004 - }, - assetHub: undefined, - bridgeHub: undefined, - destination: { - success: true, - fee: 817598n, - currency: 'PAS', - asset: { - symbol: 'PAS', - isNative: true, - decimals: 10, - existentialDeposit: '1000000000', - location: { parents: 1, interior: { Here: null } }, - isFeeAsset: true - }, - weight: { refTime: 176858000n, proofSize: 0n }, - forwardedXcms: [], - destParaId: undefined - }, - hops: [] -} -
    -## Verify the Existential Deposit - -Check if the recipient account meets the [Existential Deposit (ED)](/polkadot-protocol/glossary/#existential-deposit){target=\_blank} requirement before sending by using [`verifyEdOnDestination`](https://paraspell.github.io/docs/sdk/xcmUtils.html#verify-ed-on-destination){target=\_blank}: - -```ts title="index.ts" -async function verifyED() { - const isValid = await Builder() - .from('AssetHubPaseo') - .to('PeoplePaseo') - .currency({ - symbol: 'PAS', - amount: 10n * PAS_UNITS, - }) - .address(RECIPIENT_ADDRESS) - .senderAddress(SENDER_ADDRESS) - .verifyEdOnDestination(); - - console.log(`ED verification ${isValid ? 'successful' : 'failed'}.`); - process.exit(0); -} - -verifyED(); -``` -Comment out the `dryRunTransfer()` function so that it is not executed again. Then, execute the `verifyED()` by running the following command: - -```bash -npx tsx index.ts -``` - -After that, you will get output confirming the ED which will look similar to the following: - -
    - npx tsx index.ts - ED verification successful. -
    -## Get Transfer Info and Fee Estimates - -Before sending an XCM transaction, it is helpful to estimate the fees associated with executing and delivering the cross-chain message. - -ParaSpell has a helpful function for this: [`getTransferInfo()`](https://paraspell.github.io/docs/sdk/xcmUtils.html#xcm-transfer-info){target=\_blank}. This function returns an estimate of the associated XCM fees, along with the account's balance before and after the fees are paid. - -```ts title="index.ts" -async function XcmTransferInfo() { - const info = await Builder() - .from('AssetHubPaseo') - .to('PeoplePaseo') - .currency({ - symbol: 'PAS', - amount: 10n * PAS_UNITS, - }) - .address(RECIPIENT_ADDRESS) - .senderAddress(SENDER_ADDRESS) - .getTransferInfo(); - - console.log('Transfer Info:', info); - process.exit(0); -} - -XcmTransferInfo(); -``` - -Comment out the `verifyED()` function so it doesn't execute again. Then, execute the `XcmTransferInfo()` function by running the following command: - -```bash -npx tsx index.ts -``` - -You will see all the information for your transfer similar to the following example: - -
    - npx tsx index.ts - Transfer Info: { - chain: { - origin: "AssetHubPaseo", - destination: "PeoplePaseo", - ecosystem: "PAS", - }, - origin: { - selectedCurrency: { - sufficient: true, - balance: 9799197260420n, - balanceAfter: 9699197260420n, - currencySymbol: "PAS", - asset: [Object ...], - existentialDeposit: 100000000n, - }, - xcmFee: { - sufficient: true, - fee: 17965000n, - balance: 9799197260420n, - balanceAfter: 9799179295420n, - currencySymbol: "PAS", - asset: [Object ...], - }, - }, - assetHub: undefined, - bridgeHub: undefined, - hops: [], - destination: { - receivedCurrency: { - sufficient: true, - receivedAmount: 99999182402n, - balance: 199998364804n, - balanceAfter: 299997547206n, - currencySymbol: "PAS", - asset: [Object ...], - existentialDeposit: 1000000000n, - }, - xcmFee: { - fee: 817598n, - balance: 199998364804n, - balanceAfter: 299997547206n, - currencySymbol: "PAS", - asset: [Object ...], - }, - }, -} -
    -Now that you have: - -- Completed a successful dry run of the transaction. -- Verified the existential deposit on the recipient account. -- Obtained an estimate of the associated XCM fees. - -You can execute the transfer function by adding the following function call: - -```typescript title="index.ts" -transfer(); -``` - -Comment out the `XcmTransferInfo()` function so it doesn't execute again. Then, execute the transfer by running the following command: - -```bash -npx tsx index.ts -``` - -Your `transfer` function will submit the transaction, and you will get the following output: - -
    - npx tsx index.ts - ... - Built transaction: { - getPaymentInfo: [AsyncFunction: getPaymentInfo], - getEstimatedFees: [AsyncFunction: getEstimatedFees], - decodedCall: { - type: 'PolkadotXcm', - value: { - type: 'limited_teleport_assets', - value: { - dest: { - type: 'V5', - value: { - parents: 1, - interior: { type: 'X1', value: { type: 'Parachain', value: 1004 } } - } - }, - beneficiary: { - type: 'V5', - value: { - parents: 0, - interior: { - type: 'X1', - value: { - type: 'AccountId32', - value: { - network: undefined, - id: FixedSizeBinary { - asText: [Function (anonymous)], - asHex: [Function (anonymous)], - asOpaqueHex: [Function (anonymous)], - asBytes: [Function (anonymous)], - asOpaqueBytes: [Function (anonymous)] - } - } - } - } - } - }, - assets: { - type: 'V5', - value: [ - { - id: { parents: 1, interior: { type: 'Here', value: null } }, - fun: { type: 'Fungible', value: 100000000000n } - } - ] - }, - fee_asset_item: 0, - weight_limit: { type: 'Unlimited' } - } - } - }, - getEncodedData: [Function: getEncodedData], - sign: [Function: sign], - signSubmitAndWatch: [Function: signSubmitAndWatch], - signAndSubmit: [Function: signAndSubmit] -} -
    -Once the transaction is successfully included in a block, you will see the recipient's account balance updated, and you will receive output similar to the following. - -???- code "Successful Transaction Submission" - This output will be returned once the transaction has been successfully included in a block. - -
    - ... - { - txHash: '0x6fbecc0b284adcff46ab39872659c2567395c865adef5f8cbea72f25b6042609', - block: { - index: 2, - number: 2524809, - hash: '0xa39a96d5921402c6e8f67e48b8395d6b21382c72d4d30f8497a0e9f890bc0d4c' - }, - ok: true, - events: [ - { - type: 'Balances', - value: { - type: 'Withdraw', - value: { - who: '15DMtB5BDCJqw4uZtByTWXGqViAVx7XjRsxWbTH5tfrHLe8j', - amount: 15668864n - } - }, - topics: [] - }, - { - type: 'Balances', - value: { - type: 'Burned', - value: { - who: '15DMtB5BDCJqw4uZtByTWXGqViAVx7XjRsxWbTH5tfrHLe8j', - amount: 100000000000n - } - }, - topics: [] - }, - { - type: 'PolkadotXcm', - value: { - type: 'Attempted', - value: { - outcome: { - type: 'Complete', - value: { used: { ref_time: 190990000n, proof_size: 3593n } } - } - } - }, - topics: [] - }, - { - type: 'Balances', - value: { - type: 'Burned', - value: { - who: '15DMtB5BDCJqw4uZtByTWXGqViAVx7XjRsxWbTH5tfrHLe8j', - amount: 304850000n - } - }, - topics: [] - }, - { - type: 'Balances', - value: { - type: 'Minted', - value: { - who: '14xmwinmCEz6oRrFdczHKqHgWNMiCysE2KrA4jXXAAM1Eogk', - amount: 304850000n - } - }, - topics: [] - }, - { - type: 'PolkadotXcm', - value: { - type: 'FeesPaid', - value: { - paying: { - parents: 0, - interior: { - type: 'X1', - value: { - type: 'AccountId32', - value: { - network: { type: 'Polkadot', value: undefined }, - id: FixedSizeBinary { - asText: [Function (anonymous)], - asHex: [Function (anonymous)], - asOpaqueHex: [Function (anonymous)], - asBytes: [Function (anonymous)], - asOpaqueBytes: [Function (anonymous)] - } - } - } - } - }, - fees: [ - { - id: { - parents: 1, - interior: { type: 'Here', value: undefined } - }, - fun: { type: 'Fungible', value: 304850000n } - } - ] - } - }, - topics: [] - }, - { - type: 'XcmpQueue', - value: { - type: 'XcmpMessageSent', - value: { - message_hash: FixedSizeBinary { - asText: [Function (anonymous)], - asHex: [Function (anonymous)], - asOpaqueHex: [Function (anonymous)], - asBytes: [Function (anonymous)], - asOpaqueBytes: [Function (anonymous)] - } - } - }, - topics: [] - }, - { - type: 'PolkadotXcm', - value: { - type: 'Sent', - value: { - origin: { - parents: 0, - interior: { - type: 'X1', - value: { - type: 'AccountId32', - value: { - network: { type: 'Polkadot', value: undefined }, - id: FixedSizeBinary { - asText: [Function (anonymous)], - asHex: [Function (anonymous)], - asOpaqueHex: [Function (anonymous)], - asBytes: [Function (anonymous)], - asOpaqueBytes: [Function (anonymous)] - } - } - } - } - }, - destination: { - parents: 1, - interior: { type: 'X1', value: { type: 'Parachain', value: 1002 } } - }, - message: [ - { - type: 'ReceiveTeleportedAsset', - value: [ - { - id: { - parents: 1, - interior: { type: 'Here', value: undefined } - }, - fun: { type: 'Fungible', value: 100000000000n } - } - ] - }, - { type: 'ClearOrigin', value: undefined }, - { - type: 'BuyExecution', - value: { - fees: { - id: { - parents: 1, - interior: { type: 'Here', value: undefined } - }, - fun: { type: 'Fungible', value: 100000000000n } - }, - weight_limit: { type: 'Unlimited', value: undefined } - } - }, - { - type: 'DepositAsset', - value: { - assets: { - type: 'Wild', - value: { type: 'AllCounted', value: 1 } - }, - beneficiary: { - parents: 0, - interior: { - type: 'X1', - value: { - type: 'AccountId32', - value: { - network: undefined, - id: FixedSizeBinary { - asText: [Function (anonymous)], - asHex: [Function (anonymous)], - asOpaqueHex: [Function (anonymous)], - asBytes: [Function (anonymous)], - asOpaqueBytes: [Function (anonymous)] - } - } - } - } - } - } - } - ], - message_id: FixedSizeBinary { - asText: [Function (anonymous)], - asHex: [Function (anonymous)], - asOpaqueHex: [Function (anonymous)], - asBytes: [Function (anonymous)], - asOpaqueBytes: [Function (anonymous)] - } - } - }, - topics: [] - }, - { - type: 'Balances', - value: { - type: 'Deposit', - value: { - who: '13UVJyLgBASGhE2ok3TvxUfaQBGUt88JCcdYjHvUhvQkFTTx', - amount: 15668864n - } - }, - topics: [] - }, - { - type: 'TransactionPayment', - value: { - type: 'TransactionFeePaid', - value: { - who: '15DMtB5BDCJqw4uZtByTWXGqViAVx7XjRsxWbTH5tfrHLe8j', - actual_fee: 15668864n, - tip: 0n - } - }, - topics: [] - }, - { - type: 'System', - value: { - type: 'ExtrinsicSuccess', - value: { - dispatch_info: { - weight: { ref_time: 952851000n, proof_size: 13382n }, - class: { type: 'Normal', value: undefined }, - pays_fee: { type: 'Yes', value: undefined } - } - } - }, - topics: [] - } - ] - } -
    -After executing the transfer, check the account balance on [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.turboflakes.io%2Fasset-hub-paseo){target=\_blank} for [Paseo's Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.turboflakes.io%2Fasset-hub-paseo#/accounts){target=\_blank} and [Paseo's People Chain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.ibp.network%2Fpeople-paseo#/accounts){target=\_blank}. - -You should see: - -- The recipient account now has 10 more PAS tokens. -- The sender account has the transfer amount (10 PAS) + the fees amount debited from their account balance. - -You have now successfully created and sent a cross-chain transfer using the ParaSpell XCM SDK! - -???- code "Full Code" - - ```typescript title="index.ts" - import { Builder, hasDryRunSupport } from '@paraspell/sdk'; - import { - entropyToMiniSecret, - mnemonicToEntropy, - ss58Address, - } from '@polkadot-labs/hdkd-helpers'; - import { getPolkadotSigner } from 'polkadot-api/signer'; - import { sr25519CreateDerive } from '@polkadot-labs/hdkd'; - import { inspect } from 'util'; - - // PAS token has 10 decimals - const PAS_UNITS = 10_000_000_000n; - - const SEED_PHRASE = - 'INSERT_YOUR_SEED_PHRASE'; - - // Create Sr25519 signer from mnemonic - function getSigner() { - const entropy = mnemonicToEntropy(SEED_PHRASE); - const miniSecret = entropyToMiniSecret(entropy); - const derive = sr25519CreateDerive(miniSecret); - const keyPair = derive(''); - return getPolkadotSigner(keyPair.publicKey, 'Sr25519', keyPair.sign); - } - - const RECIPIENT_ADDRESS = ss58Address(getSigner().publicKey); - const SENDER_ADDRESS = ss58Address(getSigner().publicKey); - - async function transfer() { - const signer = getSigner(); - - const tx = await Builder() - .from('AssetHubPaseo') - .to('PeoplePaseo') - .currency({ - symbol: 'PAS', - amount: 10n * PAS_UNITS, // 10 PAS - }) - .address(RECIPIENT_ADDRESS) - .build(); - - console.log('Built transaction:', inspect(tx, { colors: true, depth: null })); - - const result = await tx.signAndSubmit(signer); - console.log(inspect(result, { colors: true, depth: null })); - process.exit(0); - } - - async function dryRunTransfer() { - if (!hasDryRunSupport('AssetHubPaseo')) { - console.log('Dry run is not supported on AssetHubPaseo.'); - return; - } - - const tx = await Builder() - .from('AssetHubPaseo') - .to('PeoplePaseo') - .currency({ - symbol: 'PAS', - amount: 10n * PAS_UNITS, - }) - .address(RECIPIENT_ADDRESS) - .senderAddress(SENDER_ADDRESS) - .dryRun(); - - console.log(inspect(tx, { colors: true, depth: null })); - process.exit(0); - } - - dryRunTransfer(); - - async function verifyED() { - const isValid = await Builder() - .from('AssetHubPaseo') - .to('PeoplePaseo') - .currency({ - symbol: 'PAS', - amount: 10n * PAS_UNITS, - }) - .address(RECIPIENT_ADDRESS) - .senderAddress(SENDER_ADDRESS) - .verifyEdOnDestination(); - - console.log(`ED verification ${isValid ? 'successful' : 'failed'}.`); - process.exit(0); - } - - verifyED(); - - async function XcmTransferInfo() { - const info = await Builder() - .from('AssetHubPaseo') - .to('PeoplePaseo') - .currency({ - symbol: 'PAS', - amount: 10n * PAS_UNITS, - }) - .address(RECIPIENT_ADDRESS) - .senderAddress(SENDER_ADDRESS) - .getTransferInfo(); - - console.log('Transfer Info:', info); - process.exit(0); - } - - XcmTransferInfo(); - - transfer(); - - ``` - -## Next Steps - -- Read the Docs: Dive deeper into the features of the [ParaSpell XCM SDK](https://paraspell.github.io/docs/sdk/getting-started.html){target=\_blank} documentation. - -- Learn about XCM: Understand the underlying protocol by visiting the [Introduction to XCM page](/parachains/interoperability/get-started/) in the Polkadot Docs. diff --git a/.ai/pages/chain-interactions-send-transactions-pay-fees-with-different-tokens.md b/.ai/pages/chain-interactions-send-transactions-pay-fees-with-different-tokens.md deleted file mode 100644 index c27802cd6..000000000 --- a/.ai/pages/chain-interactions-send-transactions-pay-fees-with-different-tokens.md +++ /dev/null @@ -1,308 +0,0 @@ ---- -title: Send a Transaction While Paying the Fee with a Different Token -description: This tutorial demonstrates how to send a DOT transfer transaction while paying the fees using a different token on the Asset Hub. -url: https://docs.polkadot.com/chain-interactions/send-transactions/pay-fees-with-different-tokens/ ---- - -# Send a Transaction While Paying the Fee with a Different Token - -## Introduction - -The Asset Hub provides a powerful feature that allows users to pay transaction fees using alternative tokens instead of the native token of the chain. - -This tutorial demonstrates how to send a DOT transfer transaction while paying the fees using a different token (USDT in this example) on the Asset Hub. - -## Environment Setup - -Let's set up the development environment for this tutorial: - -1. Create a new directory and initialize the project: - - ```bash - mkdir fee-payment-tutorial && \ - cd fee-payment-tutorial - ``` - -2. Initialize the project: - - ```bash - npm init -y - ``` - -3. Install dev dependencies: - - ```bash - npm install --save-dev @types/node@^22.12.0 ts-node@^10.9.2 typescript@^5.7.3 - ``` - -4. Install dependencies: - - ```bash - npm install --save @polkadot-labs/hdkd@^0.0.13 @polkadot-labs/hdkd-helpers@^0.0.13 polkadot-api@1.9.5 - ``` - -5. Create TypeScript configuration: - - ```bash - npx tsc --init && npm pkg set type=module - ``` - - The command `npm pkg set type=module` is used to set the type of the project to module. This is necessary to use the `import` statement in the TypeScript code. - -6. Generate Polkadot API types for Asset Hub: - - ```bash - npx papi add assetHub -n polkadot_asset_hub - ``` - -7. Create a new file called `fee-payment-transaction.ts`: - - ```bash - touch fee-payment-transaction.ts - ``` - -## Local Asset Hub Setup - -Before running the script, you'll need to fork the Asset Hub locally using Chopsticks: - -```bash -chopsticks -c polkadot-asset-hub -``` - -This command forks the Asset Hub chain, making it available at `ws://localhost:8000`. By running `polkadot-asset-hub`, you're using the Asset Hub fork with the configuration specified in the [`polkadot-asset-hub.yml`](https://github.com/AcalaNetwork/chopsticks/blob/master/configs/polkadot-asset-hub.yml){target=_blank} file. This configuration defines Alice's account with USDT assets. If you want to use a different chain, ensure the account you're using has the necessary assets. - -## Implementation - -In the following sections, you'll set up imports and constants, create a transaction signer, and connect to the Polkadot Asset Hub chain. Then, you'll create and send a DOT transfer transaction, requesting that fees be paid in USDT instead of DOT. - -### Import Dependencies - -Add the following imports to your `fee-payment-transaction.ts` file: - -```typescript title="fee-payment-transaction.ts" -import { sr25519CreateDerive } from "@polkadot-labs/hdkd"; -import { - DEV_PHRASE, - entropyToMiniSecret, - mnemonicToEntropy, -} from "@polkadot-labs/hdkd-helpers"; -import { getPolkadotSigner } from "polkadot-api/signer"; -import { createClient } from "polkadot-api"; -import { assetHub } from "@polkadot-api/descriptors"; -import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat"; -import { getWsProvider } from "polkadot-api/ws-provider/node"; -import { MultiAddress } from "@polkadot-api/descriptors"; -``` - -### Define Constants - -Define the constants for your transaction: - -```typescript title="fee-payment-transaction.ts" -const TARGET_ADDRESS = "14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3"; // Bob's address -const TRANSFER_AMOUNT = 3_000_000_000n; // 3 DOT -const USD_ASSET_ID = 1337; -``` - -### Create a Signer - -Create a signer using Alice's development account: - -```typescript title="fee-payment-transaction.ts" -const createSigner = async () => { - const entropy = mnemonicToEntropy(DEV_PHRASE); - const miniSecret = entropyToMiniSecret(entropy); - const derive = sr25519CreateDerive(miniSecret); - const hdkdKeyPair = derive("//Alice"); - const polkadotSigner = getPolkadotSigner( - hdkdKeyPair.publicKey, - "Sr25519", - hdkdKeyPair.sign - ); - return polkadotSigner; -}; -``` - -This function will return a signer that can be used to sign the transaction. - -### Setup the Client and API - -Create the client connection to the local Asset Hub: - -```typescript title="fee-payment-transaction.ts" -const client = createClient( - withPolkadotSdkCompat( - getWsProvider("ws://localhost:8000") // Chopsticks Asset Hub - ) -); - -const api = client.getTypedApi(assetHub); -``` - -### Create the Transaction - -Create a standard DOT transfer transaction: - -```typescript title="fee-payment-transaction.ts" -const tx = api.tx.Balances.transfer_keep_alive({ - dest: MultiAddress.Id(TARGET_ADDRESS), - value: BigInt(TRANSFER_AMOUNT), -}); -``` - -This creates a transaction that transfers 3 DOT to Bob's address while keeping Alice's account alive. - -### Sign and Submit with Alternative Fee Payment - -The key part of this tutorial is specifying an alternative asset for fee payment. This is done through the `asset` parameter in the `signAndSubmit` options: - -```typescript title="fee-payment-transaction.ts" -const signer = await createSigner(); - -const result = await tx.signAndSubmit(signer, { - asset: { - parents: 0, - interior: { - type: "X2", - value: [ - { type: "PalletInstance", value: 50 }, - { type: "GeneralIndex", value: BigInt(USD_ASSET_ID) }, - ], - }, - }, -}); - -const { txHash, ok, block, events } = result; -console.log(`Tx finalized: ${txHash} (ok=${ok})`); -console.log(`Block: #${block.number} ${block.hash} [tx index ${block.index}]`); - -console.log("Events:"); -for (const ev of events) { - const type = (ev as any).type ?? "unknown"; - console.log(`- ${type}`); -} - -process.exit(0); -``` - -This specifies that the fees should be paid using the USDT asset. - -## Full Code - -The full code for the complete implementation is the following: - -??? code "Complete Code" - - ```typescript title="fee-payment-transaction.ts" - import { sr25519CreateDerive } from "@polkadot-labs/hdkd"; - import { - DEV_PHRASE, - entropyToMiniSecret, - mnemonicToEntropy, - } from "@polkadot-labs/hdkd-helpers"; - import { getPolkadotSigner } from "polkadot-api/signer"; - import { createClient } from "polkadot-api"; - import { assetHub } from "@polkadot-api/descriptors"; - import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat"; - import { getWsProvider } from "polkadot-api/ws-provider/node"; - import { MultiAddress } from "@polkadot-api/descriptors"; - - const TARGET_ADDRESS = "14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3"; // Bob's address - const TRANSFER_AMOUNT = 3_000_000_000n; // 3 DOT - const USD_ASSET_ID = 1337; - - const createSigner = async () => { - const entropy = mnemonicToEntropy(DEV_PHRASE); - const miniSecret = entropyToMiniSecret(entropy); - const derive = sr25519CreateDerive(miniSecret); - const hdkdKeyPair = derive("//Alice"); - const polkadotSigner = getPolkadotSigner( - hdkdKeyPair.publicKey, - "Sr25519", - hdkdKeyPair.sign - ); - return polkadotSigner; - }; - - const client = createClient( - withPolkadotSdkCompat( - getWsProvider("ws://localhost:8000") // Chopsticks Asset Hub - ) - ); - - const api = client.getTypedApi(assetHub); - - const tx = api.tx.Balances.transfer_keep_alive({ - dest: MultiAddress.Id(TARGET_ADDRESS), - value: BigInt(TRANSFER_AMOUNT), - }); - - const signer = await createSigner(); - - const result = await tx.signAndSubmit(signer, { - asset: { - parents: 0, - interior: { - type: "X2", - value: [ - { type: "PalletInstance", value: 50 }, - { type: "GeneralIndex", value: BigInt(USD_ASSET_ID) }, - ], - }, - }, - }); - - const { txHash, ok, block, events } = result; - console.log(`Tx finalized: ${txHash} (ok=${ok})`); - console.log(`Block: #${block.number} ${block.hash} [tx index ${block.index}]`); - - console.log("Events:"); - for (const ev of events) { - const type = (ev as any).type ?? "unknown"; - console.log(`- ${type}`); - } - - process.exit(0); - ``` - -## Running the Script - -To run the script: - -```bash -npx ts-node fee-payment-transaction.ts -``` - -## Expected Output - -When you run the script successfully, you should see output similar to: - -
    - npx ts-node fee-payment-transaction.ts -
    -Tx finalized: 0x771956fdf40b3741bdc3c1e981a6daacbe5521877ad1915542e7413bb4a820bc (ok=true)
    -Block: #9645060 0x57710514f168b5c444c8e47b1e1a31dd9e7bc7e9a51d8d25ccdbc6053e159f6b [tx index 2]
    -Events:
    -- Assets
    -- Balances
    -- Assets
    -- AssetConversion
    -- Balances
    -- Balances
    -- AssetTxPayment
    -- System
    -
    -
    -The key events to look for are: - -- **Assets**: The asset was transferred. -- **Balances**: The fees were paid using the alternative asset. -- **AssetConversion**: The fees were converted to the alternative asset. -- **AssetTxPayment**: The fees were paid using the alternative asset. -- **System**: The transaction was successful. - -## Conclusion - -Paying transaction fees with alternative tokens on Asset Hub provides significant flexibility for users and applications. - -The key takeaway is understanding how to specify alternative assets using the XCM location format, which opens up possibilities for building applications that can operate entirely using specific token ecosystems while still leveraging the full power of the network. diff --git a/.ai/pages/chain-interactions-send-transactions-with-sdks.md b/.ai/pages/chain-interactions-send-transactions-with-sdks.md deleted file mode 100644 index 9c52f2374..000000000 --- a/.ai/pages/chain-interactions-send-transactions-with-sdks.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/chain-interactions/send-transactions/with-sdks/ ---- - -TODO diff --git a/.ai/pages/chain-interactions-token-operations-convert-assets.md b/.ai/pages/chain-interactions-token-operations-convert-assets.md deleted file mode 100644 index 3d057db56..000000000 --- a/.ai/pages/chain-interactions-token-operations-convert-assets.md +++ /dev/null @@ -1,356 +0,0 @@ ---- -title: Convert Assets on Asset Hub -description: A guide detailing the step-by-step process of converting assets on Asset Hub, helping users efficiently navigate asset management on the platform. -categories: dApps -url: https://docs.polkadot.com/chain-interactions/token-operations/convert-assets/ ---- - -# Convert Assets on Asset Hub - -## Introduction - -Asset Conversion is an Automated Market Maker (AMM) utilizing [Uniswap V2](https://github.com/Uniswap/v2-core){target=\_blank} logic and implemented as a pallet on Polkadot's Asset Hub. - -This guide will provide detailed information about the key functionalities offered by the [Asset Conversion](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/asset-conversion){target=\_blank} pallet on Asset Hub, including: - -- Creating a liquidity pool. -- Adding liquidity to a pool. -- Swapping assets. -- Withdrawing liquidity from a pool. - -## Prerequisites - -Before converting assets on Asset Hub, you must ensure you have: - -- Access to the [Polkadot.js Apps](https://polkadot.js.org/apps){target=\_blank} interface and a connection with the intended blockchain. -- A funded wallet containing the assets you wish to convert and enough available funds to cover the transaction fees. -- An asset registered on Asset Hub that you want to convert. If you haven't created an asset on Asset Hub yet, refer to the [Register a Local Asset](/chain-interactions/token-operations/register-local-asset/){target=\_blank} or [Register a Foreign Asset](/chain-interactions/token-operations/register-foreign-asset/){target=\_blank} documentation to create an asset. - -## Create a Liquidity Pool - -If an asset on Asset Hub does not have an existing liquidity pool, the first step is to create one. - -The asset conversion pallet provides the `createPool` extrinsic to create a new liquidity pool, creating an empty liquidity pool and a new `LP token` asset. - -!!! tip - A testing token with the asset ID `1112` and the name `PPM` was created for this example. - -As stated in the [Test Environment Setup](#test-environment-setup) section, this tutorial is based on the assumption that you have an instance of Polkadot Asset Hub running locally. Therefore, the demo liquidity pool will be created between DOT and PPM tokens. However, the same steps can be applied to any other asset on Asset Hub. - -From the Asset Hub perspective, the Multilocation that identifies the PPM token is the following: - -```javascript -{ - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } -} -``` - -The `PalletInstance` value of `50` represents the Assets pallet on Asset Hub. The `GeneralIndex` value of `1112` is the PPM asset's asset ID. - -To create the liquidity pool, you can follow these steps: - -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: - - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. - - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) - -2. Select extrinsic to create the pool: - - 1. Select the **`AssetConversion`** pallet. - 2. Choose the **`createPool`** extrinsic from the list of available extrinsics. - - ![Create Pool Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-02.webp) - -3. Fill in the required fields: - - 1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents. - - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` - - 2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies. - - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` - - 3. Click on **Submit Transaction** to create the liquidity pool. - - ![Create Pool Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-03.webp) - -Signing and submitting the transaction triggers the creation of the liquidity pool. To verify the new pool's creation, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`PoolCreated`** event was emitted. - -![Pool Created Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-04.webp) - -As the preceding image shows, the **`lpToken`** ID created for this pool is 19. This ID is essential to identify the liquidity pool and associated LP tokens. - -## Add Liquidity to a Pool - -The `addLiquidity` extrinsic allows users to provide liquidity to a pool of two assets. Users specify their preferred amounts for both assets and minimum acceptable quantities. The function determines the best asset contribution, which may vary from the amounts desired but won't fall below the specified minimums. Providers receive liquidity tokens representing their pool portion in return for their contribution. - -To add liquidity to a pool, follow these steps: - -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: - - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. - - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) - -2. Select extrinsic to add liqudity: - - 1. Select the **`assetConversion`** pallet. - 2. Choose the **`addLiquidity`** extrinsic from the list of available extrinsics. - - ![Add Liquidity Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-05.webp) - -3. Fill in the required fields: - - 1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents. - - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` - - 2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies. - - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` - - 3. **`amount1Desired`**: The amount of the first asset that will be contributed to the pool. - 4. **`amount2Desired`**: The quantity of the second asset intended for pool contribution. - 5. **`amount1Min`**: The minimum amount of the first asset that will be contributed. - 6. **`amount2Min`**: The lowest acceptable quantity of the second asset for contribution. - 7. **`mintTo`**: The account to which the liquidity tokens will be minted. - 8. Click on **Submit Transaction** to add liquidity to the pool. - - ![Add Liquidity Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-06.webp) - - !!! warning - Ensure that the appropriate amount of tokens provided has been minted previously and is available in your account before adding liquidity to the pool. - - In this case, the liquidity provided to the pool is between DOT tokens and PPM tokens with the asset ID 1112 on Polkadot Asset Hub. The intention is to provide liquidity for 1 DOT token (`u128` value of 1000000000000 as it has 10 decimals) and 1 PPM token (`u128` value of 1000000000000 as it also has 10 decimals). - -Signing and submitting the transaction adds liquidity to the pool. To verify the liquidity addition, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`LiquidityAdded`** event was emitted. - -![Liquidity Added Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-07.webp) - -## Swap Assets - -### Swap from an Exact Amount of Tokens - -The asset conversion pallet enables users to exchange a specific quantity of one asset for another in a designated liquidity pool by swapping them for an exact amount of tokens. It guarantees the user will receive at least a predetermined minimum amount of the second asset. This function increases trading predictability and allows users to conduct asset exchanges with confidence that they are assured a minimum return. - -To swap assets for an exact amount of tokens, follow these steps: - -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: - - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. - - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) - -2. Select extrinsic to swap assets: - - 1. Select the **`AssetConversion`** pallet. - 2. Choose the **`swapExactTokensForTokens`** extrinsic from the list of available extrinsics. - - ![Swap From Exact Tokens Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-08.webp) - -3. Fill in the required fields: - - 1. **`path: Vec`**: An array of Multilocations representing the path of the swap. The first and last elements of the array are the input and output assets, respectively. In this case, the path consists of two elements: - - - **`0: StagingXcmV3MultiLocation`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents. - - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` - - - **`1: StagingXcmV3MultiLocation`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies. - - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` - - 2. **`amountOut`**: The exact amount of the second asset that the user wants to receive. - 3. **`amountInMax`**: The maximum amount of the first asset that the user is willing to swap. - 4. **`sendTo`**: The account to which the swapped assets will be sent. - 5. **`keepAlive`**: A boolean value that determines whether the pool should be kept alive after the swap. - 6. Click on **Submit Transaction** to swap assets for an exact amount of tokens. - - ![Swap For Exact Tokens Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-09.webp) - - !!! warning - Ensure that the appropriate amount of tokens provided has been minted previously and is available in your account before adding liquidity to the pool. - - In this case, the intention is to swap 0.01 DOT token (u128 value of 100000000000 as it has 10 decimals) for 0.04 PPM token (u128 value of 400000000000 as it also has 10 decimals). - -Signing and submitting the transaction will execute the swap. To verify execution, check the **Explorer** section on the Polkadot.js Apps interface and make sure that the **`SwapExecuted`** event was emitted. - -![Swap From Exact Tokens Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-10.webp) - -### Swap to an Exact Amount of Tokens - -Conversely, the Asset Conversion pallet comes with a function that allows users to trade a variable amount of one asset to acquire a precise quantity of another. It ensures that users stay within a set maximum of the initial asset to obtain the desired amount of the second asset. This provides a method to control transaction costs while achieving the intended result. - -To swap assets for an exact amount of tokens, follow these steps: - -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: - - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. - - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) - -2. Select extrinsic to swap tokens: - - 1. Select the **`AssetConversion`** pallet. - 2. Choose the **`swapTokensForExactTokens`** extrinsic from the list of available extrinsics. - - ![Swap Tokens For Exact Tokens Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-11.webp) - -3. Fill in the required fields: - - 1. **`path: Vec`**: An array of Multilocations representing the path of the swap. The first and last elements of the array are the input and output assets, respectively. In this case, the path consists of two elements: - - **`0: StagingXcmV3MultiLocation`**: The Multilocation of the first asset in the pool. In this case, it is the PPM token, which the following Multilocation represents. - - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` - - - **`1: StagingXcmV3MultiLocation`**: The second asset's Multilocation within the pool. This refers to the DOT token, which the following Multilocation identifies. - - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` - - 2. **`amountOut`**: The exact amount of the second asset that the user wants to receive. - 3. **`amountInMax`**: The maximum amount of the first asset that the user is willing to swap. - 4. **`sendTo`**: The account to which the swapped assets will be sent. - 5. **`keepAlive`**: A boolean value that determines whether the pool should be kept alive after the swap. - 6. Click on **Submit Transaction** to swap assets for an exact amount of tokens. - - ![Swap Tokens For Exact Tokens Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-12.webp) - - !!! warning - Before swapping assets, ensure that the tokens provided have been minted previously and are available in your account. - - In this case, the intention is to swap 0.01 DOT token (`u128` value of 100000000000 as it has ten decimals) for 0.04 PPM token (`u128` value of 400000000000 as it also has ten decimals). - -Signing and submitting the transaction will execute the swap. To verify execution, check the **Explorer** section on the Polkadot.js Apps interface and make sure that the **`SwapExecuted`** event was emitted. - -![Swap Tokens For Exact Tokens Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-13.webp) - -## Withdraw Liquidity from a Pool - -The Asset Conversion pallet provides the `removeLiquidity` extrinsic to remove liquidity from a pool. This function allows users to withdraw the liquidity they offered from a pool, returning the original assets. When calling this function, users specify the number of liquidity tokens (representing their share in the pool) they wish to burn. They also set minimum acceptable amounts for the assets they expect to receive back. This mechanism ensures that users can control the minimum value they receive, protecting against unfavorable price movements during the withdrawal process. - -To withdraw liquidity from a pool, follow these steps: - -1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface: - - 1. Select **Developer** from the top menu. - 2. Click on **Extrinsics** from the dropdown menu. - - ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp) - -2. Select extrinsic to withdraw liqudity from a pool: - - 1. Select the **`AssetConversion`** pallet. - 2. Choose the **`removeLiquidity`** extrinsic from the list of available extrinsics. - - ![Remove Liquidity Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-14.webp) - -3. Fill in the required fields: - - 1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents. - - ```javascript - { - parents: 0, - interior: 'Here' - } - ``` - - 2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies. - - ```javascript - { - parents: 0, - interior: { - X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }] - } - } - ``` - - 3. **`lpTokenBurn`**: The number of liquidity tokens to burn. - 4. **`amount1MinReceived`**: The minimum amount of the first asset that the user expects to receive. - 5. **`amount2MinReceived`**: The minimum quantity of the second asset the user expects to receive. - 6. **`withdrawTo`**: The account to which the withdrawn assets will be sent. - 7. Click on **Submit Transaction** to withdraw liquidity from the pool. - - ![Remove Liquidity Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-15.webp) - - !!! warning - Ensure that the tokens provided have been minted previously and are available in your account before withdrawing liquidity from the pool. - - In this case, the intention is to withdraw 0.05 liquidity tokens from the pool, expecting to receive 0.004 DOT token (`u128` value of 40000000000 as it has 10 decimals) and 0.04 PPM token (`u128` value of 400000000000 as it also has 10 decimals). - -Signing and submitting the transaction will initiate the withdrawal of liquidity from the pool. To verify the withdrawal, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`LiquidityRemoved`** event was emitted. - -![Remove Liquidity Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-16.webp) - -## Test Environment Setup - -To test the Asset Conversion pallet, you can set up a local test environment to simulate different scenarios. This guide uses Chopsticks to spin up an instance of Polkadot Asset Hub. For further details on using Chopsticks, please refer to the [Chopsticks documentation](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank}. - -To set up a local test environment, execute the following command: - -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` - -This command initiates a lazy fork of Polkadot Asset Hub, including the most recent block information from the network. For Kusama Asset Hub testing, simply switch out `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. - -You now have a local Asset Hub instance up and running, ready for you to test various asset conversion procedures. The process here mirrors what you'd do on MainNet. After completing a transaction on TestNet, you can apply the same steps to convert assets on MainNet. diff --git a/.ai/pages/chain-interactions-token-operations-register-foreign-asset.md b/.ai/pages/chain-interactions-token-operations-register-foreign-asset.md deleted file mode 100644 index 17a11089b..000000000 --- a/.ai/pages/chain-interactions-token-operations-register-foreign-asset.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Register a Foreign Asset on Asset Hub -description: An in-depth guide to registering a foreign asset on the Asset Hub parachain, providing clear, step-by-step instructions. -categories: dApps -url: https://docs.polkadot.com/chain-interactions/token-operations/register-foreign-asset/ ---- - -# Register a Foreign Asset on Asset Hub - -## Introduction - -As outlined in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank}, Asset Hub supports two categories of assets: local and foreign. Local assets are created on the Asset Hub system parachain and are identified by integer IDs. On the other hand, foreign assets, which originate outside of Asset Hub, are recognized by [Multilocations](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank}. - -When registering a foreign asset on Asset Hub, it's essential to notice that the process involves communication between two parachains. The Asset Hub parachain will be the destination of the foreign asset, while the source parachain will be the origin of the asset. The communication between the two parachains is facilitated by the [Cross-Chain Message Passing (XCMP)](/parachains/interoperability/get-started/){target=\_blank} protocol. - -This guide will take you through the process of registering a foreign asset on the Asset Hub parachain. - -## Prerequisites - -The Asset Hub parachain is one of the system parachains on a relay chain, such as [Polkadot](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot.api.onfinality.io%2Fpublic-ws#/explorer){target=\_blank} or [Kusama](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama.api.onfinality.io%2Fpublic-ws#/explorer){target=\_blank}. To interact with these parachains, you can use the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank} interface for: - -- [Polkadot Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/explorer){target=\_blank} -- [Kusama Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.ibp.network%2Fstatemine#/explorer){target=\_blank} - -For testing purposes, you can also interact with the Asset Hub instance on the following test networks: - -- [Paseo Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpas-rpc.stakeworld.io%2Fassethub#/explorer){target=\_blank} - -Before you start, ensure that you have: - -- Access to the Polkadot.js Apps interface, and you are connected to the desired chain. -- A parachain that supports the XCMP protocol to interact with the Asset Hub parachain. -- A funded wallet to pay for the transaction fees and subsequent registration of the foreign asset. - -This guide will use Polkadot, its local Asset Hub instance, and the [Astar](https://astar.network/){target=\_blank} parachain (`ID` 2006), as stated in the [Test Environment Setup](#test-environment-setup) section. However, the process is the same for other relay chains and their respective Asset Hub parachain, regardless of the network you are using and the parachain owner of the foreign asset. - -## Steps to Register a Foreign Asset - -### Asset Hub - -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. - - - Testing foreign asset registration is recommended on TestNet before proceeding to MainNet. If you haven't set up a local testing environment yet, consult the [Environment setup](#test-environment-setup) guide. After setting up, connect to the Local Node (Chopsticks) at `ws://127.0.0.1:8000`. - - For live network operations, connect to the Asset Hub parachain. You can choose either Polkadot or Kusama Asset Hub from the dropdown menu, selecting your preferred RPC provider. - -2. Navigate to the **Extrinsics** page: - - 1. Click on the **Developer** tab from the top navigation bar. - 2. Select **Extrinsics** from the dropdown. - - ![Access to Developer Extrinsics section](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-01.webp) - -3. Select the Foreign Assets pallet: - - 3. Select the **`foreignAssets`** pallet from the dropdown list. - 4. Choose the **`create`** extrinsic. - - ![Select the Foreign Asset pallet](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-02.webp) - -3. Fill out the required fields and click on the copy icon to copy the **encoded call data** to your clipboard. The fields to be filled are: - - - **id**: As this is a foreign asset, the ID will be represented by a Multilocation that reflects its origin. For this case, the Multilocation of the asset will be from the source parachain perspective. - - ```javascript - { parents: 1, interior: { X1: [{ Parachain: 2006 }] } } - ``` - - - **admin**: Refers to the account that will be the admin of this asset. This account will be able to manage the asset, including updating its metadata. As the registered asset corresponds to a native asset of the source parachain, the admin account should be the sovereign account of the source parachain. - - The sovereign account can be obtained through [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/){target=\_blank}. - - Ensure that **Sibling** is selected and that the **Para ID** corresponds to the source parachain. In this case, since the guide follows the test setup stated in the [Test Environment Setup](#test-environment-setup) section, the **Para ID** is `2006`. - - ![Get parachain sovereign account](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-03.webp) - - - - **`minBalance`**: The minimum balance required to hold this asset. - - ![Fill out the required fields](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-04.webp) - - !!! tip - If you need an example of the encoded call data, you can copy the following: - ``` - 0x3500010100591f007369626cd6070000000000000000000000000000000000000000000000000000a0860100000000000000000000000000 - ``` - -### Source Parachain - -1. Navigate to the **Developer > Extrinsics** section. -2. Create the extrinsic to register the foreign asset through XCM: - - 1. Paste the **encoded call data** copied in the previous step. - 2. Click the **Submit Transaction** button. - - ![Register foreign asset through XCM](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-05.webp) - - This XCM call involves withdrawing DOT from the sibling account of the parachain, using it to initiate an execution. The transaction will be carried out with XCM as the origin kind, and will be a hex-encoded call to create a foreign asset on Asset Hub for the specified parachain asset multilocation. Any surplus will be refunded, and the asset will be deposited into the sibling account. - - !!! warning - Note that the sovereign account on the Asset Hub parachain must have a sufficient balance to cover the XCM `BuyExecution` instruction. If the account does not have enough balance, the transaction will fail. - - If you want to have the whole XCM call ready to be copied, go to the **Developer > Extrinsics > Decode** section and paste the following hex-encoded call data: - - ```text - 0x6300330003010100a10f030c000400010000070010a5d4e81300010000070010a5d4e80006030700b4f13501419ce03500010100591f007369626cd607000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - ``` - - Be sure to replace the encoded call data with the one you copied in the previous step. - -After the transaction is successfully executed, the foreign asset will be registered on the Asset Hub parachain. - -## Asset Registration Verification - -To confirm that a foreign asset has been successfully accepted and registered on the Asset Hub parachain, you can navigate to the `Network > Explorer` section of the Polkadot.js Apps interface for Asset Hub. You should be able to see an event that includes the following details: - -![Asset registration event](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-06.webp) - -In the image above, the **success** field indicates whether the asset registration was successful. - -## Test Environment Setup - -To test the foreign asset registration process before deploying it on a live network, you can set up a local parachain environment. This guide uses Chopsticks to simulate that process. For more information on using Chopsticks, please refer to the [Chopsticks documentation](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank}. - -To set up a test environment, run the following command: - -```bash -npx @acala-network/chopsticks xcm \ ---r polkadot \ ---p polkadot-asset-hub \ ---p astar -``` - -The preceding command will create a lazy fork of Polkadot as the relay chain, its Asset Hub instance, and the Astar parachain. The `xcm` parameter enables communication through the XCMP protocol between the relay chain and the parachains, allowing the registration of foreign assets on Asset Hub. For further information on the chopsticks usage of the XCMP protocol, refer to the [XCM Testing](/tutorials/polkadot-sdk/testing/fork-live-chains/#xcm-testing){target=\_blank} section of the Chopsticks documentation. - -After executing the command, the terminal will display output indicating the Polkadot relay chain, the Polkadot Asset Hub, and the Astar parachain are running locally and connected through XCM. You can access them individually via the Polkadot.js Apps interface. - -- [Polkadot Relay Chain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8002#/explorer){target=\_blank} -- [Polkadot Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8000#/explorer){target=\_blank} -- [Astar Parachain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8001#/explorer){target=\_blank} diff --git a/.ai/pages/chain-interactions-token-operations-register-local-asset.md b/.ai/pages/chain-interactions-token-operations-register-local-asset.md deleted file mode 100644 index 0f257f3e2..000000000 --- a/.ai/pages/chain-interactions-token-operations-register-local-asset.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Register a Local Asset -description: Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. -categories: Basics, dApps -url: https://docs.polkadot.com/chain-interactions/token-operations/register-local-asset/ ---- - -# Register a Local Asset on Asset Hub - -## Introduction - -As detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation. - -This guide will take you through the steps of registering a local asset on the Asset Hub parachain. - -## Prerequisites - -Before you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and a funded wallet with DOT or KSM. - -- For Polkadot Asset Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata. -- For Kusama Asset Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata. - -You need to ensure that your Asset Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees. - -## Steps to Register a Local Asset - -To register a local asset on the Asset Hub parachain, follow these steps: - -1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner. - - - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`. - - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider. - -2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list. - - ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp) - -3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column. - - ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp) - -4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page. - - ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp) - -5. Fill in the required fields in the **Create Asset** form: - - 1. **creator account**: The account to be used for creating this asset and setting up the initial metadata. - 2. **asset name**: The descriptive name of the asset you are registering. - 3. **asset symbol**: The symbol that will be used to represent the asset. - 4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface. - 5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested. - 6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id. - 7. Click on the **Next** button. - - ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp) - -6. Choose the accounts for the roles listed below: - - 1. **admin account**: The account designated for continuous administration of the token. - 2. **issuer account**: The account that will be used for issuing this token. - 3. **freezer account**: The account that will be used for performing token freezing operations. - 4. Click on the **Create** button. - - ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp) - -7. Click on the **Sign and Submit** button to complete the asset registration process. - - ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp) - -## Verify Asset Registration - -After completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets){target=\_blank} section of the Polkadot.js Apps interface. - -![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp) - -!!! tip - Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field. - -In this way, you have successfully registered a local asset on the Asset Hub parachain. - -For an in-depth explanation about Asset Hub and its features, see the [Asset Hub](/chain-interactions/token-operations/convert-assets/){target=\_blank} entry in the Polkadot Wiki. - -## Test Setup Environment - -You can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\_blank} documentation. - -To set up a test environment, execute the following command: - -```bash -npx @acala-network/chopsticks \ ---config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -``` - -The above command will spawn a lazy fork of Polkadot Asset Hub with the latest block data from the network. If you need to test Kusama Asset Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command. - -An Asset Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet. diff --git a/.ai/pages/chain-interactions.md b/.ai/pages/chain-interactions.md deleted file mode 100644 index dfb4dde67..000000000 --- a/.ai/pages/chain-interactions.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Chain Interactions Overview -description: Learn how to query data, send transactions, enable cross-chain communication, and manage accounts across the Polkadot ecosystem. -categories: Chain Interactions -url: https://docs.polkadot.com/chain-interactions/ ---- - -# Chain Interactions - -## Introduction - -Chain interactions form the foundation of building applications on Polkadot. Whether you're querying on-chain data, executing transactions, enabling cross-chain communication, or managing accounts, understanding how to interact with Polkadot-based chains is essential for application developers. - -This section provides comprehensive guidance on the various ways to interact with Polkadot chains, from basic queries to complex cross-chain operations. You'll learn how to: - -- Query on-chain state and subscribe to blockchain events. -- Send transactions and manage their lifecycle. -- Enable interoperability between parachains through XCM. -- Manage tokens and perform token operations. -- Create and manage accounts programmatically. - -Whether you're building a frontend application, a backend service, or integrating with the Polkadot ecosystem, these guides will equip you with the knowledge and tools to effectively interact with chains across the network. - -## Core Interaction Patterns - -### Query On-Chain Data - -Accessing blockchain state is fundamental to building responsive applications. Polkadot offers several methods to query on-chain data, each suited for different use cases. - -- **[SDK integration](/chain-interactions/query-data/query-sdks/)**: Programmatically read blockchain state using: - - - [Polkadot API (PAPI)](/reference/tools/papi/) - - [Polkadot.js](/reference/tools/polkadot-js-api/) - - [Dedot](/reference/tools/dedot/) - - [Python Substrate Interface](/reference/tools/py-substrate-interface/) - - [Subxt](/reference/tools/subxt/) - -- **[REST API access](/chain-interactions/query-data/query-rest/)**: Query chain data through standardized REST endpoints for simpler integration. -- **[Runtime API calls](/chain-interactions/query-data/runtime-api-calls/)**: Execute runtime APIs directly for specialized queries and operations. - -### Send Transactions - -Transactions are the primary mechanism for modifying blockchain state. Understanding transaction construction, signing, and submission is crucial for building interactive applications. - -- **[Transaction construction](/chain-interactions/send-transactions/with-sdks/)**: Build transactions using various SDKs with proper encoding and formatting. -- **[Fee estimation](/chain-interactions/send-transactions/calculate-transaction-fees/)**: Calculate transaction fees to ensure sufficient balance and optimize costs. -- **[Multi-token fees](/chain-interactions/send-transactions/pay-fees-with-different-tokens/)**: Learn how to pay transaction fees with different tokens on supported chains. - -### Send Cross-Chain Transactions - -Polkadot enables native cross-chain capabilities through Cross-Consensus Messaging (XCM), allowing chains to securely communicate and transfer assets across the ecosystem. - -- **[Transfer assets between parachains](/chain-interactions/send-transactions/interoperability/transfer-assets-parachains/)**: Understand how to construct and send XCM messages using [ParaSpell XCM SDK](/reference/tools/paraspell/){target=\_blank} and [Polkadot API (PAPI)](/reference/tools/papi/){target=\_blank}. -- **[Transfer assets out of Polkadot](/chain-interactions/send-transactions/interoperability/transfer-assets-out-of-polkadot/)**: Connect to blockchains outside the Polkadot ecosystem using [Snowbridge](https://wiki.polkadot.com/learn/learn-snowbridge/){target=\_blank} and other bridge solutions. - -### Manage Tokens - -Polkadot Hub provides a unified platform for managing assets across the ecosystem. Understanding token operations is essential for DeFi applications and multi-chain asset management. - -- **[Local asset registration](/chain-interactions/token-operations/register-local-asset/)**: Learn how assets created in Asset Hub are registered on the network. -- **[Foregin asset registration](/chain-interactions/token-operations/register-foreign-asset/)**: Learn how assets created outside of Asset Hub are registered on the network. -- **[Convert assets](/chain-interactions/token-operations/convert-assets/)**: Convert, swap, and manage assets on-chain using the Asset Conversion pallet. -- **Asset Hub integration**: Interact with Polkadot's central asset management hub using [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\_blank}. - -### Manage Accounts - -Account management forms the basis of user identity and authentication in blockchain applications. Learn how to create, manage, and query accounts programmatically. - -- **[Account creation](/chain-interactions/accounts/create-account/)**: Generate accounts using various SDKs in Rust, Python, and JavaScript. -- **[Account queries](/chain-interactions/accounts/query-accounts/)**: Retrieve account information including balances, nonces, and metadata. - -## Development Tools and SDKs - -The Polkadot ecosystem offers a rich set of tools and libraries to facilitate chain interactions: - -- **[Polkadot API (PAPI)](/reference/tools/papi/)**: Modern, type-safe TypeScript library with full metadata support. -- **[Polkadot.js](/reference/tools/polkadot-js-api/)**: Comprehensive JavaScript library with extensive ecosystem support. -- **[Dedot](/reference/tools/dedot/)**: Lightweight TypeScript library optimized for performance. -- **[Python Substrate Interface](/reference/tools/py-substrate-interface/)**: Polkadot Substrate Interface for streamlined development. -- **[Subxt](/reference/tools/subxt/)**: Rust library for building robust substrate-based applications. -- **[Polkadot.js Apps](https://polkadot.js.org/apps/)**: Web-based interface for exploring and interacting with chains. - -Each tool has its strengths, and choosing the right one depends on your project requirements, programming language preference, and specific use cases. - -## Next Steps - -Explore the sections below to dive deeper into specific chain interaction patterns: - -- **[Query On-Chain Data](/chain-interactions/query-data/query-sdks/)**: Learn to read blockchain state efficiently. -- **[Send Transactions](/chain-interactions/send-transactions/with-sdks/)**: Master transaction construction and submission. -- **[Send Cross-Chain Transactions](/chain-interactions/send-transactions/interoperability/transfer-assets-parachains/)**: Enable cross-chain communication with XCM. -- **[Manage Tokens](/chain-interactions/token-operations/register-local-asset/)**: Manage assets across the Polkadot ecosystem. -- **[Manage Accounts](/chain-interactions/accounts/create-account/)**: Create and query accounts programmatically. - -Each section provides practical examples, code snippets, and comprehensive guides to help you build production-ready applications on Polkadot. diff --git a/.ai/pages/parachains-interoperability-get-started.md b/.ai/pages/parachains-interoperability-get-started.md index bb8008ceb..a7e59e626 100644 --- a/.ai/pages/parachains-interoperability-get-started.md +++ b/.ai/pages/parachains-interoperability-get-started.md @@ -1,11 +1,11 @@ --- -title: Introduction to XCM +title: Get Started with XCM description: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. categories: Basics, Polkadot Protocol url: https://docs.polkadot.com/parachains/interoperability/get-started/ --- -# Introduction to XCM +# Get Started with XCM ## Introduction diff --git a/.ai/pages/parachains-testing-fork-a-parachain.md b/.ai/pages/parachains-testing-fork-a-parachain.md index 6bb56dbff..73df0a187 100644 --- a/.ai/pages/parachains-testing-fork-a-parachain.md +++ b/.ai/pages/parachains-testing-fork-a-parachain.md @@ -1,11 +1,11 @@ --- -title: Get Started +title: Fork a Parachain Using Chopsticks description: Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. categories: Parachains, Tooling url: https://docs.polkadot.com/parachains/testing/fork-a-parachain/ --- -# Get Started +# Fork a Parachain Using Chopsticks ## Introduction diff --git a/.ai/pages/parachains-testing-run-a-parachain-network.md b/.ai/pages/parachains-testing-run-a-parachain-network.md index afc7dda6e..a922abdce 100644 --- a/.ai/pages/parachains-testing-run-a-parachain-network.md +++ b/.ai/pages/parachains-testing-run-a-parachain-network.md @@ -1,11 +1,11 @@ --- -title: Get Started +title: Run a Parachain Network description: Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. categories: Parachains, Tooling url: https://docs.polkadot.com/parachains/testing/run-a-parachain-network/ --- -# Get Started +# Run a Parachain Network Using Zombienet ## Introduction diff --git a/.ai/pages/reference-glossary.md b/.ai/pages/reference-glossary.md deleted file mode 100644 index fc82d8bc8..000000000 --- a/.ai/pages/reference-glossary.md +++ /dev/null @@ -1,365 +0,0 @@ ---- -title: Glossary -description: Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. -categories: Reference -url: https://docs.polkadot.com/reference/glossary/ ---- - -# Glossary - -Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here. - -Additional glossaries from around the ecosystem you might find helpful: - -- [Polkadot Wiki Glossary](https://wiki.polkadot.com/general/glossary){target=\_blank} -- [Polkadot SDK Glossary](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/glossary/index.html){target=\_blank} - -## Authority - -The role in a blockchain that can participate in consensus mechanisms. - -- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final. -- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author). - -Authority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol. - -## Authority Round (Aura) - -A deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol. - -Learn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\_blank} wiki article. - -## Blind Assignment of Blockchain Extension (BABE) - -A [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block. - -Learn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank}. - -## Block Author - -The node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_. - -## Byzantine Fault Tolerance (BFT) - -The ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack. - -### Byzantine Failure - -The loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus. - -### Practical Byzantine Fault Tolerance (pBFT) - -An early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants. - -The communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system. - -### Preimage - -A preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\_blank}, the output, the hash, cannot be used to reveal the input, the preimage. - -## Call - -In the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object. - -## Chain Specification - -A chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains. - -## Collator - -An [author](#block-author) of a [parachain](#parachain) network. -They aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus). - -More details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\_blank}. - -## Collective - -Most often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network. - -## Consensus - -Consensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship. - -See also [hybrid consensus](#hybrid-consensus). - -## Consensus Algorithm - -Ensures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft). - -Consensus algorithms are generally concerned with ensuring two properties: - -- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain. -- **Liveness**: Indicating the ability of the chain to keep progressing. - -## Consensus Engine - -The node subsystem responsible for consensus tasks. - -For detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} blog series. - -See also [hybrid consensus](#hybrid-consensus). - -## Coretime - -The time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*. - -On-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety. - -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\_blank}. - -## Development Phrase - -A [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\_blank} that is intentionally made public. - -Well-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase: - -``` -bottom drive obey lake curtain smoke basket hold race lonely fit walk -``` - -Many tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`. - -## Digest - -An extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including: - -- [Light clients](#light-client) for chain synchronization. -- Consensus engines for block verification. -- The runtime itself, in the case of pre-runtime digests. - -## Dispatchable - -Function objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations. - -## Events - -A means of recording that some particular [state](#state) transition happened. - -In the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization. - -## Executor - -A means of executing a function call in a given [runtime](#runtime) with a set of dependencies. -There are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_. - -- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes. - -- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain. - -## Existential Deposit - -The minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. - -If an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\_blank} to drop its references to that account. - -If the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\_blank}. - -## Extrinsic - -A general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder. - -It is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). - -For more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\_blank}. - -## Fork Choice Rule/Strategy - -A fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\_blank}, in which the chain with the most blocks is selected. - -## FRAME (Framework for Runtime Aggregation of Modularized Entities) - -Enables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes. - -[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank} - -## Full Node - -A node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization. - -## Genesis Configuration - -A mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file. - -## GRANDPA - -A deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. - -The [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\_blank}. - -## Header - -A structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization. - -## Hybrid Consensus - -A blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality. - -Hybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa). - -## Inherent Transactions - -A special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block. - -Only the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified. - -## JSON-RPC - -A stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON. - -For Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\_blank} crate. - -## Keystore - -A subsystem for managing keys for the purpose of producing new blocks. - -## Kusama - -[Kusama](https://kusama.network/){target=\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network. - -Kusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\_blank} network and is referred to as [Polkadot's "wild cousin."](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\_blank}. - -As a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation. - -## libp2p - -A peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser). - -Polkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\_blank} of the `libp2p` networking stack. - -## Light Client - -A type of blockchain node that doesn't store the [chain state](#state) or produce blocks. - -A light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\_blank} server, enabling blockchain users to interact with the network. - -## Metadata - -Data that provides information about one or more aspects of a system. -The metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system. - -## Nominated Proof of Stake (NPoS) - -A method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes. - -## Oracle - -An entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services. - -## Origin - -A [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\_blank}. - -## Pallet - -A module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime). -Pallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item). - -## Parachain - -A parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_. -You can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\_blank}. - -## Paseo - -Paseo TestNet provisions testing on Polkadot's "production" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing. - -## Polkadot - -The [Polkadot network](https://polkadot.com/){target=\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain). - -## Polkadot Cloud - -Polkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance. - -## Polkadot Hub - -Polkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3. - -## PolkaVM - -PolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution. - -## Relay Chain - -Relay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another. - -## Rococo - -A [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead. - -## Runtime - -The runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function. - -## Slot - -A fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block. - -## Sovereign Account - -The unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem. - -The sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier. - -## SS58 Address Format - -A public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain - -The [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks - -## State Transition Function (STF) - -The logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime). - -## Storage Item - -[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime). -Learn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\_blank} reference document in the Polkadot SDK. - -## Substrate - -A flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\_blank}. - -## Transaction - -An [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}. - -## Transaction Era - -A definable period expressed as a range of block numbers during which a transaction can be included in a block. -Transaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero. - -## Trie (Patricia Merkle Tree) - -A data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set. - -In Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays. - -## Validator - -A validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance. - -## WebAssembly (Wasm) - -An execution architecture that allows for the efficient, platform-neutral expression of -deterministic, machine-executable logic. - -[Wasm](https://webassembly.org/){target=\_blank} can be compiled from many languages, including -the [Rust](https://www.rust-lang.org/){target=\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state. - -## Weight - -A convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block. -Polkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware. - -The maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for: - -- Block construction -- Network propagation -- Import and verification - -By defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements. - -## Westend - -Westend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network. diff --git a/.ai/pages/reference-governance-origins-tracks.md b/.ai/pages/reference-governance-origins-tracks.md deleted file mode 100644 index 72c121a77..000000000 --- a/.ai/pages/reference-governance-origins-tracks.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Origins and Tracks -description: Explore Polkadot's OpenGov origins and tracks system, defining privilege levels, decision processes, and tailored pathways for network proposals. -categories: Polkadot Protocol -url: https://docs.polkadot.com/reference/governance/origins-tracks/ ---- - -# Origins and Tracks - -## Introduction - -Polkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency. - -This guide will help you understand the role of origins in classifying proposals by privilege and priority. You will learn how tracks guide proposals through tailored stages like voting, confirmation, and enactment and how to select the correct origin for your referendum to align with community expectations and network governance. - -Origins and tracks are vital in streamlining the governance workflow and maintaining Polkadot's resilience and adaptability. - -## Origins - -Origins are the foundation of Polkadot's OpenGov governance system. They categorize proposals by privilege and define their decision-making rules. Each origin corresponds to a specific level of importance and risk, guiding how referendums progress through the governance process. - -- High-privilege origins like Root Origin govern critical network changes, such as core software upgrades. -- Lower-privilege origins like Small Spender handle minor requests, such as community project funding under 10,000 DOT. - -Proposers select an origin based on the nature of their referendum. Origins determine parameters like approval thresholds, required deposits, and timeframes for voting and confirmation. Each origin is paired with a track, which acts as a roadmap for the proposal's lifecycle, including preparation, voting, and enactment. - -For a detailed list of origins and their associated parameters, see the [Polkadot OpenGov Origins](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/){target=\_blank} entry in the Polkadot Wiki. - -## Tracks - -Tracks define a referendum's journey from submission to enactment, tailoring governance parameters to the impact of proposed changes. Each track operates independently and includes several key stages: - -- **Preparation**: Time for community discussion before voting begins. -- **Voting**: Period for token holders to cast their votes. -- **Decision**: Finalization of results and determination of the proposal's outcome. -- **Confirmation**: Period to verify sustained community support before enactment. -- **Enactment**: Final waiting period before the proposal takes effect. - -Tracks customize these stages with parameters like decision deposit requirements, voting durations, and approval thresholds, ensuring proposals from each origin receive the required scrutiny and process. For example, a runtime upgrade in the Root Origin track will have longer timeframes and stricter thresholds than a treasury request in the Small Spender track. - -## Additional Resources - -- For a list of origins and tracks for Polkadot and Kusama, including associated parameters, see the [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#origins-and-tracks-info){target=\_blank} entry in the Polkadot Wiki. - -- For a deeper dive into the approval and support system, see the [Approval and Support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} entry of the Polkadot Wiki. diff --git a/.ai/pages/reference-governance.md b/.ai/pages/reference-governance.md deleted file mode 100644 index 891fb4cb9..000000000 --- a/.ai/pages/reference-governance.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: On-Chain Governance Overview -description: Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/governance/ ---- - -# On-Chain Governance - -## Introduction - -Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model. - -This guide will explain the principles and structure of OpenGov and walk you through its key components, such as Origins, Tracks, and Delegation. You will learn about improvements over earlier governance systems, including streamlined voting processes and enhanced stakeholder participation. - -With OpenGov, Polkadot achieves a flexible, scalable, and democratic governance framework that allows multiple proposals to proceed simultaneously, ensuring the network evolves in alignment with its community's needs. - -## Governance Evolution - -Polkadot’s governance journey began with [Governance V1](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#governance-summary){target=\_blank}, a system that proved effective in managing treasury funds and protocol upgrades. However, it faced limitations, such as: - -- Slow voting cycles, causing delays in decision-making. -- Inflexibility in handling multiple referendums, restricting scalability. - -To address these challenges, Polkadot introduced OpenGov, a governance model designed for greater inclusivity, efficiency, and scalability. OpenGov replaces the centralized structures of Governance V1, such as the Council and Technical Committee, with a fully decentralized and dynamic framework. - -For a full comparison of the historic and current governance models, visit the [Gov1 vs. Polkadot OpenGov](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#gov1-vs-polkadot-opengov){target=\_blank} section of the Polkadot Wiki. - -## OpenGov Key Features - -OpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include: - -- **Decentralization**: Shifts all decision-making power to the public, ensuring a more democratic process. -- **Enhanced delegation**: Allows users to delegate their votes to trusted experts across specific governance tracks. -- **Simultaneous referendums**: Multiple proposals can progress at once, enabling faster decision-making. -- **Polkadot Technical Fellowship**: A broad, community-driven group replacing the centralized Technical Committee. - -This new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows. - -## Origins and Tracks - -In OpenGov, origins and tracks are central to managing proposals and votes. - -- **Origin**: Determines the authority level of a proposal (e.g., Treasury, Root) which decides the track of all referendums from that origin. -- **Track**: Define the procedural flow of a proposal, such as voting duration, approval thresholds, and enactment timelines. - -Developers must be aware that referendums from different origins and tracks will take varying amounts of time to reach approval and enactment. The [Polkadot Technical Fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank} has the option to shorten this timeline by whitelisting a proposal and allowing it to be enacted through the [Whitelist Caller](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#whitelisted-caller){target=\_blank} origin. - -Visit [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#origins-and-tracks){target=\_blank} for details on current origins and tracks, associated terminology, and parameters. - -## Referendums - -In OpenGov, anyone can submit a referendum, fostering an open and participatory system. The timeline for a referendum depends on the privilege level of the origin with more significant changes offering more time for community voting and participation before enactment. - -The timeline for an individual referendum includes four distinct periods: - -- **Lead-in**: A minimum amount of time to allow for community participation, available room in the origin, and payment of the decision deposit. Voting is open during this period. -- **Decision**: Voting continues. -- **Confirmation**: Referendum must meet [approval and support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\_blank} criteria during entire period to avoid rejection. -- **Enactment**: Changes approved by the referendum are executed. - -### Vote on Referendums - -Voters can vote with their tokens on each referendum. Polkadot uses a voluntary token locking mechanism, called conviction voting, as a way for voters to increase their voting power. A token holder signals they have a stronger preference for approving a proposal based upon their willingness to lock up tokens. Longer voluntary token locks are seen as a signal of continual approval and translate to increased voting weight. - -See [Voting on a Referendum](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank} for a deeper look at conviction voting and related token locks. - -### Delegate Voting Power - -The OpenGov system also supports multi-role delegations, allowing token holders to assign their voting power on different tracks to entities with expertise in those areas. - -For example, if a token holder lacks the technical knowledge to evaluate proposals on the [Root track](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#root){target=\_blank}, they can delegate their voting power for that track to an expert they trust to vote in the best interest of the network. This ensures informed decision-making across tracks while maintaining flexibility for token holders. - -Visit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\_blank} for more details on delegating voting power. - -### Cancel a Referendum - -Polkadot OpenGov has two origins for rejecting ongoing referendums: - -- [**Referendum Canceller**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-canceller){target=\_blank}: Cancels an active referendum when non-malicious errors occur and refunds the deposits to the originators. -- [**Referendum Killer**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-killer){target=\_blank}: Used for urgent, malicious cases this origin instantly terminates an active referendum and slashes deposits. - -See [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\_blank} for additional information on rejecting referendums. - -## Additional Resources - -- **[Democracy pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/democracy/src){target=\_blank}**: Handles administration of general stakeholder voting. -- **[Gov2: Polkadot’s Next Generation of Decentralised Governance](https://medium.com/polkadot-network/gov2-polkadots-next-generation-of-decentralised-governance-4d9ef657d11b){target=\_blank}**: Medium article by Gavin Wood. -- **[Polkadot Direction](https://matrix.to/#/#Polkadot-Direction:parity.io){target=\_blank}**: Matrix Element client. -- **[Polkassembly](https://polkadot.polkassembly.io/){target=\_blank}**: OpenGov dashboard and UI. -- **[Polkadot.js Apps Governance](https://polkadot.js.org/apps/#/referenda){target=\_blank}**: Overview of active referendums. diff --git a/.ai/pages/reference-parachains-accounts.md b/.ai/pages/reference-parachains-accounts.md deleted file mode 100644 index 5ee42fd0a..000000000 --- a/.ai/pages/reference-parachains-accounts.md +++ /dev/null @@ -1,395 +0,0 @@ ---- -title: Polkadot SDK Accounts -description: Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/accounts/ ---- - -# Accounts - -## Introduction - -Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains. - -This page will guide you through the essential aspects of accounts, including their data structure, balance types, reference counters, and address formats. You’ll learn how accounts are managed within the runtime, how balances are categorized, and how addresses are encoded and validated. - -## Account Data Structure - -Accounts are foundational to any blockchain, and the Polkadot SDK provides a flexible management system. This section explains how the Polkadot SDK defines accounts and manages their lifecycle through data structures within the runtime. - -### Account - -The [`Account` data type](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/type.Account.html){target=\_blank} is a storage map within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank} that links an account ID to its corresponding data. This structure is fundamental for mapping account-related information within the chain. - -The code snippet below shows how accounts are defined: - -```rs - /// The full account information for a particular account ID. - #[pallet::storage] - #[pallet::getter(fn account)] - pub type Account = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - AccountInfo, - ValueQuery, - >; -``` - -The preceding code block defines a storage map named `Account`. The `StorageMap` is a type of on-chain storage that maps keys to values. In the `Account` map, the key is an account ID, and the value is the account's information. Here, `T` represents the generic parameter for the runtime configuration, which is defined by the pallet's configuration trait (`Config`). - -The `StorageMap` consists of the following parameters: - -- **`_`**: Used in macro expansion and acts as a placeholder for the storage prefix type. Tells the macro to insert the default prefix during expansion. -- **`Blake2_128Concat`**: The hashing function applied to keys in the storage map. -- **`T: :AccountId`**: Represents the key type, which corresponds to the account’s unique ID. -- **`AccountInfo`**: The value type stored in the map. For each account ID, the map stores an `AccountInfo` struct containing: - - - **`T::Nonce`**: A nonce for the account, which is incremented with each transaction to ensure transaction uniqueness. - - **`T: :AccountData`**: Custom account data defined by the runtime configuration, which could include balances, locked funds, or other relevant information. - -- **`ValueQuery`**: Defines how queries to the storage map behave when no value is found; returns a default value instead of `None`. - -For a detailed explanation of storage maps, see the [`StorageMap`](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/struct.StorageMap.html){target=\_blank} entry in the Rust docs. - -### Account Info - -The `AccountInfo` structure is another key element within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\_blank}, providing more granular details about each account's state. This structure tracks vital data, such as the number of transactions and the account’s relationships with other modules. - -```rs -/// Information of an account. -#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct AccountInfo { - /// The number of transactions this account has sent. - pub nonce: Nonce, - /// The number of other modules that currently depend on this account's existence. The account - /// cannot be reaped until this is zero. - pub consumers: RefCount, - /// The number of other modules that allow this account to exist. The account may not be reaped - /// until this and `sufficients` are both zero. - pub providers: RefCount, - /// The number of modules that allow this account to exist for their own purposes only. The - /// account may not be reaped until this and `providers` are both zero. - pub sufficients: RefCount, - /// The additional data that belongs to this account. Used to store the balance(s) in a lot of - /// chains. - pub data: AccountData, -} -``` - -The `AccountInfo` structure includes the following components: - -- **`nonce`**: Tracks the number of transactions initiated by the account, which ensures transaction uniqueness and prevents replay attacks. -- **`consumers`**: Counts how many other modules or pallets rely on this account’s existence. The account cannot be removed from the chain (reaped) until this count reaches zero. -- **`providers`**: Tracks how many modules permit this account’s existence. An account can only be reaped once both `providers` and `sufficients` are zero. -- **`sufficients`**: Represents the number of modules that allow the account to exist for internal purposes, independent of any other modules. -- **`AccountData`**: A flexible data structure that can be customized in the runtime configuration, usually containing balances or other user-specific data. - -This structure helps manage an account's state and prevents its premature removal while it is still referenced by other on-chain data or modules. The [`AccountInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.AccountInfo.html){target=\_blank} structure can vary as long as it satisfies the trait bounds defined by the `AccountData` associated type in the [`frame-system::pallet::Config`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/trait.Config.html){target=\_blank} trait. - -### Account Reference Counters - -Polkadot SDK uses reference counters to track an account’s dependencies across different runtime modules. These counters ensure that accounts remain active while data is associated with them. - -The reference counters include: - -- **`consumers`**: Prevents account removal while other pallets still rely on the account. -- **`providers`**: Ensures an account is active before other pallets store data related to it. -- **`sufficients`**: Indicates the account’s independence, ensuring it can exist even without a native token balance, such as when holding sufficient alternative assets. - -#### Providers Reference Counters - -The `providers` counter ensures that an account is ready to be depended upon by other runtime modules. For example, it is incremented when an account has a balance above the existential deposit, which marks the account as active. - -The system requires this reference counter to be greater than zero for the `consumers` counter to be incremented, ensuring the account is stable before any dependencies are added. - -#### Consumers Reference Counters - -The `consumers` counter ensures that the account cannot be reaped until all references to it across the runtime have been removed. This check prevents the accidental deletion of accounts that still have active on-chain data. - -It is the user’s responsibility to clear out any data from other runtime modules if they wish to remove their account and reclaim their existential deposit. - -#### Sufficients Reference Counter - -The `sufficients` counter tracks accounts that can exist independently without relying on a native account balance. This is useful for accounts holding other types of assets, like tokens, without needing a minimum balance in the native token. - -For instance, the [Assets pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank}, may increment this counter for an account holding sufficient tokens. - -#### Account Deactivation - -In Polkadot SDK-based chains, an account is deactivated when its reference counters (such as `providers`, `consumers`, and `sufficient`) reach zero. These counters ensure the account remains active as long as other runtime modules or pallets reference it. - -When all dependencies are cleared and the counters drop to zero, the account becomes deactivated and may be removed from the chain (reaped). This is particularly important in Polkadot SDK-based blockchains, where accounts with balances below the existential deposit threshold are pruned from storage to conserve state resources. - -Each pallet that references an account has cleanup functions that decrement these counters when the pallet no longer depends on the account. Once these counters reach zero, the account is marked for deactivation. - -#### Updating Counters - -The Polkadot SDK provides runtime developers with various methods to manage account lifecycle events, such as deactivation or incrementing reference counters. These methods ensure that accounts cannot be reaped while still in use. - -The following helper functions manage these counters: - -- **`inc_consumers()`**: Increments the `consumer` reference counter for an account, signaling that another pallet depends on it. -- **`dec_consumers()`**: Decrements the `consumer` reference counter, signaling that a pallet no longer relies on the account. -- **`inc_providers()`**: Increments the `provider` reference counter, ensuring the account remains active. -- **`dec_providers()`**: Decrements the `provider` reference counter, allowing for account deactivation when no longer in use. -- **`inc_sufficients()`**: Increments the `sufficient` reference counter for accounts that hold sufficient assets. -- **`dec_sufficients()`**: Decrements the `sufficient` reference counter. - -To ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action. - -The `System` pallet offers three query functions to assist developers in tracking account states: - -- **[`can_inc_consumer()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_inc_consumer){target=\_blank}**: Checks if the account can safely increment the consumer reference. -- **[`can_dec_provider()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_dec_provider){target=\_blank}**: Ensures that no consumers exist before allowing the decrement of the provider counter. -- **[`is_provider_required()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.is_provider_required){target=\_blank}**: Verifies whether the account still has any active consumer references. - -This modular and flexible system of reference counters tightly controls the lifecycle of accounts in Polkadot SDK-based blockchains, preventing the accidental removal or retention of unneeded accounts. You can refer to the [System pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html){target=\_blank} for more details. - - -## Account Balance Types - -In the Polkadot ecosystem, account balances are categorized into different types based on how the funds are utilized and their availability. These balance types determine the actions that can be performed, such as transferring tokens, paying transaction fees, or participating in governance activities. Understanding these balance types helps developers manage user accounts and implement balance-dependent logic. - -!!! note "A more efficient distribution of account balance types is in development" - Soon, pallets in the Polkadot SDK will implement the [`Fungible` trait](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} (see the [tracking issue](https://github.com/paritytech/polkadot-sdk/issues/226){target=\_blank} for more details). For example, the [`transaction-storage`](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_storage/index.html){target=\_blank} pallet changed the implementation of the [`Currency`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/currency/index.html){target=\_blank} trait (see the [Refactor transaction storage pallet to use fungible traits](https://github.com/paritytech/polkadot-sdk/pull/1800){target=\_blank} PR for further details): - - ```rust - type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; - ``` - - To the [`Fungible`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\_blank} trait: - - ```rust - type BalanceOf = <::Currency as FnInspect<::AccountId>>::Balance; - ``` - - This update will enable more efficient use of account balances, allowing the free balance to be utilized for on-chain activities such as setting proxies and managing identities. - -### Balance Types - -The five main balance types are: - -- **Free balance**: Represents the total tokens available to the account for any on-chain activity, including staking, governance, and voting. However, it may not be fully spendable or transferrable if portions of it are locked or reserved. -- **Locked balance**: Portions of the free balance that cannot be spent or transferred because they are tied up in specific activities like [staking](https://wiki.polkadot.com/learn/learn-staking/#nominating-validators){target=\_blank}, [vesting](https://wiki.polkadot.com/learn/learn-guides-transfers/#vested-transfers-with-the-polkadot-js-ui){target=\_blank}, or participating in [governance](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\_blank}. While the tokens remain part of the free balance, they are non-transferable for the duration of the lock. -- **Reserved balance**: Funds locked by specific system actions, such as setting up an [identity](https://wiki.polkadot.com/learn/learn-identity/){target=\_blank}, creating [proxies](https://wiki.polkadot.com/learn/learn-proxies/){target=\_blank}, or submitting [deposits for governance proposals](https://wiki.polkadot.com/learn/learn-guides-polkadot-opengov/#claiming-opengov-deposits){target=\_blank}. These tokens are not part of the free balance and cannot be spent unless they are unreserved. -- **Spendable balance**: The portion of the free balance that is available for immediate spending or transfers. It is calculated by subtracting the maximum of locked or reserved amounts from the free balance, ensuring that existential deposit limits are met. -- **Untouchable balance**: Funds that cannot be directly spent or transferred but may still be utilized for on-chain activities, such as governance participation or staking. These tokens are typically tied to certain actions or locked for a specific period. - -The spendable balance is calculated as follows: - -```text -spendable = free - max(locked - reserved, ED) -``` - -Here, `free`, `locked`, and `reserved` are defined above. The `ED` represents the [existential deposit](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\_blank}, the minimum balance required to keep an account active and prevent it from being reaped. You may find you can't see all balance types when looking at your account via a wallet. Wallet providers often display only spendable, locked, and reserved balances. - -### Locks - -Locks are applied to an account's free balance, preventing that portion from being spent or transferred. Locks are automatically placed when an account participates in specific on-chain activities, such as staking or governance. Although multiple locks may be applied simultaneously, they do not stack. Instead, the largest lock determines the total amount of locked tokens. - -Locks follow these basic rules: - -- If different locks apply to varying amounts, the largest lock amount takes precedence. -- If multiple locks apply to the same amount, the lock with the longest duration governs when the balance can be unlocked. - -#### Locks Example - -Consider an example where an account has 80 DOT locked for both staking and governance purposes like so: - -- 80 DOT is staked with a 28-day lock period. -- 24 DOT is locked for governance with a 1x conviction and a 7-day lock period. -- 4 DOT is locked for governance with a 6x conviction and a 224-day lock period. - -In this case, the total locked amount is 80 DOT because only the largest lock (80 DOT from staking) governs the locked balance. These 80 DOT will be released at different times based on the lock durations. In this example, the 24 DOT locked for governance will be released first since the shortest lock period is seven days. The 80 DOT stake with a 28-day lock period is released next. Now, all that remains locked is the 4 DOT for governance. After 224 days, all 80 DOT (minus the existential deposit) will be free and transferable. - -![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp) - -#### Edge Cases for Locks - -In scenarios where multiple convictions and lock periods are active, the lock duration and amount are determined by the longest period and largest amount. For example, if you delegate with different convictions and attempt to undelegate during an active lock period, the lock may be extended for the full amount of tokens. For a detailed discussion on edge case lock behavior, see this [Stack Exchange post](https://substrate.stackexchange.com/questions/5067/delegating-and-undelegating-during-the-lock-period-extends-it-for-the-initial-am){target=\_blank}. - -### Balance Types on Polkadot.js - -Polkadot.js provides a user-friendly interface for managing and visualizing various account balances on Polkadot and Kusama networks. When interacting with Polkadot.js, you will encounter multiple balance types that are critical for understanding how your funds are distributed and restricted. This section explains how different balances are displayed in the Polkadot.js UI and what each type represents. - -![](/images/reference/parachains/accounts/accounts-02.webp) - -The most common balance types displayed on Polkadot.js are: - -- **Total balance**: The total number of tokens available in the account. This includes all tokens, whether they are transferable, locked, reserved, or vested. However, the total balance does not always reflect what can be spent immediately. In this example, the total balance is 0.6274 KSM. - -- **Transferable balance**: Shows how many tokens are immediately available for transfer. It is calculated by subtracting the locked and reserved balances from the total balance. For example, if an account has a total balance of 0.6274 KSM and a transferable balance of 0.0106 KSM, only the latter amount can be sent or spent freely. - -- **Vested balance**: Tokens that allocated to the account but released according to a specific schedule. Vested tokens remain locked and cannot be transferred until fully vested. For example, an account with a vested balance of 0.2500 KSM means that this amount is owned but not yet transferable. - -- **Locked balance**: Tokens that are temporarily restricted from being transferred or spent. These locks typically result from participating in staking, governance, or vested transfers. In Polkadot.js, locked balances do not stack—only the largest lock is applied. For instance, if an account has 0.5500 KSM locked for governance and staking, the locked balance would display 0.5500 KSM, not the sum of all locked amounts. - -- **Reserved balance**: Refers to tokens locked for specific on-chain actions, such as setting an identity, creating a proxy, or making governance deposits. Reserved tokens are not part of the free balance, but can be freed by performing certain actions. For example, removing an identity would unreserve those funds. - -- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period. - -- **Redeemable balance**: The number of tokens that have completed the unbonding period and are ready to be unlocked and transferred again. For example, if an account has a redeemable balance of 0.1000 KSM, those tokens are now available for spending. - -- **Democracy balance**: Reflects the number of tokens locked for governance activities, such as voting on referenda. These tokens are locked for the duration of the governance action and are only released after the lock period ends. - -By understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively. - -## Address Formats - -The SS58 address format is a core component of the Polkadot SDK that enables accounts to be uniquely identified across Polkadot-based networks. This format is a modified version of Bitcoin's Base58Check encoding, specifically designed to accommodate the multi-chain nature of the Polkadot ecosystem. SS58 encoding allows each chain to define its own set of addresses while maintaining compatibility and checksum validation for security. - -### Basic Format - -SS58 addresses consist of three main components: - -```text -base58encode(concat(,
    , )) -``` - -- **Address type**: A byte or set of bytes that define the network (or chain) for which the address is intended. This ensures that addresses are unique across different Polkadot SDK-based chains. -- **Address**: The public key of the account encoded as bytes. -- **Checksum**: A hash-based checksum which ensures that addresses are valid and unaltered. The checksum is derived from the concatenated address type and address components, ensuring integrity. - -The encoding process transforms the concatenated components into a Base58 string, providing a compact and human-readable format that avoids easily confused characters (e.g., zero '0', capital 'O', lowercase 'l'). This encoding function ([`encode`](https://docs.rs/bs58/latest/bs58/fn.encode.html){target=\_blank}) is implemented exactly as defined in Bitcoin and IPFS specifications, using the same alphabet as both implementations. - -For more details about the SS58 address format implementation, see the [`Ss58Codec`](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Ss58Codec.html){target=\_blank} trait in the Rust Docs. - -### Address Type - -The address type defines how an address is interpreted and to which network it belongs. Polkadot SDK uses different prefixes to distinguish between various chains and address formats: - -- **Address types `0-63`**: Simple addresses, commonly used for network identifiers. -- **Address types `64-127`**: Full addresses that support a wider range of network identifiers. -- **Address types `128-255`**: Reserved for future address format extensions. - -For example, Polkadot’s main network uses an address type of 0, while Kusama uses 2. This ensures that addresses can be used without confusion between networks. - -The address type is always encoded as part of the SS58 address, making it easy to quickly identify the network. Refer to the [SS58 registry](https://github.com/paritytech/ss58-registry){target=\_blank} for the canonical listing of all address type identifiers and how they map to Polkadot SDK-based networks. - -### Address Length - -SS58 addresses can have different lengths depending on the specific format. Address lengths range from as short as 3 to 35 bytes, depending on the complexity of the address and network requirements. This flexibility allows SS58 addresses to adapt to different chains while providing a secure encoding mechanism. - -| Total | Type | Raw account | Checksum | -|-------|------|-------------|----------| -| 3 | 1 | 1 | 1 | -| 4 | 1 | 2 | 1 | -| 5 | 1 | 2 | 2 | -| 6 | 1 | 4 | 1 | -| 7 | 1 | 4 | 2 | -| 8 | 1 | 4 | 3 | -| 9 | 1 | 4 | 4 | -| 10 | 1 | 8 | 1 | -| 11 | 1 | 8 | 2 | -| 12 | 1 | 8 | 3 | -| 13 | 1 | 8 | 4 | -| 14 | 1 | 8 | 5 | -| 15 | 1 | 8 | 6 | -| 16 | 1 | 8 | 7 | -| 17 | 1 | 8 | 8 | -| 35 | 1 | 32 | 2 | - -SS58 addresses also support different payload sizes, allowing a flexible range of account identifiers. - -### Checksum Types - -A checksum is applied to validate SS58 addresses. Polkadot SDK uses a Blake2b-512 hash function to calculate the checksum, which is appended to the address before encoding. The checksum length can vary depending on the address format (e.g., 1-byte, 2-byte, or longer), providing varying levels of validation strength. - -The checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management. - -### Validating Addresses - -SS58 addresses can be validated using the subkey command-line interface or the Polkadot.js API. These tools help ensure an address is correctly formatted and valid for the intended network. The following sections will provide an overview of how validation works with these tools. - -#### Using Subkey - -[Subkey](https://paritytech.github.io/polkadot-sdk/master/subkey/index.html){target=\_blank} is a CLI tool provided by Polkadot SDK for generating and managing keys. It can inspect and validate SS58 addresses. - -The `inspect` command gets a public key and an SS58 address from the provided secret URI. The basic syntax for the `subkey inspect` command is: - -```bash -subkey inspect [flags] [options] uri -``` - -For the `uri` command-line argument, you can specify the secret seed phrase, a hex-encoded private key, or an SS58 address. If the input is a valid address, the `subkey` program displays the corresponding hex-encoded public key, account identifier, and SS58 addresses. - -For example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following: - -```bash -subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" -``` - -The command displays output similar to the following: - -
    - subkey inspect "caution juice atom organ advance problem want pledge someone senior holiday very" - Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account: - Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849 - Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR - Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746 - SS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR -
    - -The `subkey` program assumes an address is based on a public/private key pair. If you inspect an address, the command returns the 32-byte account identifier. - -However, not all addresses in Polkadot SDK-based networks are based on keys. - -Depending on the command-line options you specify and the input you provided, the command output might also display the network for which the address has been encoded. For example: - -```bash -subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" -``` - -The command displays output similar to the following: - -
    - subkey inspect "12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU" - Public Key URI `12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU` is account: - Network ID/Version: polkadot - Public key (hex): 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Account ID: 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a - Public key (SS58): 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU - SS58 Address: 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU -
    - -#### Using Polkadot.js API - -To verify an address in JavaScript or TypeScript projects, you can use the functions built into the [Polkadot.js API](https://polkadot.js.org/docs/){target=\_blank}. For example: - -```js -// Import Polkadot.js API dependencies -const { decodeAddress, encodeAddress } = require('@polkadot/keyring'); -const { hexToU8a, isHex } = require('@polkadot/util'); - -// Specify an address to test. -const address = 'INSERT_ADDRESS_TO_TEST'; - -// Check address -const isValidSubstrateAddress = () => { - try { - encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address)); - - return true; - } catch (error) { - return false; - } -}; - -// Query result -const isValid = isValidSubstrateAddress(); -console.log(isValid); - -``` - -If the function returns `true`, the specified address is a valid address. - -#### Other SS58 Implementations - -Support for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries. - -- **Crystal**: [`wyhaines/base58.cr`](https://github.com/wyhaines/base58.cr){target=\_blank} -- **Go**: [`itering/subscan-plugin`](https://github.com/itering/subscan-plugin){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **TypeScript**: [`subsquid/squid-sdk`](https://github.com/subsquid/squid-sdk){target=\_blank} diff --git a/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md b/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md deleted file mode 100644 index 5c5a60dd1..000000000 --- a/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Blocks -description: Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/ ---- - -# Blocks - -## Introduction - -In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the network. By understanding these concepts, developers can better grasp how blockchains maintain security, consistency, and performance within the Polkadot ecosystem. - -## What is a Block? - -In the Polkadot SDK, a block is a fundamental unit that encapsulates both the header and an array of transactions. The block header includes critical metadata to ensure the integrity and sequence of the blockchain. Here's a breakdown of its components: - -- **Block height**: Indicates the number of blocks created in the chain so far. -- **Parent hash**: The hash of the previous block, providing a link to maintain the blockchain's immutability. -- **Transaction root**: Cryptographic digest summarizing all transactions in the block. -- **State root**: A cryptographic digest representing the post-execution state. -- **Digest**: Additional information that can be attached to a block, such as consensus-related messages. - -Each transaction is part of a series that is executed according to the runtime's rules. The transaction root is a cryptographic digest of this series, which prevents alterations and enables succinct verification by light clients. This verification process allows light clients to confirm whether a transaction exists in a block with only the block header, avoiding downloading the entire block. - -## Block Production - -When an authoring node is authorized to create a new block, it selects transactions from the transaction queue based on priority. This step, known as block production, relies heavily on the executive module to manage the initialization and finalization of blocks. The process is summarized as follows: - -### Initialize Block - -The block initialization process begins with a series of function calls that prepare the block for transaction execution: - -1. **Call `on_initialize`**: The executive module calls the [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} hook from the system pallet and other runtime pallets to prepare for the block's transactions. -2. **Coordinate runtime calls**: Coordinates function calls in the order defined by the transaction queue. -3. **Verify information**: Once [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\_blank} functions are executed, the executive module checks the parent hash in the block header and the trie root to verify information is consistent. - -### Finalize Block - -Once transactions are processed, the block must be finalized before being broadcast to the network. The finalization steps are as follows: - -1. **Call `on_finalize`**: The executive module calls the [`on_finalize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_finalize){target=\_blank} hooks in each pallet to ensure any remaining state updates or checks are completed before the block is sealed and published. -2. **Verify information**: The block's digest and storage root in the header are checked against the initialized block to ensure consistency. -3. **Call `on_idle`**: The [`on_idle`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_idle){target=\_blank} hook is triggered to process any remaining tasks using the leftover weight from the block. - -## Block Authoring and Import - -Once the block is finalized, it is gossiped to other nodes in the network. Nodes follow this procedure: - -1. **Receive transactions**: The authoring node collects transactions from the network. -2. **Validate**: Transactions are checked for validity. -3. **Queue**: Valid transactions are placed in the transaction pool for execution. -4. **Execute**: State changes are made as the transactions are executed. -5. **Publish**: The finalized block is broadcast to the network. - -### Block Import Queue - -After a block is published, other nodes on the network can import it into their chain state. The block import queue is part of the outer node in every Polkadot SDK-based node and ensures incoming blocks are valid before adding them to the node's state. - -In most cases, you don't need to know details about how transactions are gossiped or how other nodes on the network import blocks. The following traits are relevant, however, if you plan to write any custom consensus logic or want a deeper dive into the block import queue: - -- **[`ImportQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.ImportQueue.html){target=\_blank}**: The trait that defines the block import queue. -- **[`Link`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Link.html){target=\_blank}**: The trait that defines the link between the block import queue and the network. -- **[`BasicQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/struct.BasicQueue.html){target=\_blank}**: A basic implementation of the block import queue. -- **[`Verifier`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Verifier.html){target=\_blank}**: The trait that defines the block verifier. -- **[`BlockImport`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/block_import/trait.BlockImport.html){target=\_blank}**: The trait that defines the block import process. - -These traits govern how blocks are validated and imported across the network, ensuring consistency and security. - -## Additional Resources - -To learn more about the block structure in the Polkadot SDK runtime, see the [`Block` reference](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.Block.html){target=\_blank} entry in the Rust Docs. diff --git a/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md b/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md deleted file mode 100644 index 474cd6537..000000000 --- a/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md +++ /dev/null @@ -1,342 +0,0 @@ ---- -title: Transactions Weights and Fees -description: Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/ ---- - -# Transactions Weights and Fees - -## Introductions - -When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop the network from producing new blocks. To protect blockchain resources from being drained or overloaded, you need to manage how they are made available and how they are consumed. The resources to be aware of include: - -- Memory usage -- Storage input and output -- Computation -- Transaction and block size -- State database size - -The Polkadot SDK provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource. Two of the most important mechanisms available to block authors are weights and transaction fees. - -[Weights](/reference/glossary/#weight){target=\_blank} manage the time it takes to validate a block and characterize the time it takes to execute the calls in the block's body. By controlling the execution time a block can consume, weights set limits on storage input, output, and computation. - -Some of the weight allowed for a block is consumed as part of the block's initialization and finalization. The weight might also be used to execute mandatory inherent extrinsic calls. To help ensure blocks don’t consume too much execution time and prevent malicious users from overloading the system with unnecessary calls, weights are combined with transaction fees. - -[Transaction fees](/reference/parachains/blocks-transactions-fees/transactions/#transaction-fees){target=\_blank} provide an economic incentive to limit execution time, computation, and the number of calls required to perform operations. Transaction fees are also used to make the blockchain economically sustainable because they are typically applied to transactions initiated by users and deducted before a transaction request is executed. - -## How Fees are Calculated - -The final fee for a transaction is calculated using the following parameters: - -- **`base fee`**: This is the minimum amount a user pays for a transaction. It is declared a base weight in the runtime and converted to a fee using the [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} conversion. -- **`weight fee`**: A fee proportional to the execution time (input and output and computation) that a transaction consumes. -- **`length fee`**: A fee proportional to the encoded length of the transaction. -- **`tip`**: An optional tip to increase the transaction’s priority, giving it a higher chance to be included in the transaction queue. - -The base fee and proportional weight and length fees constitute the inclusion fee. The inclusion fee is the minimum fee that must be available for a transaction to be included in a block. - -```text -inclusion fee = base fee + weight fee + length fee -``` - -Transaction fees are withdrawn before the transaction is executed. After the transaction is executed, the weight can be adjusted to reflect the resources used. If a transaction uses fewer resources than expected, the transaction fee is corrected, and the adjusted transaction fee is deposited. - -## Using the Transaction Payment Pallet - -The [Transaction Payment pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/transaction-payment){target=\_blank} provides the basic logic for calculating the inclusion fee. You can also use the Transaction Payment pallet to: - -- Convert a weight value into a deductible fee based on a currency type using [`Config::WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank}. -- Update the fee for the next block by defining a multiplier based on the chain’s final state at the end of the previous block using [`Config::FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank}. -- Manage the withdrawal, refund, and deposit of transaction fees using [`Config::OnChargeTransaction`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.OnChargeTransaction){target=\_blank}. - -You can learn more about these configuration traits in the [Transaction Payment documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_payment/index.html){target=\_blank}. - -### Understanding the Inclusion Fee - -The formula for calculating the inclusion fee is as follows: - -```text -inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee] -``` - -And then, for calculating the final fee: - -```text -final_fee = inclusion_fee + tip -``` - -In the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion. - -- The `base_fee` derived from the base weight covers inclusion overhead like signature verification. -- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic. -- The `weight_fee` fee is calculated using two parameters: - - The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics. - - The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity. - -To convert the weight to `Currency`, the runtime must define a `WeightToFee` struct that implements a conversion function, [`Convert`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/struct.Pallet.html#method.weight_to_fee){target=\_blank}. - -Note that the extrinsic sender is charged the inclusion fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution. - -### Accounts with an Insufficient Balance - -If an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum existential deposit—then you should ensure the transaction is canceled so that no fee is deducted and the transaction does not begin execution. - -The Polkadot SDK doesn't enforce this rollback behavior. However, this scenario would be rare because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block. - -### Fee Multipliers - -The inclusion fee formula always results in the same fee for the same input. However, weight can be dynamic and—based on how [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\_blank} is defined—the final fee can include some degree of variability. -The Transaction Payment pallet provides the [`FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\_blank} configurable parameter to account for this variability. - -The Polkadot network inspires the default update function and implements a targeted adjustment in which a target saturation level of block weight is defined. If the previous block is more saturated, the fees increase slightly. Similarly, if the last block has fewer transactions than the target, fees are decreased by a small amount. For more information about fee multiplier adjustments, see the [Web3 Research Page](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank}. - -## Transactions with Special Requirements - -Inclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example: - -- Bonds are a type of fee that might be returned or slashed after some on-chain event. For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior. -- Deposits are fees that might be returned later. For example, you might require users to pay a deposit to execute an operation that uses storage. The user’s deposit could be returned if a subsequent operation frees up storage. -- Burn operations are used to pay for a transaction based on its internal logic. For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased state size. -- Limits enable you to enforce constant or configurable limits on specific operations. For example, the default [Staking pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/staking){target=\_blank} only allows nominators to nominate 16 validators to limit the complexity of the validator election process. - -It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee. - -## Default Weight Annotations - -All dispatchable functions in the Polkadot SDK must specify a weight. The way of doing that is using the annotation-based system that lets you combine fixed values for database read/write weight and/or fixed values based on benchmarks. The most basic example would look like this: - -```rust -#[pallet::weight(100_000)] -fn my_dispatchable() { - // ... -} -``` - -Note that the [`ExtrinsicBaseWeight`](https://crates.parity.io/frame_support/weights/constants/struct.ExtrinsicBaseWeight.html){target=\_blank} is automatically added to the declared weight to account for the costs of simply including an empty extrinsic into a block. - -### Weights and Database Read/Write Operations - -To make weight annotations independent of the deployed database backend, they are defined as a constant and then used in the annotations when expressing database accesses performed by the dispatchable: - -```rust -#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)] -fn my_dispatchable() { - // ... -} -``` - -This dispatchable allows one database to read and two to write, in addition to other things that add the additional 20,000. Database access is generally every time a value declared inside the [`#[pallet::storage]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\_blank} block is accessed. However, unique accesses are counted because after a value is accessed, it is cached, and reaccessing it does not result in a database operation. That is: - -- Multiple reads of the exact value count as one read. -- Multiple writes of the exact value count as one write. -- Multiple reads of the same value, followed by a write to that value, count as one read and one write. -- A write followed by a read-only counts as one write. - -### Dispatch Classes - -Dispatches are broken into three classes: - -- Normal -- Operational -- Mandatory - -If a dispatch is not defined as `Operational` or `Mandatory` in the weight annotation, the dispatch is identified as `Normal` by default. You can specify that the dispatchable uses another class like this: - -```rust -#[pallet::dispatch((DispatchClass::Operational))] -fn my_dispatchable() { - // ... -} -``` - -This tuple notation also allows you to specify a final argument determining whether the user is charged based on the annotated weight. If you don't specify otherwise, `Pays::Yes` is assumed: - -```rust -#[pallet::dispatch(DispatchClass::Normal, Pays::No)] -fn my_dispatchable() { - // ... -} -``` - -#### Normal Dispatches - -Dispatches in this class represent normal user-triggered transactions. These types of dispatches only consume a portion of a block's total weight limit. For information about the maximum portion of a block that can be consumed for normal dispatches, see [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Normal dispatches are sent to the transaction pool. - -#### Operational Dispatches - -Unlike normal dispatches, which represent the usage of network capabilities, operational dispatches are those that provide network capabilities. Operational dispatches can consume the entire weight limit of a block. They are not bound by the [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\_blank}. Dispatches in this class are given maximum priority and are exempt from paying the [`length_fee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/){target=\_blank}. - -#### Mandatory Dispatches - -Mandatory dispatches are included in a block even if they cause the block to surpass its weight limit. You can only use the mandatory dispatch class for inherent transactions that the block author submits. This dispatch class is intended to represent functions in the block validation process. Because these dispatches are always included in a block regardless of the function weight, the validation process must prevent malicious nodes from abusing the function to craft valid but impossibly heavy blocks. You can typically accomplish this by ensuring that: - -- The operation performed is always light. -- The operation can only be included in a block once. - -To make it more difficult for malicious nodes to abuse mandatory dispatches, they cannot be included in blocks that return errors. This dispatch class serves the assumption that it is better to allow an overweight block to be created than not to allow any block to be created at all. - -### Dynamic Weights - -In addition to purely fixed weights and constants, the weight calculation can consider the input arguments of a dispatchable. The weight should be trivially computable from the input arguments with some basic arithmetic: - -```rust -use frame_support:: { - dispatch:: { - DispatchClass::Normal, - Pays::Yes, - }, - weights::Weight, -}; - -#[pallet::weight(FunctionOf( - |args: (&Vec,)| args.0.len().saturating_mul(10_000), - ) -] -fn handle_users(origin, calls: Vec) { - // Do something per user -} -``` - -## Post Dispatch Weight Correction - -Depending on the execution logic, a dispatchable function might consume less weight than was prescribed pre-dispatch. To correct weight, the function declares a different return type and returns its actual weight: - -```rust -#[pallet::weight(10_000 + 500_000_000)] -fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo { - let was_heavy = do_calculation(input); - - if (was_heavy) { - // None means "no correction" from the weight annotation. - Ok(None.into()) - } else { - // Return the actual weight consumed. - Ok(Some(10_000).into()) - } -} -``` - -## Custom Fees - -You can also define custom fee systems through custom weight functions or inclusion fee functions. - -### Custom Weights - -Instead of using the default weight annotations, you can create a custom weight calculation type using the weights module. The custom weight calculation type must implement the following traits: - -- [`WeighData`](https://crates.parity.io/frame_support/weights/trait.WeighData.html){target=\_blank} to determine the weight of the dispatch. -- [`ClassifyDispatch`](https://crates.parity.io/frame_support/weights/trait.ClassifyDispatch.html){target=\_blank} to determine the class of the dispatch. -- [`PaysFee`](https://crates.parity.io/frame_support/weights/trait.PaysFee.html){target=\_blank} to determine whether the sender of the dispatch pays fees. - -The Polkadot SDK then bundles the output information of the three traits into the [`DispatchInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.DispatchInfo.html){target=\_blank} struct and provides it by implementing the [`GetDispatchInfo`](https://docs.rs/frame-support/latest/frame_support/dispatch/trait.GetDispatchInfo.html){target=\_blank} for all `Call` variants and opaque extrinsic types. This is used internally by the System and Executive modules. - -`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over T, which gets resolved into the tuple of all dispatch arguments except for the origin. The following example illustrates a struct that calculates the weight as `m * len(args)`, where `m` is a given multiplier and args is the concatenated tuple of all dispatch arguments. In this example, the dispatch class is `Operational` if the transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length exceeds 10 bytes. - -```rust -struct LenWeight(u32); -impl WeighData for LenWeight { - fn weigh_data(&self, target: T) -> Weight { - let multiplier = self.0; - let encoded_len = target.encode().len() as u32; - multiplier * encoded_len - } -} - -impl ClassifyDispatch for LenWeight { - fn classify_dispatch(&self, target: T) -> DispatchClass { - let encoded_len = target.encode().len() as u32; - if encoded_len > 100 { - DispatchClass::Operational - } else { - DispatchClass::Normal - } - } -} - -impl PaysFee { - fn pays_fee(&self, target: T) -> Pays { - let encoded_len = target.encode().len() as u32; - if encoded_len > 10 { - Pays::Yes - } else { - Pays::No - } - } -} -``` - -A weight calculator function can also be coerced to the final type of the argument instead of defining it as a vague type that can be encoded. The code would roughly look like this: - -```rust -struct CustomWeight; -impl WeighData<(&u32, &u64)> for CustomWeight { - fn weigh_data(&self, target: (&u32, &u64)) -> Weight { - ... - } -} - -// given a dispatch: -#[pallet::call] -impl, I: 'static> Pallet { - #[pallet::weight(CustomWeight)] - fn foo(a: u32, b: u64) { ... } -} -``` - -In this example, the `CustomWeight` can only be used in conjunction with a dispatch with a particular signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because there aren't any assumptions about ``. - -#### Custom Inclusion Fee - -The following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module. - -```rust -// Assume this is the balance type -type Balance = u64; - -// Assume we want all the weights to have a `100 + 2 * w` conversion to fees -struct CustomWeightToFee; -impl WeightToFee for CustomWeightToFee { - fn convert(w: Weight) -> Balance { - let a = Balance::from(100); - let b = Balance::from(2); - let w = Balance::from(w); - a + b * w - } -} - -parameter_types! { - pub const ExtrinsicBaseWeight: Weight = 10_000_000; -} - -impl frame_system::Config for Runtime { - type ExtrinsicBaseWeight = ExtrinsicBaseWeight; -} - -parameter_types! { - pub const TransactionByteFee: Balance = 10; -} - -impl transaction_payment::Config { - type TransactionByteFee = TransactionByteFee; - type WeightToFee = CustomWeightToFee; - type FeeMultiplierUpdate = TargetedFeeAdjustment; -} - -struct TargetedFeeAdjustment(sp_std::marker::PhantomData); -impl> WeightToFee for TargetedFeeAdjustment { - fn convert(multiplier: Fixed128) -> Fixed128 { - // Don't change anything. Put any fee update info here. - multiplier - } -} -``` - -## Additional Resources - -You now know the weight system, how it affects transaction fee computation, and how to specify weights for your dispatchable calls. The next step is determining the correct weight for your dispatchable operations. You can use Substrate benchmarking functions and frame-benchmarking calls to test your functions with different parameters and empirically determine the proper weight in their worst-case scenarios. - -- [Benchmark](/parachains/customize-runtime/pallet-development/benchmark-pallet/) -- [`SignedExtension`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} -- [Custom weights for the Example pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/examples/basic/src/weights.rs){target=\_blank} -- [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\_blank} diff --git a/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md b/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md deleted file mode 100644 index 41d2ef16f..000000000 --- a/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md +++ /dev/null @@ -1,264 +0,0 @@ ---- -title: Transactions -description: Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/ ---- - -# Transactions - -## Introduction - -Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions. - -This guide walks you through the different transaction types and how they're formatted, validated, and processed within the Polkadot ecosystem. You'll also learn how to customize transaction formats and construct transactions for FRAME-based runtimes, ensuring a complete understanding of how transactions are built and executed in Polkadot SDK-based chains. - -## What Is a Transaction? - -In the Polkadot SDK, transactions represent operations that modify the chain's state, bundled into blocks for execution. The term extrinsic is often used to refer to any data that originates outside the runtime and is included in the chain. While other blockchain systems typically refer to these operations as "transactions," the Polkadot SDK adopts the broader term "extrinsic" to capture the wide variety of data types that can be added to a block. - -There are three primary types of transactions (extrinsics) in the Polkadot SDK: - -- **Signed transactions**: Signed by the submitting account, often carrying transaction fees. -- **Unsigned transactions**: Submitted without a signature, often requiring custom validation logic. -- **Inherent transactions**: Typically inserted directly into blocks by block authoring nodes, without gossiping between peers. - -Each type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK. - -### Signed Transactions - -Signed transactions require an account's signature and typically involve submitting a request to execute a runtime call. The signature serves as a form of cryptographic proof that the sender has authorized the action, using their private key. These transactions often involve a transaction fee to cover the cost of execution and incentivize block producers. - -Signed transactions are the most common type of transaction and are integral to user-driven actions, such as token transfers. For instance, when you transfer tokens from one account to another, the sending account must sign the transaction to authorize the operation. - -For example, the [`pallet_balances::Call::transfer_allow_death`](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/pallet/struct.Pallet.html#method.transfer_allow_death){target=\_blank} extrinsic in the Balances pallet allows you to transfer tokens. Since your account initiates this transaction, your account key is used to sign it. You'll also be responsible for paying the associated transaction fee, with the option to include an additional tip to incentivize faster inclusion in the block. - -### Unsigned Transactions - -Unsigned transactions do not require a signature or account-specific data from the sender. Unlike signed transactions, they do not come with any form of economic deterrent, such as fees, which makes them susceptible to spam or replay attacks. Custom validation logic must be implemented to mitigate these risks and ensure these transactions are secure. - -Unsigned transactions typically involve scenarios where including a fee or signature is unnecessary or counterproductive. However, due to the absence of fees, they require careful validation to protect the network. For example, [`pallet_im_online::Call::heartbeat`](https://paritytech.github.io/polkadot-sdk/master/pallet_im_online/pallet/struct.Pallet.html#method.heartbeat){target=\_blank} extrinsic allows validators to send a heartbeat signal, indicating they are active. Since only validators can make this call, the logic embedded in the transaction ensures that the sender is a validator, making the need for a signature or fee redundant. - -Unsigned transactions are more resource-intensive than signed ones because custom validation is required, but they play a crucial role in certain operational scenarios, especially when regular user accounts aren't involved. - -### Inherent Transactions - -Inherent transactions are a specialized type of unsigned transaction that is used primarily for block authoring. Unlike signed or other unsigned transactions, inherent transactions are added directly by block producers and are not broadcasted to the network or stored in the transaction queue. They don't require signatures or the usual validation steps and are generally used to insert system-critical data directly into blocks. - -A key example of an inherent transaction is inserting a timestamp into each block. The [`pallet_timestamp::Call::now`](https://paritytech.github.io/polkadot-sdk/master/pallet_timestamp/pallet/struct.Pallet.html#method.now-1){target=\_blank} extrinsic allows block authors to include the current time in the block they are producing. Since the block producer adds this information, there is no need for transaction validation, like signature verification. The validation in this case is done indirectly by the validators, who check whether the timestamp is within an acceptable range before finalizing the block. - -Another example is the [`paras_inherent::Call::enter`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/paras_inherent/pallet/struct.Pallet.html#method.enter){target=\_blank} extrinsic, which enables parachain collator nodes to send validation data to the relay chain. This inherent transaction ensures that the necessary parachain data is included in each block without the overhead of gossiped transactions. - -Inherent transactions serve a critical role in block authoring by allowing important operational data to be added directly to the chain without needing the validation processes required for standard transactions. - -## Transaction Formats - -Understanding the structure of signed and unsigned transactions is crucial for developers building on Polkadot SDK-based chains. Whether you're optimizing transaction processing, customizing formats, or interacting with the transaction pool, knowing the format of extrinsics, Polkadot's term for transactions, is essential. - -### Types of Transaction Formats - -In Polkadot SDK-based chains, extrinsics can fall into three main categories: - -- **Unchecked extrinsics**: Typically used for signed transactions that require validation. They contain a signature and additional data, such as a nonce and information for fee calculation. Unchecked extrinsics are named as such because they require validation checks before being accepted into the transaction pool. -- **Checked extrinsics**: Typically used for inherent extrinsics (unsigned transactions); these don't require signature verification. Instead, they carry information such as where the extrinsic originates and any additional data required for the block authoring process. -- **Opaque extrinsics**: Used when the format of an extrinsic is not yet fully committed or finalized. They are still decodable, but their structure can be flexible depending on the context. - -### Signed Transaction Data Structure - -A signed transaction typically includes the following components: - -- **Signature**: Verifies the authenticity of the transaction sender. -- **Call**: The actual function or method call the transaction is requesting (for example, transferring funds). -- **Nonce**: Tracks the number of prior transactions sent from the account, helping to prevent replay attacks. -- **Tip**: An optional incentive to prioritize the transaction in block inclusion. -- **Additional data**: Includes details such as spec version, block hash, and genesis hash to ensure the transaction is valid within the correct runtime and chain context. - -Here's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime: - -``` code - + + -``` - -Each part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain. - -### Signed Extensions - -Polkadot SDK also provides the concept of [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\_blank}, which allow developers to extend extrinsics with additional data or validation logic before they are included in a block. The [`SignedExtension`](https://paritytech.github.io/try-runtime-cli/sp_runtime/traits/trait.SignedExtension.html){target=\_blank} set helps enforce custom rules or protections, such as ensuring the transaction's validity or calculating priority. - -The transaction queue regularly calls signed extensions to verify a transaction's validity before placing it in the ready queue. This safeguard ensures transactions won't fail in a block. Signed extensions are commonly used to enforce validation logic and protect the transaction pool from spam and replay attacks. - -In FRAME, a signed extension can hold any of the following types by default: - -- **[`AccountId`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/types_common/type.AccountId.html){target=\_blank}**: To encode the sender's identity. -- **[`Call`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Call){target=\_blank}**: To encode the pallet call to be dispatched. This data is used to calculate transaction fees. -- **[`AdditionalSigned`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.AdditionalSigned){target=\_blank}**: To handle any additional data to go into the signed payload allowing you to attach any custom logic prior to dispatching a transaction. -- **[`Pre`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Pre){target=\_blank}**: To encode the information that can be passed from before a call is dispatched to after it gets dispatched. - -Signed extensions can enforce checks like: - -- **[`CheckSpecVersion`](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/extensions/check_spec_version.rs.html){target=\_blank}**: Ensures the transaction is compatible with the runtime's current version. -- **[`CheckWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.CheckWeight.html){target=\_blank}**: Calculates the weight (or computational cost) of the transaction, ensuring the block doesn't exceed the maximum allowed weight. - -These extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed. - -## Transaction Construction - -Building transactions in the Polkadot SDK involves constructing a payload that can be verified, signed, and submitted for inclusion in a block. Each runtime in the Polkadot SDK has its own rules for validating and executing transactions, but there are common patterns for constructing a signed transaction. - -### Construct a Signed Transaction - -A signed transaction in the Polkadot SDK includes various pieces of data to ensure security, prevent replay attacks, and prioritize processing. Here's an overview of how to construct one: - -1. **Construct the unsigned payload**: Gather the necessary information for the call, including: - - - **Pallet index**: Identifies the pallet where the runtime function resides. - - **Function index**: Specifies the particular function to call in the pallet. - - **Parameters**: Any additional arguments required by the function call. - -2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included: - - - **Transaction nonce**: Unique identifier to prevent replay attacks. - - **Era information**: Defines how long the transaction is valid before it's dropped from the pool. - - **Block hash**: Ensures the transaction doesn't execute on the wrong chain or fork. - -3. **Sign the payload**: Using the sender's private key, sign the payload to ensure that the transaction can only be executed by the account holder. -4. **Serialize the signed payload**: Once signed, the transaction must be serialized into a binary format, ensuring the data is compact and easy to transmit over the network. -5. **Submit the serialized transaction**: Finally, submit the serialized transaction to the network, where it will enter the transaction pool and wait for processing by an authoring node. - -The following is an example of how a signed transaction might look: - -``` rust -node_runtime::UncheckedExtrinsic::new_signed( - function.clone(), // some call - sp_runtime::AccountId32::from(sender.public()).into(), // some sending account - node_runtime::Signature::Sr25519(signature.clone()), // the account's signature - extra.clone(), // the signed extensions -) -``` - -### Transaction Encoding - -Before a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering: - -- **`[1]`**: Compact encoded length in bytes of the entire transaction. -- **`[2]`**: A u8 containing 1 byte to indicate whether the transaction is signed or unsigned (1 bit) and the encoded transaction version ID (7 bits). -- **`[3]`**: If signed, this field contains an account ID, an SR25519 signature, and some extra data. -- **`[4]`**: Encoded call data, including pallet and function indices and any required arguments. - -This encoded format ensures consistency and efficiency in processing transactions across the network. By adhering to this format, applications can construct valid transactions and pass them to the network for execution. - -To learn more about how compact encoding works using SCALE, see the [SCALE Codec](https://github.com/paritytech/parity-scale-codec){target=\_blank} README on GitHub. - -### Customize Transaction Construction - -Although the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example: - -- **Custom pallets**: You can define new pallets with custom function calls, each with its own parameters and validation logic. -- **Signed extensions**: Developers can implement custom extensions that modify how transactions are prioritized, validated, or included in blocks. - -By leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs. - -## Lifecycle of a Transaction - -In the Polkadot SDK, transactions are often referred to as extrinsics because the data in transactions originates outside of the runtime. These transactions contain data that initiates changes to the chain state. The most common type of extrinsic is a signed transaction, which is cryptographically verified and typically incurs a fee. This section focuses on how signed transactions are processed, validated, and ultimately included in a block. - -### Define Transaction Properties - -The Polkadot SDK runtime defines key transaction properties, such as: - -- **Transaction validity**: Ensures the transaction meets all runtime requirements. -- **Signed or unsigned**: Identifies whether a transaction needs to be signed by an account. -- **State changes**: Determines how the transaction modifies the state of the chain. - -Pallets, which compose the runtime's logic, define the specific transactions that your chain supports. When a user submits a transaction, such as a token transfer, it becomes a signed transaction, verified by the user's account signature. If the account has enough funds to cover fees, the transaction is executed, and the chain's state is updated accordingly. - -### Process on a Block Authoring Node - -In Polkadot SDK-based networks, some nodes are authorized to author blocks. These nodes validate and process transactions. When a transaction is sent to a node that can produce blocks, it undergoes a lifecycle that involves several stages, including validation and execution. Non-authoring nodes gossip the transaction across the network until an authoring node receives it. The following diagram illustrates the lifecycle of a transaction that's submitted to a network and processed by an authoring node. - -![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style="background:white" } - -### Validate and Queue - -Once a transaction reaches an authoring node, it undergoes an initial validation process to ensure it meets specific conditions defined in the runtime. This validation includes checks for: - -- **Correct nonce**: Ensures the transaction is sequentially valid for the account. -- **Sufficient funds**: Confirms the account can cover any associated transaction fees. -- **Signature validity**: Verifies that the sender's signature matches the transaction data. - -After these checks, valid transactions are placed in the transaction pool, where they are queued for inclusion in a block. The transaction pool regularly re-validates queued transactions to ensure they remain valid before being processed. To reach consensus, two-thirds of the nodes must agree on the order of the transactions executed and the resulting state change. Transactions are validated and queued on the local node in a transaction pool to prepare for consensus. - -#### Transaction Pool - -The transaction pool is responsible for managing valid transactions. It ensures that only transactions that pass initial validity checks are queued. Transactions that fail validation, expire, or become invalid for other reasons are removed from the pool. - -The transaction pool organizes transactions into two queues: - -- **Ready queue**: Transactions that are valid and ready to be included in a block. -- **Future queue**: Transactions that are not yet valid but could be in the future, such as transactions with a nonce too high for the current state. - -Details on how the transaction pool validates transactions, including fee and signature handling, can be found in the [`validate_transaction`](https://paritytech.github.io/polkadot-sdk/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction){target=\_blank} method. - -#### Invalid Transactions - -If a transaction is invalid, for example, due to an invalid signature or insufficient funds, it is rejected and won't be added to the block. Invalid transactions might be rejected for reasons such as: - -- The transaction has already been included in a block. -- The transaction's signature does not match the sender. -- The transaction is too large to fit in the current block. - -### Transaction Ordering and Priority - -When a node is selected as the next block author, it prioritizes transactions based on weight, length, and tip amount. The goal is to fill the block with high-priority transactions without exceeding its maximum size or computational limits. Transactions are ordered as follows: - -- **Inherents first**: Inherent transactions, such as block timestamp updates, are always placed first. -- **Nonce-based ordering**: Transactions from the same account are ordered by their nonce. -- **Fee-based ordering**: Among transactions with the same nonce or priority level, those with higher fees are prioritized. - -### Transaction Execution - -Once a block author selects transactions from the pool, the transactions are executed in priority order. As each transaction is processed, the state changes are written directly to the chain's storage. It's important to note that these changes are not cached, meaning a failed transaction won't revert earlier state changes, which could leave the block in an inconsistent state. - -Events are also written to storage. Runtime logic should not emit an event before performing the associated actions. If the associated transaction fails after the event was emitted, the event will not revert. - -## Transaction Mortality - -Transactions in the network can be configured as either mortal (with expiration) or immortal (without expiration). Every transaction payload contains a block checkpoint (reference block number and hash) and an era/validity period that determines how many blocks after the checkpoint the transaction remains valid. - -When a transaction is submitted, the network validates it against these parameters. If the transaction is not included in a block within the specified validity window, it is automatically removed from the transaction queue. - -- **Mortal transactions**: Have a finite lifespan and will expire after a specified number of blocks. For example, a transaction with a block checkpoint of 1000 and a validity period of 64 blocks will be valid from blocks 1000 to 1064. - -- **Immortal transactions**: Never expire and remain valid indefinitely. To create an immortal transaction, set the block checkpoint to 0 (genesis block), use the genesis hash as a reference, and set the validity period to 0. - -However, immortal transactions pose significant security risks through replay attacks. If an account is reaped (balance drops to zero, account removed) and later re-funded, malicious actors can replay old immortal transactions. - -The blockchain maintains only a limited number of prior block hashes for reference validation, called `BlockHashCount`. If your validity period exceeds `BlockHashCount`, the effective validity period becomes the minimum of your specified period and the block hash count. - -## Unique Identifiers for Extrinsics - -Transaction hashes are **not unique identifiers** in Polkadot SDK-based chains. - -Key differences from traditional blockchains: - -- Transaction hashes serve only as fingerprints of transaction information. -- Multiple valid transactions can share the same hash. -- Hash uniqueness assumptions lead to serious issues. - -For example, when an account is reaped (removed due to insufficient balance) and later recreated, it resets to nonce 0, allowing identical transactions to be valid at different points: - -| Block | Extrinsic Index | Hash | Origin | Nonce | Call | Result | -|-------|----------------|------|-----------|-------|---------------------|-------------------------------| -| 100 | 0 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Account A reaped | -| 150 | 5 | 0x02 | Account B | 4 | Transfer 7 DOT to A | Account A created (nonce = 0) | -| 200 | 2 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Successful transaction | - -Notice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times. - -Additional complexity comes from Polkadot SDK's origin abstraction. Origins can represent collectives, governance bodies, or other non-account entities that don't maintain nonces like regular accounts and might dispatch identical calls multiple times with the same hash values. Each execution occurs in different chain states with different results. - -The correct way to uniquely identify an extrinsic on a Polkadot SDK-based chain is to use the block ID (height or hash) and the extrinsic index. Since the Polkadot SDK defines blocks as headers plus ordered arrays of extrinsics, the index position within a canonical block provides guaranteed uniqueness. - -## Additional Resources - -For a video overview of the lifecycle of transactions and the types of transactions that exist, see the [Transaction lifecycle](https://www.youtube.com/watch?v=3pfM0GOp02c){target=\_blank} seminar from Parity Tech. diff --git a/.ai/pages/reference-parachains-chain-data.md b/.ai/pages/reference-parachains-chain-data.md deleted file mode 100644 index dd62f40aa..000000000 --- a/.ai/pages/reference-parachains-chain-data.md +++ /dev/null @@ -1,356 +0,0 @@ ---- -title: Chain Data -description: Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/chain-data/ ---- - -# Chain Data - -## Introduction - -Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you can ensure seamless communication between your applications and the blockchain. - -## Application Development - -You might not be directly involved in building frontend applications as a blockchain developer. However, most applications that run on a blockchain require some form of frontend or user-facing client to enable users or other programs to access and modify the data that the blockchain stores. For example, you might develop a browser-based, mobile, or desktop application that allows users to submit transactions, post articles, view their assets, or track previous activity. The backend for that application is configured in the runtime logic for your blockchain, but the frontend client makes the runtime features accessible to your users. - -For your custom chain to be useful to others, you'll need to provide a client application that allows users to view, interact with, or update information that the blockchain keeps track of. In this article, you'll learn how to expose information about your runtime so that client applications can use it, see examples of the information exposed, and explore tools and libraries that use it. - -## Understand Metadata - -Polkadot SDK-based blockchain networks are designed to expose their runtime information, allowing developers to learn granular details regarding pallets, RPC calls, and runtime APIs. The metadata also exposes their related documentation. The chain's metadata is [SCALE-encoded](/reference/parachains/data-encoding/){target=\_blank}, allowing for the development of browser-based, mobile, or desktop applications to support the chain's runtime upgrades seamlessly. It is also possible to develop applications compatible with multiple Polkadot SDK-based chains simultaneously. - -## Expose Runtime Information as Metadata - -To interact with a node or the state of the blockchain, you need to know how to connect to the chain and access the exposed runtime features. This interaction involves a Remote Procedure Call (RPC) through a node endpoint address, commonly through a secure web socket connection. - -An application developer typically needs to know the contents of the runtime logic, including the following details: - -- Version of the runtime the application is connecting to. -- Supported APIs. -- Implemented pallets. -- Defined functions and corresponding type signatures. -- Defined custom types. -- Exposed parameters users can set. - -As the Polkadot SDK is modular and provides a composable framework for building blockchains, there are limitless opportunities to customize the schema of properties. Each runtime can be configured with its properties, including function calls and types, which can be changed over time with runtime upgrades. - -The Polkadot SDK enables you to generate the runtime metadata schema to capture information unique to a runtime. The metadata for a runtime describes the pallets in use and types defined for a specific runtime version. The metadata includes information about each pallet's storage items, functions, events, errors, and constants. The metadata also provides type definitions for any custom types included in the runtime. - -Metadata provides a complete inventory of a chain's runtime. It is key to enabling client applications to interact with the node, parse responses, and correctly format message payloads sent back to that chain. - -## Generate Metadata - -To efficiently use the blockchain's networking resources and minimize the data transmitted over the network, the metadata schema is encoded using the [Parity SCALE Codec](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank}. This encoding is done automatically through the [`scale-info`](https://docs.rs/scale-info/latest/scale_info/){target=\_blank}crate. - -At a high level, generating the metadata involves the following steps: - -1. The pallets in the runtime logic expose callable functions, types, parameters, and documentation that need to be encoded in the metadata. -2. The `scale-info` crate collects type information for the pallets in the runtime, builds a registry of the pallets that exist in a particular runtime, and the relevant types for each pallet in the registry. The type information is detailed enough to enable encoding and decoding for every type. -3. The [`frame-metadata`](https://github.com/paritytech/frame-metadata){target=\_blank} crate describes the structure of the runtime based on the registry provided by the `scale-info` crate. -4. Nodes provide the RPC method `state_getMetadata` to return a complete description of all the types in the current runtime as a hex-encoded vector of SCALE-encoded bytes. - -## Retrieve Runtime Metadata - -The type information provided by the metadata enables applications to communicate with nodes using different runtime versions and across chains that expose different calls, events, types, and storage items. The metadata also allows libraries to generate a substantial portion of the code needed to communicate with a given node, enabling libraries like [`subxt`](https://github.com/paritytech/subxt){target=\_blank} to generate frontend interfaces that are specific to a target chain. - -### Use Polkadot.js - -Visit the [Polkadot.js Portal](https://polkadot.js.org/apps/#/rpc){target=\_blank} and select the **Developer** dropdown in the top banner. Select **RPC Calls** to make the call to request metadata. Follow these steps to make the RPC call: - -1. Select **state** as the endpoint to call. -2. Select **`getMetadata(at)`** as the method to call. -3. Click **Submit RPC call** to submit the call and return the metadata in JSON format. - -### Use Curl - -You can fetch the metadata for the network by calling the node's RPC endpoint. This request returns the metadata in bytes rather than human-readable JSON: - -```sh -curl -H "Content-Type: application/json" \ --d '{"id":1, "jsonrpc":"2.0", "method": "state_getMetadata"}' \ -https://rpc.polkadot.io - -``` - -### Use Subxt - -[`subxt`](https://github.com/paritytech/subxt){target=\_blank} may also be used to fetch the metadata of any data in a human-readable JSON format: - -```sh -subxt metadata --url wss://rpc.polkadot.io --format json > spec.json -``` - -Another option is to use the [`subxt` explorer web UI](https://paritytech.github.io/subxt-explorer/#/){target=\_blank}. - -## Client Applications and Metadata - -The metadata exposes the expected way to decode each type, meaning applications can send, retrieve, and process application information without manual encoding and decoding. Client applications must use the [SCALE codec library](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\_blank} to encode and decode RPC payloads to use the metadata. Client applications use the metadata to interact with the node, parse responses, and format message payloads sent to the node. - -## Metadata Format - -Although the SCALE-encoded bytes can be decoded using the `frame-metadata` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} libraries, there are other tools, such as `subxt` and the Polkadot-JS API, that can convert the raw data to human-readable JSON format. - -The types and type definitions included in the metadata returned by the `state_getMetadata` RPC call depend on the runtime's metadata version. - -In general, the metadata includes the following information: - -- A constant identifying the file as containing metadata. -- The version of the metadata format used in the runtime. -- Type definitions for all types used in the runtime and generated by the `scale-info` crate. -- Pallet information for the pallets included in the runtime in the order that they are defined in the `construct_runtime` macro. - -!!!tip - Depending on the frontend library used (such as the [Polkadot API](https://papi.how/){target=\_blank}), they may format the metadata differently than the raw format shown. - -The following example illustrates a condensed and annotated section of metadata decoded and converted to JSON: - -```json -[ - 1635018093, - { - "V14": { - "types": { - "types": [{}] - }, - "pallets": [{}], - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [{}] - }, - "ty": 141 - } - } -] - -``` - -The constant `1635018093` is a magic number that identifies the file as a metadata file. The rest of the metadata is divided into the `types`, `pallets`, and `extrinsic` sections: - -- The `types` section contains an index of the types and information about each type's type signature. -- The `pallets` section contains information about each pallet in the runtime. -- The `extrinsic` section describes the type identifier and transaction format version that the runtime uses. - -Different extrinsic versions can have varying formats, especially when considering [signed transactions](/reference/parachains/blocks-transactions-fees/transactions/#signed-transactions){target=\_blank}. - -### Pallets - -The following is a condensed and annotated example of metadata for a single element in the `pallets` array (the [`sudo`](https://paritytech.github.io/polkadot-sdk/master/pallet_sudo/index.html){target=\_blank} pallet): - -```json -{ - "name": "Sudo", - "storage": { - "prefix": "Sudo", - "entries": [ - { - "name": "Key", - "modifier": "Optional", - "ty": { - "Plain": 0 - }, - "default": [0], - "docs": ["The `AccountId` of the sudo key."] - } - ] - }, - "calls": { - "ty": 117 - }, - "event": { - "ty": 42 - }, - "constants": [], - "error": { - "ty": 124 - }, - "index": 8 -} - -``` - -Every element metadata contains the name of the pallet it represents and information about its storage, calls, events, and errors. You can look up details about the definition of the calls, events, and errors by viewing the type index identifier. The type index identifier is the `u32` integer used to access the type information for that item. For example, the type index identifier for calls in the Sudo pallet is 117. If you view information for that type identifier in the `types` section of the metadata, it provides information about the available calls, including the documentation for each call. - -For example, the following is a condensed excerpt of the calls for the Sudo pallet: - -```json -{ - "id": 117, - "type": { - "path": ["pallet_sudo", "pallet", "Call"], - "params": [ - { - "name": "T", - "type": null - } - ], - "def": { - "variant": { - "variants": [ - { - "name": "sudo", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 0, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "sudo_unchecked_weight", - "fields": [ - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - }, - { - "name": "weight", - "type": 8, - "typeName": "Weight" - } - ], - "index": 1, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Root` origin" - ] - }, - { - "name": "set_key", - "fields": [ - { - "name": "new", - "type": 103, - "typeName": "AccountIdLookupOf" - } - ], - "index": 2, - "docs": [ - "Authenticates current sudo key, sets the given AccountId (`new`) as the new sudo" - ] - }, - { - "name": "sudo_as", - "fields": [ - { - "name": "who", - "type": 103, - "typeName": "AccountIdLookupOf" - }, - { - "name": "call", - "type": 114, - "typeName": "Box<::RuntimeCall>" - } - ], - "index": 3, - "docs": [ - "Authenticates sudo key, dispatches a function call with `Signed` origin from a given account" - ] - } - ] - } - } - } -} - -``` - -For each field, you can access type information and metadata for the following: - -- **Storage metadata**: Provides the information required to enable applications to get information for specific storage items. -- **Call metadata**: Includes information about the runtime calls defined by the `#[pallet]` macro including call names, arguments and documentation. -- **Event metadata**: Provides the metadata generated by the `#[pallet::event]` macro, including the name, arguments, and documentation for each pallet event. -- **Constants metadata**: Provides metadata generated by the `#[pallet::constant]` macro, including the name, type, and hex-encoded value of the constant. -- **Error metadata**: Provides metadata generated by the `#[pallet::error]` macro, including the name and documentation for each pallet error. - -!!!tip - Type identifiers change from time to time, so you should avoid relying on specific type identifiers in your applications. - -### Extrinsic - -The runtime generates extrinsic metadata and provides useful information about transaction format. When decoded, the metadata contains the transaction version and the list of signed extensions. - -For example: - -```json -{ - "extrinsic": { - "ty": 126, - "version": 4, - "signed_extensions": [ - { - "identifier": "CheckNonZeroSender", - "ty": 132, - "additional_signed": 41 - }, - { - "identifier": "CheckSpecVersion", - "ty": 133, - "additional_signed": 4 - }, - { - "identifier": "CheckTxVersion", - "ty": 134, - "additional_signed": 4 - }, - { - "identifier": "CheckGenesis", - "ty": 135, - "additional_signed": 11 - }, - { - "identifier": "CheckMortality", - "ty": 136, - "additional_signed": 11 - }, - { - "identifier": "CheckNonce", - "ty": 138, - "additional_signed": 41 - }, - { - "identifier": "CheckWeight", - "ty": 139, - "additional_signed": 41 - }, - { - "identifier": "ChargeTransactionPayment", - "ty": 140, - "additional_signed": 41 - } - ] - }, - "ty": 141 -} - -``` - -The type system is [composite](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\_blank}, meaning each type identifier contains a reference to a specific type or to another type identifier that provides information about the associated primitive types. - -For example, you can encode the `BitVec` type, but to decode it properly, you must know the types used for the `Order` and `Store` types. To find type information for `Order` and `Store`, you can use the path in the decoded JSON to locate their type identifiers. - -## Included RPC APIs - -A standard node comes with the following APIs to interact with a node: - -- **[`AuthorApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/author/trait.AuthorApiServer.html){target=\_blank}**: Make calls into a full node, including authoring extrinsics and verifying session keys. -- **[`ChainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/chain/trait.ChainApiServer.html){target=\_blank}**: Retrieve block header and finality information. -- **[`OffchainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/offchain/trait.OffchainApiServer.html){target=\_blank}**: Make RPC calls for off-chain workers. -- **[`StateApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/state/trait.StateApiServer.html){target=\_blank}**: Query information about on-chain state such as runtime version, storage items, and proofs. -- **[`SystemApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/system/trait.SystemApiServer.html){target=\_blank}**: Retrieve information about network state, such as connected peers and node roles. - -## Additional Resources - -The following tools can help you locate and decode metadata: - -- [Subxt Explorer](https://paritytech.github.io/subxt-explorer/#/){target=\_blank} -- [Metadata Portal 🌗](https://github.com/paritytech/metadata-portal){target=\_blank} -- [De[code] Sub[strate]](https://github.com/paritytech/desub){target=\_blank} diff --git a/.ai/pages/reference-parachains-consensus-async-backing.md b/.ai/pages/reference-parachains-consensus-async-backing.md deleted file mode 100644 index adabf852a..000000000 --- a/.ai/pages/reference-parachains-consensus-async-backing.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/reference/parachains/consensus/async-backing/ ---- - -TODO diff --git a/.ai/pages/reference-parachains-consensus-elastic-scaling.md b/.ai/pages/reference-parachains-consensus-elastic-scaling.md deleted file mode 100644 index c826d5b68..000000000 --- a/.ai/pages/reference-parachains-consensus-elastic-scaling.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Elastic Scaling -description: Learn how elastic scaling in Polkadot boosts parachain throughput, reduces latency, and supports dynamic, cost-efficient resource allocation. -categories: Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/consensus/elastic-scaling/ ---- - -# Elastic Scaling - -## Introduction - -Polkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains. - -Elastic scaling enhances this architecture by allowing parachains to utilize multiple computational cores simultaneously, breaking the previous 1:1 relationship between parachain and relay chain blocks. - -This technical advancement enables parachains to process multiple blocks within a single relay chain block, significantly increasing throughput capabilities. By leveraging [Agile Coretime](/polkadot-protocol/architecture/polkadot-chain/agile-coretime){target=\_blank}, parachains can dynamically adjust their processing capacity based on demand, creating an efficient and responsive infrastructure for high-throughput applications. - -## How Elastic Scaling Works - -Elastic scaling enables parachains to process multiple blocks in parallel by utilizing additional cores on the relay chain. This section provides a technical analysis of the performance advantages and details of the implementation. - -Consider a parachain that needs to process four consecutive parablocks. With traditional single-core allocation, the validation process follows a strictly sequential pattern. Each parablock undergoes a two-phase process on the relay chain: - -1. **Backing phase**: Validators create and distribute validity statements. -2. **Inclusion phase**: The parablock is included in the relay chain after availability verification. - -Throughout the following diagrams, specific notation is used to represent different components of the system: - -- **R1, R2, ...**: Relay chain blocks (produced at ~6-second intervals). -- **P1, P2, ...**: Parachain blocks that need validation and inclusion. -- **C1, C2, ...**: Cores on the relay chain. - -In the single-core scenario (assuming a 6-second relay chain block time), processing four parablocks requires approximately 30 seconds: - -```mermaid -sequenceDiagram - participant R1 as R1 - participant R2 as R2 - participant R3 as R3 - participant R4 as R4 - participant R5 as R5 - - Note over R1,R5: Single Core Scenario - - rect rgb(200, 220, 240) - Note right of R1: Core C1 - R1->>R1: Back P1 - R2->>R2: Include P1 - R2->>R2: Back P2 - R3->>R3: Include P2 - R3->>R3: Back P3 - R4->>R4: Include P3 - R4->>R4: Back P4 - R5->>R5: Include P4 - end -``` - -With elastic scaling utilizing two cores simultaneously, the same four parablocks can be processed in approximately 18 seconds: - -```mermaid -sequenceDiagram - participant R1 as R1 - participant R2 as R2 - participant R3 as R3 - participant R4 as R4 - participant R5 as R5 - - Note over R1,R3: Multi-Core Scenario - - rect rgb(200, 220, 240) - Note right of R1: Core C1 - R1->>R1: Back P1 - R2->>R2: Include P1 - R2->>R2: Back P2 - R3->>R3: Include P2 - end - - rect rgb(220, 200, 240) - Note right of R1: Core C2 - R1->>R1: Back P3 - R2->>R2: Include P3 - R2->>R2: Back P4 - R3->>R3: Include P4 - end -``` - -To help interpret the sequence diagrams above, note the following key elements: - -- The horizontal axis represents time progression through relay chain blocks (R1-R5). -- Each colored rectangle shows processing on a specific core (C1 or C2). -- In the single-core scenario, all blocks must be processed sequentially on one core. -- In the multi-core scenario, blocks are processed in parallel across multiple cores, reducing total time. - -The relay chain processes these multiple parablocks as independent validation units during the backing, availability, and approval phases. However, during inclusion, it verifies that their state roots align properly to maintain chain consistency. - -From an implementation perspective: - -- **Parachain side**: Collators must increase their block production rate to utilize multiple cores fully. -- **Validation process**: Each core operates independently, but with coordinated state verification. -- **Resource management**: Cores are dynamically allocated based on parachain requirements. -- **State consistency**: While backed and processed in parallel, the parablocks maintain sequential state transitions. - -## Benefits of Elastic Scaling - -- **Increased throughput**: Multiple concurrent cores enable parachains to process transactions at multiples of their previous capacity. By allowing multiple parachain blocks to be validated within each relay chain block cycle, applications can achieve significantly higher transaction volumes. - -- **Lower latency**: Transaction finality improves substantially with multi-core processing. Parachains currently achieve 2-second latency with three cores, with projected improvements to 500ms using 12 cores, enabling near-real-time application responsiveness. - -- **Resource efficiency**: Applications acquire computational resources precisely matched to their needs, eliminating wasteful over-provisioning. Coretime can be purchased at granular intervals (blocks, hours, days), creating cost-effective operations, particularly for applications with variable transaction patterns. - -- **Scalable growth**: New applications can launch with minimal initial resource commitment and scale dynamically as adoption increases. This eliminates the traditional paradox of either over-allocating resources (increasing costs) or under-allocating (degrading performance) during growth phases. - -- **Workload distribution**: Parachains intelligently distribute workloads across cores during peak demand periods and release resources when traffic subsides. Paired with secondary coretime markets, this ensures maximum resource utilization across the entire network ecosystem. - -- **Reliable performance**: End-users experience reliable application performance regardless of network congestion levels. Applications maintain responsiveness even during traffic spikes, eliminating performance degradation that commonly impacts blockchain applications during high-demand periods. - -## Use Cases - -Elastic scaling enables applications to dynamically adjust their resource consumption based on real-time demand. This is especially valuable for decentralized applications where usage patterns can be highly variable. The following examples illustrate common scenarios where elastic scaling delivers significant performance and cost-efficiency benefits. - -### Handling Sudden Traffic Spikes - -Many decentralized applications experience unpredictable, high-volume traffic bursts, especially in gaming, DeFi protocols, NFT auctions, messaging platforms, and social media. Elastic scaling allows these systems to acquire additional coretime during peak usage and release it during quieter periods, ensuring responsiveness without incurring constant high infrastructure costs. - -### Supporting Early-Stage Growth - -Startups and new projects often begin with uncertain or volatile demand. With elastic scaling, teams can launch with minimal compute resources (e.g., a single core) and gradually scale as adoption increases. This prevents overprovisioning and enables cost-efficient growth until the application is ready for more permanent or horizontal scaling. - -### Scaling Massive IoT Networks - -Internet of Things (IoT) applications often involve processing data from millions of devices in real time. Elastic scaling supports this need by enabling high-throughput transaction processing as demand fluctuates. Combined with Polkadot’s shared security model, it provides a reliable and privacy-preserving foundation for large-scale IoT deployments. - -### Powering Real-Time, Low-Latency Systems - -Applications like payment processors, trading platforms, gaming engines, or real-time data feeds require fast, consistent performance. Elastic scaling can reduce execution latency during demand spikes, helping ensure low-latency, reliable service even under heavy load. diff --git a/.ai/pages/reference-parachains-consensus.md b/.ai/pages/reference-parachains-consensus.md deleted file mode 100644 index 7f1a8ec17..000000000 --- a/.ai/pages/reference-parachains-consensus.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/reference/parachains/consensus/ ---- - -TODO diff --git a/.ai/pages/reference-parachains-cryptography.md b/.ai/pages/reference-parachains-cryptography.md deleted file mode 100644 index 07407b2e4..000000000 --- a/.ai/pages/reference-parachains-cryptography.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -title: Cryptography -description: A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/cryptography/ ---- - -# Cryptography - -## Introduction - -Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem. - -## Hash Functions - -Hash functions are fundamental to blockchain technology, creating a unique digital fingerprint for any piece of data, including simple text, images, or any other form of file. They map input data of any size to a fixed-size output (typically 32 bytes) using complex mathematical operations. Hashing is used to verify data integrity, create digital signatures, and provide a secure way to store passwords. This form of mapping is known as the ["pigeonhole principle,"](https://en.wikipedia.org/wiki/Pigeonhole_principle){target=\_blank} it is primarily implemented to efficiently and verifiably identify data from large sets. - -### Key Properties of Hash Functions - -- **Deterministic**: The same input always produces the same output. -- **Quick computation**: It's easy to calculate the hash value for any given input. -- **Pre-image resistance**: It's infeasible to generate the input data from its hash. -- **Small changes in input yield large changes in output**: Known as the ["avalanche effect"](https://en.wikipedia.org/wiki/Avalanche_effect){target=\_blank}. -- **Collision resistance**: The probabilities are extremely low to find two different inputs with the same hash. - -### Blake2 - -The Polkadot SDK utilizes Blake2, a state-of-the-art hashing method that offers: - -- Equal or greater security compared to [SHA-2](https://en.wikipedia.org/wiki/SHA-2){target=\_blank}. -- Significantly faster performance than other algorithms. - -These properties make Blake2 ideal for blockchain systems, reducing sync times for new nodes and lowering the resources required for validation. For detailed technical specifications about Blake2, see the [official Blake2 paper](https://www.blake2.net/blake2.pdf){target=\_blank}. - -## Types of Cryptography - -There are two different ways that cryptographic algorithms are implemented: symmetric cryptography and asymmetric cryptography. - -### Symmetric Cryptography - -Symmetric encryption is a branch of cryptography that isn't based on one-way functions, unlike asymmetric cryptography. It uses the same cryptographic key to encrypt plain text and decrypt the resulting ciphertext. - -Symmetric cryptography is a type of encryption that has been used throughout history, such as the Enigma Cipher and the Caesar Cipher. It is still widely used today and can be found in Web2 and Web3 applications alike. There is only one single key, and a recipient must also have access to it to access the contained information. - -#### Advantages {: #symmetric-advantages } - -- Fast and efficient for large amounts of data. -- Requires less computational power. - -#### Disadvantages {: #symmetric-disadvantages } - -- Key distribution can be challenging. -- Scalability issues in systems with many users. - -### Asymmetric Cryptography - -Asymmetric encryption is a type of cryptography that uses two different keys, known as a keypair: a public key, used to encrypt plain text, and a private counterpart, used to decrypt the ciphertext. - -The public key encrypts a fixed-length message that can only be decrypted with the recipient's private key and, sometimes, a set password. The public key can be used to cryptographically verify that the corresponding private key was used to create a piece of data without compromising the private key, such as with digital signatures. This has obvious implications for identity, ownership, and properties and is used in many different protocols across Web2 and Web3. - -#### Advantages {: #asymmetric-advantages } - -- Solves the key distribution problem. -- Enables digital signatures and secure key exchange. - -#### Disadvantages {: #asymmetric-disadvantages } - -- Slower than symmetric encryption. -- Requires more computational resources. - -### Trade-offs and Compromises - -Symmetric cryptography is faster and requires fewer bits in the key to achieve the same level of security that asymmetric cryptography provides. However, it requires a shared secret before communication can occur, which poses issues to its integrity and a potential compromise point. On the other hand, asymmetric cryptography doesn't require the secret to be shared ahead of time, allowing for far better end-user security. - -Hybrid symmetric and asymmetric cryptography is often used to overcome the engineering issues of asymmetric cryptography, as it is slower and requires more bits in the key to achieve the same level of security. It encrypts a key and then uses the comparatively lightweight symmetric cipher to do the "heavy lifting" with the message. - -## Digital Signatures - -Digital signatures are a way of verifying the authenticity of a document or message using asymmetric keypairs. They are used to ensure that a sender or signer's document or message hasn't been tampered with in transit, and for recipients to verify that the data is accurate and from the expected sender. - -Signing digital signatures only requires a low-level understanding of mathematics and cryptography. For a conceptual example -- when signing a check, it is expected that it cannot be cashed multiple times. This isn't a feature of the signature system but rather the check serialization system. The bank will check that the serial number on the check hasn't already been used. Digital signatures essentially combine these two concepts, allowing the signature to provide the serialization via a unique cryptographic fingerprint that cannot be reproduced. - -Unlike pen-and-paper signatures, knowledge of a digital signature cannot be used to create other signatures. Digital signatures are often used in bureaucratic processes, as they are more secure than simply scanning in a signature and pasting it onto a document. - -Polkadot SDK provides multiple different cryptographic schemes and is generic so that it can support anything that implements the [`Pair` trait](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Pair.html){target=\_blank}. - -### Example of Creating a Digital Signature - -The process of creating and verifying a digital signature involves several steps: - -1. The sender creates a hash of the message. -2. The hash is encrypted using the sender's private key, creating the signature. -3. The message and signature are sent to the recipient. -4. The recipient decrypts the signature using the sender's public key. -5. The recipient hashes the received message and compares it to the decrypted hash. - -If the hashes match, the signature is valid, confirming the message's integrity and the sender's identity. - -## Elliptic Curve - -Blockchain technology requires the ability to have multiple keys creating a signature for block proposal and validation. To this end, Elliptic Curve Digital Signature Algorithm (ECDSA) and Schnorr signatures are two of the most commonly used methods. While ECDSA is a far simpler implementation, Schnorr signatures are more efficient when it comes to multi-signatures. - -Schnorr signatures bring some noticeable features over the ECDSA/EdDSA schemes: - -- It is better for hierarchical deterministic key derivations. -- It allows for native multi-signature through [signature aggregation](https://bitcoincore.org/en/2017/03/23/schnorr-signature-aggregation/){target=\_blank}. -- It is generally more resistant to misuse. - -One sacrifice that is made when using Schnorr signatures over ECDSA is that both require 64 bytes, but only ECDSA signatures communicate their public key. - -### Various Implementations - -- **[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm){target=\_blank}**: Polkadot SDK provides an ECDSA signature scheme using the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1){target=\_blank} curve. This is the same cryptographic algorithm used to secure [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin){target=\_blank} and [Ethereum](https://en.wikipedia.org/wiki/Ethereum){target=\_blank}. - -- **[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519){target=\_blank}**: An EdDSA signature scheme using [Curve25519](https://en.wikipedia.org/wiki/Curve25519){target=\_blank}. It is carefully engineered at several levels of design and implementation to achieve very high speeds without compromising security. - -- **[SR25519](https://research.web3.foundation/Polkadot/security/keys/accounts-more){target=\_blank}**: Based on the same underlying curve as Ed25519. However, it uses Schnorr signatures instead of the EdDSA scheme. diff --git a/.ai/pages/reference-parachains-data-encoding.md b/.ai/pages/reference-parachains-data-encoding.md deleted file mode 100644 index 4e8a72194..000000000 --- a/.ai/pages/reference-parachains-data-encoding.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Data Encoding -description: SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/data-encoding/ ---- - -# Data Encoding - -## Introduction - -The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data. - -The SCALE codec enables communication between the runtime and the outer node. This mechanism is designed for high-performance, copy-free data encoding and decoding in resource-constrained environments like the Polkadot SDK [Wasm runtime](/develop/parachains/deployment/build-deterministic-runtime/#introduction){target=\_blank}. - -It is not self-describing, meaning the decoding context must fully know the encoded data types. - -Parity's libraries utilize the [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\_blank} crate (a Rust implementation of the SCALE codec) to handle encoding and decoding for interactions between RPCs and the runtime. - -The `codec` mechanism is ideal for Polkadot SDK-based chains because: - -- It is lightweight compared to generic serialization frameworks like [`serde`](https://serde.rs/){target=\_blank}, which add unnecessary bulk to binaries. -- It doesn’t rely on Rust’s `libstd`, making it compatible with `no_std` environments like Wasm runtime. -- It integrates seamlessly with Rust, allowing easy derivation of encoding and decoding logic for new types using `#[derive(Encode, Decode)]`. - -Defining a custom encoding scheme in the Polkadot SDK-based chains, rather than using an existing Rust codec library, is crucial for enabling cross-platform and multi-language support. - -## SCALE Codec - -The codec is implemented using the following traits: - -- [`Encode`](#encode) -- [`Decode`](#decode) -- [`CompactAs`](#compactas) -- [`HasCompact`](#hascompact) -- [`EncodeLike`](#encodelike) - -### Encode - -The [`Encode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Encode.html){target=\_blank} trait handles data encoding into SCALE format and includes the following key functions: - -- **`size_hint(&self) -> usize`**: Estimates the number of bytes required for encoding to prevent multiple memory allocations. This should be inexpensive and avoid complex operations. Optional if the size isn’t known. -- **`encode_to(&self, dest: &mut T)`**: Encodes the data, appending it to a destination buffer. -- **`encode(&self) -> Vec`**: Encodes the data and returns it as a byte vector. -- **`using_encoded R>(&self, f: F) -> R`**: Encodes the data and passes it to a closure, returning the result. -- **`encoded_size(&self) -> usize`**: Calculates the encoded size. Should be used when the encoded data isn’t required. - -!!!tip - For best performance, value types should override `using_encoded`, and allocating types should override `encode_to`. It's recommended to implement `size_hint` for all types where possible. - -### Decode - -The [`Decode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Decode.html){target=\_blank} trait handles decoding SCALE-encoded data back into the appropriate types: - -- **`fn decode(value: &mut I) -> Result`**: Decodes data from the SCALE format, returning an error if decoding fails. - -### CompactAs - -The [`CompactAs`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.CompactAs.html){target=\_blank} trait wraps custom types for compact encoding: - -- **`encode_as(&self) -> &Self::As`**: Encodes the type as a compact type. -- **`decode_from(_: Self::As) -> Result`**: decodes from a compact encoded type. - -### HasCompact - -The [`HasCompact`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.HasCompact.html){target=\_blank} trait indicates a type supports compact encoding. - -### EncodeLike - -The [`EncodeLike`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.EncodeLike.html){target=\_blank} trait is used to ensure multiple types that encode similarly are accepted by the same function. When using `derive`, it is automatically implemented. - -### Data Types - -The table below outlines how the Rust implementation of the Parity SCALE codec encodes different data types. - -| Type | Description | Example SCALE Decoded Value | SCALE Encoded Value | -|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------| -| Boolean | Boolean values are encoded using the least significant bit of a single byte. | `false` / `true` | `0x00` / `0x01` | -| Compact/general integers | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2^536) and is more efficient at encoding most values than the fixed-width version. | `unsigned integer 0` / `unsigned integer 1` / `unsigned integer 42` / `unsigned integer 69` / `unsigned integer 65535` / `BigInt(100000000000000)` | `0x00` / `0x04` / `0xa8` / `0x1501` / `0xfeff0300` / `0x0b00407a10f35a` | -| Enumerations (tagged-unions) | A fixed number of variants, each mutually exclusive and potentially implying a further value or series of values. Encoded as the first byte identifying the index of the variant that the value is. Any further bytes are used to encode any data that the variant implies. Thus, no more than 256 variants are supported. | `Int(42)` and `Bool(true)` where `enum IntOrBool { Int(u8), Bool(bool) }` | `0x002a` and `0x0101` | -| Fixed-width integers | Basic integers are encoded using a fixed-width little-endian (LE) format. | `signed 8-bit integer 69` / `unsigned 16-bit integer 42` / `unsigned 32-bit integer 16777215` | `0x45` / `0x2a00` / `0xffffff00` | -| Options | One or zero values of a particular type. | `Some` / `None` | `0x01` followed by the encoded value / `0x00` | -| Results | Results are commonly used enumerations which indicate whether certain operations were successful or unsuccessful. | `Ok(42)` / `Err(false)` | `0x002a` / `0x0100` | -| Strings | Strings are Vectors of bytes (Vec) containing a valid UTF8 sequence. | | | -| Structs | For structures, the values are named, but that is irrelevant for the encoding (names are ignored - only order matters). | `SortedVecAsc::from([3, 5, 2, 8])` | `[3, 2, 5, 8] ` | -| Tuples | A fixed-size series of values, each with a possibly different but predetermined and fixed type. This is simply the concatenation of each encoded value. | Tuple of compact unsigned integer and boolean: `(3, false)` | `0x0c00` | -| Vectors (lists, series, sets) | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. | Vector of unsigned `16`-bit integers: `[4, 8, 15, 16, 23, 42]` | `0x18040008000f00100017002a00` | - -## Encode and Decode Rust Trait Implementations - -Here's how the `Encode` and `Decode` traits are implemented: - - -```rust -use parity_scale_codec::{Encode, Decode}; - -[derive(Debug, PartialEq, Encode, Decode)] -enum EnumType { - #[codec(index = 15)] - A, - B(u32, u64), - C { - a: u32, - b: u64, - }, -} - -let a = EnumType::A; -let b = EnumType::B(1, 2); -let c = EnumType::C { a: 1, b: 2 }; - -a.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x0f"); -}); - -b.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -c.using_encoded(|ref slice| { - assert_eq!(slice, &b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"); -}); - -let mut da: &[u8] = b"\x0f"; -assert_eq!(EnumType::decode(&mut da).ok(), Some(a)); - -let mut db: &[u8] = b"\x01\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut db).ok(), Some(b)); - -let mut dc: &[u8] = b"\x02\x01\0\0\0\x02\0\0\0\0\0\0\0"; -assert_eq!(EnumType::decode(&mut dc).ok(), Some(c)); - -let mut dz: &[u8] = &[0]; -assert_eq!(EnumType::decode(&mut dz).ok(), None); -``` - -## SCALE Codec Libraries - -Several SCALE codec implementations are available in various languages. Here's a list of them: - -- **AssemblyScript**: [`LimeChain/as-scale-codec`](https://github.com/LimeChain/as-scale-codec){target=\_blank} -- **C**: [`MatthewDarnell/cScale`](https://github.com/MatthewDarnell/cScale){target=\_blank} -- **C++**: [`qdrvm/scale-codec-cpp`](https://github.com/qdrvm/scale-codec-cpp){target=\_blank} -- **JavaScript**: [`polkadot-js/api`](https://github.com/polkadot-js/api){target=\_blank} -- **Dart**: [`leonardocustodio/polkadart`](https://github.com/leonardocustodio/polkadart){target=\_blank} -- **Haskell**: [`airalab/hs-web3`](https://github.com/airalab/hs-web3/tree/master/packages/scale){target=\_blank} -- **Golang**: [`itering/scale.go`](https://github.com/itering/scale.go){target=\_blank} -- **Java**: [`splix/polkaj`](https://github.com/splix/polkaj){target=\_blank} -- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\_blank} -- **Ruby**: [` wuminzhe/scale_rb`](https://github.com/wuminzhe/scale_rb){target=\_blank} -- **TypeScript**: [`parity-scale-codec-ts`](https://github.com/tjjfvi/subshape){target=\_blank}, [`scale-ts`](https://github.com/unstoppablejs/unstoppablejs/tree/main/packages/scale-ts#scale-ts){target=\_blank}, [`soramitsu/scale-codec-js-library`](https://github.com/soramitsu/scale-codec-js-library){target=\_blank}, [`subsquid/scale-codec`](https://github.com/subsquid/squid-sdk/tree/master/substrate/scale-codec){target=\_blank} diff --git a/.ai/pages/reference-parachains-interoperability.md b/.ai/pages/reference-parachains-interoperability.md deleted file mode 100644 index 8427e3355..000000000 --- a/.ai/pages/reference-parachains-interoperability.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Interoperability -description: Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/interoperability/ ---- - -# Interoperability - -## Introduction - -Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions. - -Polkadot’s design ensures that blockchains can transcend their individual limitations by working together as part of a unified system. This cooperative architecture is what sets Polkadot apart in the blockchain landscape. - -## Why Interoperability Matters - -The blockchain ecosystem is inherently fragmented. Different blockchains excel in specialized domains such as finance, gaming, or supply chain management, but these chains function in isolation without interoperability. This lack of connectivity stifles the broader utility of blockchain technology. - -Interoperability solves this problem by enabling blockchains to: - -- **Collaborate across networks**: Chains can interact to share assets, functionality, and data, creating synergies that amplify their individual strengths. -- **Achieve greater scalability**: Specialized chains can offload tasks to others, optimizing performance and resource utilization. -- **Expand use-case potential**: Cross-chain applications can leverage features from multiple blockchains, unlocking novel user experiences and solutions. - -In the Polkadot ecosystem, interoperability transforms a collection of isolated chains into a cohesive, efficient network, pushing the boundaries of what blockchains can achieve together. - -## Key Mechanisms for Interoperability - -At the core of Polkadot's cross-chain collaboration are foundational technologies designed to break down barriers between networks. These mechanisms empower blockchains to communicate, share resources, and operate as a cohesive ecosystem. - -### Cross-Consensus Messaging (XCM): The Backbone of Communication - -Polkadot's Cross-Consensus Messaging (XCM) is the standard framework for interaction between parachains, relay chains, and, eventually, external blockchains. XCM provides a trustless, secure messaging format for exchanging assets, sharing data, and executing cross-chain operations. - -Through XCM, decentralized applications can: - -- Transfer tokens and other assets across chains. -- Coordinate complex workflows that span multiple blockchains. -- Enable seamless user experiences where underlying blockchain differences are invisible. -- XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem. - -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. - -### Bridges: Connecting External Networks - -While XCM enables interoperability within the Polkadot ecosystem, bridges extend this functionality to external blockchains such as Ethereum and Bitcoin. By connecting these networks, bridges allow Polkadot-based chains to access external liquidity, additional functionalities, and broader user bases. - -With bridges, developers and users gain the ability to: - -- Integrate external assets into Polkadot-based applications. -- Combine the strengths of Polkadot’s scalability with the liquidity of other networks. -- Facilitate accurate multi-chain applications that transcend ecosystem boundaries. - -For more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\_blank} guide. - -## The Polkadot Advantage - -Polkadot was purpose-built for interoperability. Unlike networks that add interoperability as an afterthought, Polkadot integrates it as a fundamental design principle. This approach offers several distinct advantages: - -- **Developer empowerment**: Polkadot’s interoperability tools allow developers to build applications that leverage multiple chains’ capabilities without added complexity. -- **Enhanced ecosystem collaboration**: Chains in Polkadot can focus on their unique strengths while contributing to the ecosystem’s overall growth. -- **Future-proofing blockchain**: By enabling seamless communication, Polkadot ensures its ecosystem can adapt to evolving demands and technologies. - -## Looking Ahead - -Polkadot’s vision of interoperability extends beyond technical functionality, representing a shift towards a more collaborative blockchain landscape. By enabling chains to work together, Polkadot fosters innovation, efficiency, and accessibility, paving the way for a decentralized future where blockchains are not isolated competitors but interconnected collaborators. diff --git a/.ai/pages/reference-parachains-networks.md b/.ai/pages/reference-parachains-networks.md deleted file mode 100644 index 118cfbffe..000000000 --- a/.ai/pages/reference-parachains-networks.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Networks -description: Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. -categories: Basics, Polkadot Protocol, Networks -url: https://docs.polkadot.com/reference/parachains/networks/ ---- - -# Networks - -## Introduction - -The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's various networks and explain how they fit into the development workflow. - -## Network Overview - -Polkadot's development process is structured to ensure new features and upgrades are rigorously tested before being deployed on live production networks. The progression follows a well-defined path, starting from local environments and advancing through TestNets, ultimately reaching the Polkadot MainNet. The diagram below outlines the typical progression of the Polkadot development cycle: - -``` mermaid -flowchart LR - id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] - id1[Local] --> id3[Paseo] --> id5[Polkadot] -``` - -This flow ensures developers can thoroughly test and iterate without risking real tokens or affecting production networks. Testing tools like [Chopsticks](#chopsticks) and various TestNets make it easier to experiment safely before releasing to production. - -A typical journey through the Polkadot core protocol development process might look like this: - -1. **Local development node**: Development starts in a local environment, where developers can create, test, and iterate on upgrades or new features using a local development node. This stage allows rapid experimentation in an isolated setup without any external dependencies. - -2. **Westend**: After testing locally, upgrades are deployed to [Westend](#westend), Polkadot's primary TestNet. Westend simulates real-world conditions without using real tokens, making it the ideal place for rigorous feature testing before moving on to production networks. - -3. **Kusama**: Once features have passed extensive testing on Westend, they move to Kusama, Polkadot's experimental and fast-moving "canary" network. Kusama operates as a high-fidelity testing ground with actual economic incentives, giving developers insights into how their features will perform in a real-world environment. - -4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network. - - In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets. - -5. **Paseo**: For parachain and dApp developers, Paseo serves as a community-run TestNet that mirrors Polkadot's runtime. Like Westend for core protocol development, Paseo provides a testing ground for parachain development without affecting live networks. - -!!!note - The Rococo TestNet deprecation date was October 14, 2024. Teams should use Westend for Polkadot protocol and feature testing and Paseo for chain development-related testing. - -## Polkadot Development Networks - -Development and testing are crucial to building robust dApps and parachains and performing network upgrades within the Polkadot ecosystem. To achieve this, developers can leverage various networks and tools that provide a risk-free environment for experimentation and validation before deploying features to live networks. These networks help avoid the costs and risks associated with real tokens, enabling testing for functionalities like governance, cross-chain messaging, and runtime upgrades. - -## Kusama Network - -Kusama is the experimental version of Polkadot, designed for developers who want to move quickly and test their applications in a real-world environment with economic incentives. Kusama serves as a production-grade testing ground where developers can deploy features and upgrades with the pressure of game theory and economics in mind. It mirrors Polkadot but operates as a more flexible space for innovation. - -The native token for Kusama is KSM. For more information about KSM, visit the [Native Assets](https://wiki.polkadot.com/kusama/kusama-getting-started/){target=\_blank} page. - -## Test Networks - -The following test networks provide controlled environments for testing upgrades and new features. TestNet tokens are available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\_blank}. - -### Westend - -Westend is Polkadot's primary permanent TestNet. Unlike temporary test networks, Westend is not reset to the genesis block, making it an ongoing environment for testing Polkadot core features. Managed by Parity Technologies, Westend ensures that developers can test features in a real-world simulation without using actual tokens. - -The native token for Westend is WND. More details about WND can be found on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_2){target=\_blank} page. - -### Paseo - -[Paseo](https://github.com/paseo-network){target=\_blank} is a community-managed TestNet designed for parachain and dApp developers. It mirrors Polkadot's runtime and is maintained by Polkadot community members. Paseo provides a dedicated space for parachain developers to test their applications in a Polkadot-like environment without the risks associated with live networks. - -The native token for Paseo is PAS. Additional information on PAS is available on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_1){target=\_blank} page. - -## Local Test Networks - -Local test networks are an essential part of the development cycle for blockchain developers using the Polkadot SDK. They allow for fast, iterative testing in controlled, private environments without connecting to public TestNets. Developers can quickly spin up local instances to experiment, debug, and validate their code before deploying to larger TestNets like Westend or Paseo. Two key tools for local network testing are Zombienet and Chopsticks. - -### Zombienet - -[Zombienet](https://github.com/paritytech/zombienet){target=\_blank} is a flexible testing framework for Polkadot SDK-based blockchains. It enables developers to create and manage ephemeral, short-lived networks. This feature makes Zombienet particularly useful for quick iterations, as it allows you to run multiple local networks concurrently, mimicking different runtime conditions. Whether you're developing a parachain or testing your custom blockchain logic, Zombienet gives you the tools to automate local testing. - -Key features of Zombienet include: - -- Creating dynamic, local networks with different configurations. -- Running parachains and relay chains in a simulated environment. -- Efficient testing of network components like cross-chain messaging and governance. - -Zombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets. - -### Chopsticks - -[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\_blank} is a tool designed to create forks of Polkadot SDK-based blockchains, allowing developers to interact with network forks as part of their testing process. This capability makes Chopsticks a powerful option for testing upgrades, runtime changes, or cross-chain applications in a forked network environment. - -Key features of Chopsticks include: - -- Forking live Polkadot SDK-based blockchains for isolated testing. -- Simulating cross-chain messages in a private, controlled setup. -- Debugging network behavior by interacting with the fork in real-time. - -Chopsticks provides a controlled environment for developers to safely explore the effects of runtime changes. It ensures that network behavior is tested and verified before upgrades are deployed to live networks. diff --git a/.ai/pages/reference-parachains-node-and-runtime.md b/.ai/pages/reference-parachains-node-and-runtime.md deleted file mode 100644 index 050ac6aab..000000000 --- a/.ai/pages/reference-parachains-node-and-runtime.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -title: Node and Runtime -description: Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/node-and-runtime/ ---- - -# Node and Runtime - -## Introduction - -Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network. - -Polkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime. - -If the system were a monolithic protocol, any modification would require updating the entire system. Instead, Polkadot achieves true upgradeability by defining an immutable meta-protocol (the client) and a protocol (the runtime) that can be upgraded independently. - -This separation gives the [Polkadot Relay Chain](/polkadot-protocol/architecture/polkadot-chain){target=\_blank} and all connected [parachains](/polkadot-protocol/architecture/parachains){target=\_blank} an evolutionary advantage over other blockchain platforms. - -## Architectural Principles - -The Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components: - -- Client (Meta-protocol): - - Handles the foundational infrastructure of the blockchain. - - Manages runtime execution, networking, consensus, and other off-chain components. - - Provides an immutable base layer that ensures network stability. - - Upgradable only through hard forks. - -- Runtime (Protocol): - - Defines the blockchain's state transition logic. - - Determines the specific rules and behaviors of the blockchain. - - Compiled to WebAssembly (Wasm) for platform-independent execution. - - Capable of being upgraded without network-wide forking. - -### Advantages of this Architecture - -- **Forkless upgrades**: Runtime can be updated without disrupting the entire network. -- **Modularity**: Clear separation allows independent development of client and runtime. -- **Flexibility**: Enables rapid iteration and evolution of blockchain logic. -- **Performance**: WebAssembly compilation provides efficient, cross-platform execution. - -## Node (Client) - -The node, also known as the client, is the core component responsible for executing the Wasm runtime and orchestrating various essential blockchain components. It ensures the correct execution of the state transition function and manages multiple critical subsystems, including: - -- **Wasm execution**: Runs the blockchain runtime, which defines the state transition rules. -- **Database management**: Stores blockchain data. -- **Networking**: Facilitates peer-to-peer communication, block propagation, and transaction gossiping. -- **Transaction pool (Mempool)**: Manages pending transactions before they are included in a block. -- **Consensus mechanism**: Ensures agreement on the blockchain state across nodes. -- **RPC services**: Provides external interfaces for applications and users to interact with the node. - -## Runtime - -The runtime is more than just a set of rules. It's the fundamental logic engine that defines a blockchain's entire behavior. In Polkadot SDK-based blockchains, the runtime represents a complete, self-contained description of the blockchain's state transition function. - -### Characteristics - -The runtime is distinguished by three key characteristics: - -- **Business logic**: Defines the complete application-specific blockchain behavior. -- **WebAssembly compilation**: Ensures platform-independent, secure execution. -- **On-chain storage**: Stored within the blockchain's state, allowing dynamic updates. - -### Key Functions - -The runtime performs several critical functions, such as: - -- Define state transition rules. -- Implement blockchain-specific logic. -- Manage account interactions. -- Control transaction processing. -- Define governance mechanisms. -- Handle custom pallets and modules. - -## Communication Between Node and Runtime - -The client and runtime communicate exclusively using [SCALE-encoded](/polkadot-protocol/parachain-basics/data-encoding){target=\_blank} communication. This ensures efficient and compact data exchange between the two components. - -### Runtime APIs - -The Runtime API consists of well-defined functions and constants a client assumes are implemented in the Runtime Wasm blob. These APIs enable the client to interact with the runtime to execute blockchain operations and retrieve information. The client invokes these APIs to: - -- Build, execute, and finalize blocks. -- Access metadata. -- Access consensus related information. -- Handle transaction execution. - -### Host Functions - -During execution, the runtime can access certain external client functionalities via host functions. The specific functions the client exposes allow the runtime to perform operations outside the WebAssembly domain. Host functions enable the runtime to: - -- Perform cryptographic operations. -- Access the current blockchain state. -- Handle storage modifications. -- Allocate memory. diff --git a/.ai/pages/reference-parachains-randomness.md b/.ai/pages/reference-parachains-randomness.md deleted file mode 100644 index 26b96542b..000000000 --- a/.ai/pages/reference-parachains-randomness.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Randomness -description: Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. -categories: Basics, Polkadot Protocol -url: https://docs.polkadot.com/reference/parachains/randomness/ ---- - -# Randomness - -## Introduction - -Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as "random" numbers on a computer are actually pseudo-random. These numbers rely on an initial "seed," which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\_blank}, [heart rates](https://mdpi.altmetric.com/details/47574324){target=\_blank}, or even [lava lamps](https://en.wikipedia.org/wiki/Lavarand){target=\_blank}. While this may seem random, given the same "seed," the same sequence of numbers will always be generated. - -In a global blockchain network, relying on real-world entropy for randomness isn’t feasible because these inputs vary by time and location. If nodes use different inputs, blockchains can fork. Hence, real-world randomness isn't suitable for use as a seed in blockchain systems. - -Currently, two primary methods for generating randomness in blockchains are used: [`RANDAO`](#randao) and [`VRF`](#vrf) (Verifiable Random Function). Polkadot adopts the `VRF` approach for its randomness. - -## VRF - -A Verifiable Random Function (VRF) is a cryptographic function that generates a random number and proof that ensures the submitter produced the number. This proof allows anyone to verify the validity of the random number. - -Polkadot's VRF is similar to the one used in [**Ouroboros Praos**](https://eprint.iacr.org/2017/573.pdf){target=\_blank}, which secures randomness for block production in systems like [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe){target=\_blank} (Polkadot’s block production mechanism). - -The key difference is that Polkadot's VRF doesn’t rely on a central clock—avoiding the issue of whose clock to trust. Instead, it uses its own past results and slot numbers to simulate time and determine future outcomes. - -### How VRF Works - -Slots on Polkadot are discrete units of time, each lasting six seconds, and can potentially hold a block. Multiple slots form an epoch, with 2400 slots making up one four-hour epoch. - -In each slot, validators execute a "die roll" using a VRF. The VRF uses three inputs: - -1. A "secret key," unique to each validator, is used for the die roll. -2. An epoch randomness value, derived from the hash of VRF outputs from blocks two epochs ago (N-2), so past randomness influences the current epoch (N). -3. The current slot number. - -This process helps maintain fair randomness across the network. - -Here is a graphical representation: - -![](/images/reference/parachains/randomness/randomness-01.webp) - -The VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly). - -The result is checked by the validator against a protocol threshold. If it's below the threshold, the validator becomes a candidate for block production in that slot. - -The validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`. - -So, VRF can be expressed like: - -`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)` - -Put simply, performing a "VRF roll" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen. - -After executing the VRF, the `RESULT` is compared to a protocol-defined `THRESHOLD`. If the `RESULT` is below the `THRESHOLD`, the validator becomes a valid candidate to propose a block for that slot. Otherwise, the validator skips the slot. - -As a result, there may be multiple validators eligible to propose a block for a slot. In this case, the block accepted by other nodes will prevail, provided it is on the chain with the latest finalized block as determined by the GRANDPA finality gadget. It's also possible for no block producers to be available for a slot, in which case the AURA consensus takes over. AURA is a fallback mechanism that randomly selects a validator to produce a block, running in parallel with BABE and only stepping in when no block producers exist for a slot. Otherwise, it remains inactive. - -Because validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. - -To verify resolution of this issue and that Polkadot block times remain near constant-time, see the [PoS Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\_blank} page of this documentation. - -## RANDAO - -An alternative on-chain randomness method is Ethereum's RANDAO, where validators perform thousands of hashes on a seed and publish the final hash during a round. The collective input from all validators forms the random number, and as long as one honest validator participates, the randomness is secure. - -To enhance security, RANDAO can optionally be combined with a Verifiable Delay Function (VDF), ensuring that randomness can't be predicted or manipulated during computation. - -For more information about RANDAO, see the [Randomness - RANDAO](https://eth2book.info/capella/part2/building_blocks/randomness/){target=\_blank} section of the Upgrading Ethereum documentation. - -## VDFs - -Verifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. - -They produce a unique result that can be quickly verified publicly. When combined with RANDAO, feeding RANDAO's output into a VDF introduces a delay that nullifies an attacker's chance to influence the randomness. - -However, VDF likely requires specialized ASIC devices to run separately from standard nodes. - -!!!warning - While only one is needed to secure the system, and they will be open-source and inexpensive, running VDF devices involves significant costs without direct incentives, adding friction for blockchain users. - -## Additional Resources - -For more information about the reasoning for choices made along with proofs, see Polkadot's research on blockchain randomness and sortition in the [Block production](https://research.web3.foundation/Polkadot/protocols/block-production){target=\_blank} entry of the Polkadot Wiki. - -For a discussion with Web3 Foundation researchers about when and under what conditions Polkadot's randomness can be utilized, see the [Discussion on Randomness used in Polkadot](https://github.com/use-ink/ink/issues/57){target=\_blank} issue on GitHub. diff --git a/.ai/pages/reference-parachains.md b/.ai/pages/reference-parachains.md deleted file mode 100644 index 8f1c746c5..000000000 --- a/.ai/pages/reference-parachains.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: Parachains Overview -description: Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. -categories: Basics, Parachains -url: https://docs.polkadot.com/reference/parachains/ ---- - -# Parachains Overview - -## Introduction - -A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network. - -Unlike standalone blockchains that must bootstrap their own validator sets and security, parachains leverage Polkadot's pooled security model. This allows parachain developers to focus on their application-specific functionality rather than consensus and security infrastructure. Parachains can communicate with each other through Cross-Consensus Messaging (XCM), enabling seamless interoperability across the Polkadot ecosystem. - -Key capabilities that parachains provide include: - -- **Shared security**: Inherit security from Polkadot's validator set without maintaining your own. -- **Interoperability**: Communicate trustlessly with other parachains via XCM. -- **Scalability**: Process transactions in parallel with other parachains. -- **Customization**: Build application-specific logic tailored to your use case. -- **Upgradeability**: Upgrade runtime logic without hard forks. - -## Polkadot SDK: Parachain Architecture - -Building a parachain involves understanding and utilizing several key components of the Polkadot SDK: - -![](/images/reference/parachains/index/overview-01.webp) - -- **[Substrate](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html){target=\_blank}**: The foundation providing core blockchain primitives and libraries. -- **[FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\_blank}**: A modular framework for building your parachain's runtime logic. -- **[Cumulus](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html){target=\_blank}**: Essential libraries and pallets that enable parachain functionality. -- **[XCM (Cross Consensus Messaging)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/xcm/index.html){target=\_blank}**: The messaging format for communicating with other parachains and the relay chain. -- **[Polkadot](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/polkadot/index.html){target=\_blank}**: The relay chain that provides security and coordination. - -### Substrate: The Foundation - -Substrate provides the core infrastructure that every parachain is built upon. It handles the low-level blockchain functionality, allowing you to focus on your application's unique features. Substrate includes implementations for networking, database management, consensus participation, and the execution environment for your runtime. - -Every Polkadot SDK node consists of two main components: - -- **Client (Host)**: Handles infrastructure services. - - - Native binary that runs on validator and collator nodes. - - Executes the Wasm-compiled runtime. - - Manages networking, database, mempool, and block production. - - Interfaces with the relay chain for validation. - -- **Runtime (State Transition Function)**: Contains your business logic. - - - Defines how your Polkadot SDK node processes transactions. - - Compiled to [Wasm](https://webassembly.org/){target=\_blank} for deterministic execution. - - Stored on-chain and upgradeable via governance. - -```mermaid -%%{init: {'flowchart': {'padding': 5, 'nodeSpacing': 50, 'rankSpacing': 10}}}%% -graph TB - classDef title font-size:20px,font-weight:bold,stroke-width:0px - classDef clientStyle font-size:16px,font-weight:bold - classDef clientSubNodeStyle margin-top:10px - classDef runtimeCallExecutorStyle padding-top:10px - - subgraph sg1[Parachain
    Node] - direction TB - - I[RuntimeCall Executor] - B[Wasm Runtime - STF] - - subgraph sg2[Client] - direction TB - C[Network and Blockchain
    Infrastructure Services
    + Relay Chain Interface] - end - - I --> B - end - - class sg1 title - class sg2 clientStyle - class C clientSubNodeStyle - class I runtimeCallExecutorStyle - -``` - -### FRAME: Building Blocks for Your Runtime - -FRAME provides modular components called [pallets](/reference/glossary#pallet){target=\_blank} that you can compose to build your parachain's runtime. Each pallet provides specific functionality that you can customize and configure for your needs. This modular approach allows you to quickly assemble complex functionality without writing everything from scratch. - -```mermaid -graph LR - subgraph SP["Parachain Runtime"] - direction LR - Timestamp ~~~ Aura ~~~ ParachainSystem - Balances ~~~ TransactionPayment ~~~ Sudo - subgraph Timestamp["Timestamp"] - SS1[Custom Config] - end - subgraph Aura["Aura"] - SS2[Custom Config] - end - subgraph ParachainSystem["Parachain System"] - SS3[Custom Config] - end - subgraph Balances["Balances"] - SS4[Custom Config] - end - subgraph TransactionPayment["Transaction Payment"] - SS5[Custom Config] - end - subgraph Sudo["Sudo"] - SS6[Custom Config] - end - style Timestamp stroke:#FF69B4 - style Aura stroke:#FF69B4 - style ParachainSystem stroke:#FF69B4 - style Balances stroke:#FF69B4 - style TransactionPayment stroke:#FF69B4 - style Sudo stroke:#FF69B4 - style SS1 stroke-dasharray: 5 - style SS2 stroke-dasharray: 5 - style SS3 stroke-dasharray: 5 - style SS4 stroke-dasharray: 5 - style SS5 stroke-dasharray: 5 - style SS6 stroke-dasharray: 5 - - end - subgraph AP["Available FRAME Pallets"] - direction LR - A1[Aura]~~~A2[Parachain
    System]~~~A3[Transaction
    Payment]~~~A4[Sudo] - B1[Identity]~~~B2[Balances]~~~B3[Assets]~~~B4[EVM] - C1[Timestamp]~~~C2[Staking]~~~C3[Contracts]~~~C4[and more...] - end - AP --> SP -``` - -### Cumulus: Parachain-Specific Functionality - -Cumulus is what transforms a Polkadot SDK-based runtime into a parachain-capable runtime. It provides the essential components for communicating with the relay chain, participating in Polkadot's consensus, and handling parachain-specific operations like block validation and collation. - -Key Cumulus components include: - -- **Parachain system pallet**: Core parachain functionality and relay chain communication. -- **Collator consensus**: Block production logic for parachain collators. -- **Relay chain interface**: APIs for interacting with the Polkadot relay chain. -- **Validation data**: Handling proof-of-validity data required by relay chain validators. - -## Where to Go Next - -Building a parachain requires understanding the relationship between your chain and the Polkadot relay chain. The Polkadot SDK provides all the tools needed to design custom runtime logic, enable cross-chain communication, and deploy your parachain to production. - -The following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance. - -
    - -- Guide __Launch a Simple Parachain__ - - --- - - Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime. - - [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/) - - -- Guide __Customize Your Runtime__ - - --- - - Design your parachain's runtime logic and choose appropriate pallets for your use case. - - [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/) - -- Guide __Interoperability__ - - --- - - Implement XCM for trustless cross-chain communication with other parachains. - - [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/) - -- Guide __Runtime Upgrades__ - - --- - - Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms. - - [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/) - -
    diff --git a/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md b/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md deleted file mode 100644 index 4773cc0df..000000000 --- a/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: Asset Hub -description: Learn about Asset Hub in Polkadot, managing on-chain assets, foreign asset integration, and using XCM for cross-chain asset transfers. -categories: Polkadot Protocol -url: https://docs.polkadot.com/reference/polkadot-hub/assets-and-smart-contracts/ ---- - -# Asset Hub - -## Introduction - -The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integration using XCM, as well as essential tools like [API Sidecar](#api-sidecar) and [`TxWrapper`](#txwrapper) for developers working with on-chain assets. - -## Assets Basics - -In the Polkadot ecosystem, the relay chain does not natively support additional assets beyond its native token (DOT for Polkadot, KSM for Kusama). The Asset Hub parachain on Polkadot and Kusama provides a fungible and non-fungible assets framework. Asset Hub allows developers and users to create, manage, and use assets across the ecosystem. - -Asset creators can use Asset Hub to track their asset issuance across multiple parachains and manage assets through operations such as minting, burning, and transferring. Projects that need a standardized method of handling on-chain assets will find this particularly useful. The fungible asset interface provided by Asset Hub closely resembles Ethereum's ERC-20 standard but is directly integrated into Polkadot's runtime, making it more efficient in terms of speed and transaction fees. - -Integrating with Asset Hub offers several key benefits, particularly for infrastructure providers and users: - -- **Support for non-native on-chain assets**: Asset Hub enables seamless asset creation and management, allowing projects to develop tokens or assets that can interact with the broader ecosystem. -- **Lower transaction fees**: Asset Hub offers significantly lower transaction costs—approximately one-tenth of the fees on the relay chain, providing cost-efficiency for regular operations. -- **Reduced deposit requirements**: Depositing assets in Asset Hub is more accessible, with deposit requirements that are around one one-hundredth of those on the relay chain. -- **Payment of transaction fees with non-native assets**: Users can pay transaction fees in assets other than the native token (DOT or KSM), offering more flexibility for developers and users. - -Assets created on the Asset Hub are stored as part of a map, where each asset has a unique ID that links to information about the asset, including details like: - -- The management team. -- The total supply. -- The number of accounts holding the asset. -- **Sufficiency for account existence**: Whether the asset alone is enough to maintain an account without a native token balance. -- The metadata of the asset, including its name, symbol, and the number of decimals for representation. - -Some assets can be regarded as sufficient to maintain an account's existence, meaning that users can create accounts on the network without needing a native token balance (i.e., no existential deposit required). Developers can also set minimum balances for their assets. If an account's balance drops below the minimum, the balance is considered dust and may be cleared. - -## Assets Pallet - -The Polkadot SDK's Assets pallet is a powerful module designated for creating and managing fungible asset classes with a fixed supply. It offers a secure and flexible way to issue, transfer, freeze, and destroy assets. The pallet supports various operations and includes permissioned and non-permissioned functions to cater to simple and advanced use cases. - -Visit the [Assets Pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\_blank} for more in-depth information. - -### Key Features - -Key features of the Assets pallet include: - -- **Asset issuance**: Allows the creation of a new asset, where the total supply is assigned to the creator's account. -- **Asset transfer**: Enables transferring assets between accounts while maintaining a balance in both accounts. -- **Asset freezing**: Prevents transfers of a specific asset from one account, locking it from further transactions. -- **Asset destruction**: Allows accounts to burn or destroy their holdings, removing those assets from circulation. -- **Non-custodial transfers**: A non-custodial mechanism to enable one account to approve a transfer of assets on behalf of another. - -### Main Functions - -The Assets pallet provides a broad interface for managing fungible assets. Some of the main dispatchable functions include: - -- **`create()`**: Create a new asset class by placing a deposit, applicable when asset creation is permissionless. -- **`issue()`**: Mint a fixed supply of a new asset and assign it to the creator's account. -- **`transfer()`**: Transfer a specified amount of an asset between two accounts. -- **`approve_transfer()`**: Approve a non-custodial transfer, allowing a third party to move assets between accounts. -- **`destroy()`**: Destroy an entire asset class, removing it permanently from the chain. -- **`freeze()` and `thaw()`**: Administrators or privileged users can lock or unlock assets from being transferred. - -For a full list of dispatchable and privileged functions, see the [dispatchables Rust docs](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/enum.Call.html){target=\_blank}. - -### Querying Functions - -The Assets pallet exposes several key querying functions that developers can interact with programmatically. These functions allow you to query asset information and perform operations essential for managing assets across accounts. The two main querying functions are: - -- **`balance(asset_id, account)`**: Retrieves the balance of a given asset for a specified account. Useful for checking the holdings of an asset class across different accounts. - -- **`total_supply(asset_id)`**: Returns the total supply of the asset identified by `asset_id`. Allows users to verify how much of the asset exists on-chain. - -In addition to these basic functions, other utility functions are available for querying asset metadata and performing asset transfers. You can view the complete list of querying functions in the [Struct Pallet Rust docs](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/struct.Pallet.html){target=\_blank}. - -### Permission Models and Roles - -The Assets pallet incorporates a robust permission model, enabling control over who can perform specific operations like minting, transferring, or freezing assets. The key roles within the permission model are: - -- **Admin**: Can freeze (preventing transfers) and forcibly transfer assets between accounts. Admins also have the power to reduce the balance of an asset class across arbitrary accounts. They manage the more sensitive and administrative aspects of the asset class. -- **Issuer**: Responsible for minting new tokens. When new assets are created, the Issuer is the account that controls their distribution to other accounts. -- **Freezer**: Can lock the transfer of assets from an account, preventing the account holder from moving their balance. This function is useful for freezing accounts involved in disputes or fraud. -- **Owner**: Has overarching control, including destroying an entire asset class. Owners can also set or update the Issuer, Freezer, and Admin roles. - -These permissions provide fine-grained control over assets, enabling developers and asset managers to ensure secure, controlled operations. Each of these roles is crucial for managing asset lifecycles and ensuring that assets are used appropriately across the network. - -### Asset Freezing - -The Assets pallet allows you to freeze assets. This feature prevents transfers or spending from a specific account, effectively locking the balance of an asset class until it is explicitly unfrozen. Asset freezing is beneficial when assets are restricted due to security concerns or disputes. - -Freezing assets is controlled by the Freezer role, as mentioned earlier. Only the account with the Freezer privilege can perform these operations. Here are the key freezing functions: - -- **`freeze(asset_id, account)`**: Locks the specified asset of the account. While the asset is frozen, no transfers can be made from the frozen account. -- **`thaw(asset_id, account)`**: Corresponding function for unfreezing, allowing the asset to be transferred again. - -This approach enables secure and flexible asset management, providing administrators the tools to control asset movement in special circumstances. - -### Non-Custodial Transfers (Approval API) - -The Assets pallet also supports non-custodial transfers through the Approval API. This feature allows one account to approve another account to transfer a specific amount of its assets to a third-party recipient without granting full control over the account's balance. Non-custodial transfers enable secure transactions where trust is required between multiple parties. - -Here's a brief overview of the key functions for non-custodial asset transfers: - -- **`approve_transfer(asset_id, delegate, amount)`**: Approves a delegate to transfer up to a certain amount of the asset on behalf of the original account holder. -- **`cancel_approval(asset_id, delegate)`**: Cancels a previous approval for the delegate. Once canceled, the delegate no longer has permission to transfer the approved amount. -- **`transfer_approved(asset_id, owner, recipient, amount)`**: Executes the approved asset transfer from the owner’s account to the recipient. The delegate account can call this function once approval is granted. - -These delegated operations make it easier to manage multi-step transactions and dApps that require complex asset flows between participants. - -## Foreign Assets - -Foreign assets in Asset Hub refer to assets originating from external blockchains or parachains that are registered in the Asset Hub. These assets are typically native tokens from other parachains within the Polkadot ecosystem or bridged tokens from external blockchains such as Ethereum. - -Once a foreign asset is registered in the Asset Hub by its originating blockchain's root origin, users are able to send these tokens to the Asset Hub and interact with them as they would any other asset within the Polkadot ecosystem. - -### Handling Foreign Assets - -The Foreign Assets pallet, an instance of the Assets pallet, manages these assets. Since foreign assets are integrated into the same interface as native assets, developers can use the same functionalities, such as transferring and querying balances. However, there are important distinctions when dealing with foreign assets. - -- **Asset identifier**: Unlike native assets, foreign assets are identified using an XCM Multilocation rather than a simple numeric `AssetId`. This multilocation identifier represents the cross-chain location of the asset and provides a standardized way to reference it across different parachains and relay chains. - -- **Transfers**: Once registered in the Asset Hub, foreign assets can be transferred between accounts, just like native assets. Users can also send these assets back to their originating blockchain if supported by the relevant cross-chain messaging mechanisms. - -## Integration - -Asset Hub supports a variety of integration tools that make it easy for developers to manage assets and interact with the blockchain in their applications. The tools and libraries provided by Parity Technologies enable streamlined operations, such as querying asset information, building transactions, and monitoring cross-chain asset transfers. - -Developers can integrate Asset Hub into their projects using these core tools: - -### API Sidecar - -[API Sidecar](https://github.com/paritytech/substrate-api-sidecar){target=\_blank} is a RESTful service that can be deployed alongside Polkadot and Kusama nodes. It provides endpoints to retrieve real-time blockchain data, including asset information. When used with Asset Hub, Sidecar allows querying: - -- **Asset look-ups**: Retrieve specific assets using `AssetId`. -- **Asset balances**: View the balance of a particular asset on Asset Hub. - -Public instances of API Sidecar connected to Asset Hub are available, such as: - -- [Polkadot Asset Hub Sidecar](https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/){target=\_blank} -- [Kusama Asset Hub Sidecar](https://kusama-asset-hub-public-sidecar.parity-chains.parity.io/){target=\_blank} - -These public instances are primarily for ad-hoc testing and quick checks. - -### TxWrapper - -[`TxWrapper`](https://github.com/paritytech/txwrapper-core){target=\_blank} is a library that simplifies constructing and signing transactions for Polkadot SDK-based chains, including Polkadot and Kusama. This tool includes support for working with Asset Hub, enabling developers to: - -- Construct offline transactions. -- Leverage asset-specific functions such as minting, burning, and transferring assets. - -`TxWrapper` provides the flexibility needed to integrate asset operations into custom applications while maintaining the security and efficiency of Polkadot's transaction model. - - -### Parachain Node - -To fully leverage the Asset Hub's functionality, developers will need to run a system parachain node. Setting up an Asset Hub node allows users to interact with the parachain in real time, syncing data and participating in the broader Polkadot ecosystem. Guidelines for setting up an [Asset Hub node](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/cumulus#asset-hub-){target=\_blank} are available in the Parity documentation. - -Using these integration tools, developers can manage assets seamlessly and integrate Asset Hub functionality into their applications, leveraging Polkadot's powerful infrastructure. - -## XCM Transfer Monitoring - -Since Asset Hub facilitates cross-chain asset transfers across the Polkadot ecosystem, XCM transfer monitoring becomes an essential practice for developers and infrastructure providers. This section outlines how to monitor the cross-chain movement of assets between parachains, the relay chain, and other systems. - -### Monitor XCM Deposits - -As assets move between chains, tracking the cross-chain transfers in real time is crucial. Whether assets are transferred via a teleport from system parachains or through a reserve-backed transfer from any other parachain, each transfer emits a relevant event (such as the `balances.minted` event). - -To ensure accurate monitoring of these events: - -- **Track XCM deposits**: Query every new block created in the relay chain or Asset Hub, loop through the events array, and filter for any `balances.minted` events which confirm the asset was successfully transferred to the account. -- **Track event origins**: Each `balances.minted` event points to a specific address. By monitoring this, service providers can verify that assets have arrived in the correct account. - -### Track XCM Information Back to the Source - -While the `balances.minted` event confirms the arrival of assets, there may be instances where you need to trace the origin of the cross-chain message that triggered the event. In such cases, you can: - -1. Query the relevant chain at the block where the `balances.minted` event was emitted. -2. Look for a `messageQueue(Processed)` event within that block's initialization. This event contains a parameter (`Id`) that identifies the cross-chain message received by the relay chain or Asset Hub. You can use this `Id` to trace the message back to its origin chain, offering full visibility of the asset transfer's journey. - -### Practical Monitoring Examples - -The preceding sections outline the process of monitoring XCM deposits to specific accounts and then tracing back the origin of these deposits. The process of tracking an XCM transfer and the specific events to monitor may vary based on the direction of the XCM message. Here are some examples to showcase the slight differences: - -- **Transfer from parachain to relay chain**: Track `parachainsystem(UpwardMessageSent)` on the parachain and `messagequeue(Processed)` on the relay chain. -- **Transfer from relay chain to parachain**: Track `xcmPallet(sent)` on the relay chain and `dmpqueue(ExecutedDownward)` on the parachain. -- **Transfer between parachains**: Track `xcmpqueue(XcmpMessageSent)` on the system parachain and `xcmpqueue(Success)` on the destination parachain. - -### Monitor for Failed XCM Transfers - -Sometimes, XCM transfers may fail due to liquidity or other errors. Failed transfers emit specific error events, which are key to resolving issues in asset transfers. Monitoring for these failure events helps catch issues before they affect asset balances. - -- **Relay chain to system parachain**: Look for the `dmpqueue(ExecutedDownward)` event on the parachain with an `Incomplete` outcome and an error type such as `UntrustedReserveLocation`. -- **Parachain to parachain**: Monitor for `xcmpqueue(Fail)` on the destination parachain with error types like `TooExpensive`. - -For detailed error management in XCM, see Gavin Wood's blog post on [XCM Execution and Error Management](https://polkadot.com/blog/xcm-part-three-execution-and-error-management/){target=\_blank}. - -## Where to Go Next - -
    - -- Tutorial __Register a Local Asset__ - - --- - - Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. - - [:octicons-arrow-right-24: Reference](/chain-interactions/token-operations/register-local-asset/) - -- Tutorial __Register a Foreign Asset__ - - --- - - An in-depth guide to registering a foreign asset on the Asset Hub parachain, providing clear, step-by-step instructions. - - [:octicons-arrow-right-24: Reference](/chain-interactions/token-operations/register-foreign-asset/) - -- Tutorial __Convert Assets__ - - --- - - A guide detailing the step-by-step process of converting assets on Asset Hub, helping users efficiently navigate asset management on the platform. - - [:octicons-arrow-right-24: Reference](/chain-interactions/token-operations/convert-assets/) - -
    diff --git a/.ai/pages/reference-polkadot-hub-bridging.md b/.ai/pages/reference-polkadot-hub-bridging.md deleted file mode 100644 index ba5c3816a..000000000 --- a/.ai/pages/reference-polkadot-hub-bridging.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Bridge Hub -description: Learn about the Bridge Hub system parachain, a parachain that facilitates the interactions from Polkadot to the rest of Web3. -categories: Polkadot Protocol -url: https://docs.polkadot.com/reference/polkadot-hub/bridging/ ---- - -# Bridge Hub - -## Introduction - -The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interoperability framework. With built-in support for XCM (Cross-Consensus Messaging), Bridge Hub enables secure, efficient communication between diverse blockchain networks. - -This guide covers the architecture, components, and deployment of the Bridge Hub system. You'll explore its trustless bridging mechanisms, key pallets for various blockchains, and specific implementations like Snowbridge and the Polkadot <> Kusama bridge. By the end, you'll understand how Bridge Hub enhances connectivity within the Polkadot ecosystem and beyond. - -## Trustless Bridging - -Bridge Hub provides a mode of trustless bridging through its implementation of on-chain light clients and trustless relayers. Trustless bridges are essentially two one-way bridges, where each chain has a method of verifying the state of the other in a trustless manner through consensus proofs. In this context, "trustless" refers to the lack of need to trust a human when interacting with various system components. Trustless systems are based instead on trusting mathematics, cryptography, and code. The target chain and source chain both provide ways of verifying one another's state and actions (such as a transfer) based on the consensus and finality of both chains rather than an external mechanism controlled by a third party. - -[BEEFY (Bridge Efficiency Enabling Finality Yielder)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#bridging-beefy){target=\_blank} is instrumental in this solution. It provides a more efficient way to verify the consensus on the relay chain. It allows the participants in a network to verify finality proofs, meaning a remote chain like Ethereum can verify the state of Polkadot at a given block height. - -For example, the Ethereum and Polkadot bridging solution that [Snowbridge](https://docs.snowbridge.network/){target=\_blank} implements involves two light clients: one which verifies the state of Polkadot and the other which verifies the state of Ethereum. The light client for Polkadot is implemented in the runtime as a pallet, whereas the light client for Ethereum is implemented as a smart contract on the beacon chain. - -## Bridging Components - -In any given Bridge Hub implementation (Kusama, Polkadot, or other relay chains), there are a few primary pallets that are utilized: - -- **[Pallet Bridge GRANDPA](https://paritytech.github.io/polkadot-sdk/master/pallet_bridge_grandpa/index.html){target=\_blank}**: An on-chain GRANDPA light client for Substrate based chains. -- **[Pallet Bridge Parachains](https://paritytech.github.io/polkadot-sdk/master/pallet_bridge_parachains/index.html){target=\_blank}**: A finality module for parachains. -- **[Pallet Bridge Messages](https://paritytech.github.io/polkadot-sdk/master/pallet_bridge_messages/index.html){target=\_blank}**: A pallet which allows sending, receiving, and tracking of inbound and outbound messages. -- **[Pallet XCM Bridge](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm_bridge_hub/index.html){target=\_blank}**: A pallet which, with the Bridge Messages pallet, adds XCM support to bridge pallets. - -### Ethereum-Specific Support - -Bridge Hub also has a set of components and pallets that support a bridge between Polkadot and Ethereum through [Snowbridge](https://github.com/Snowfork/snowbridge){target=\_blank}. - -To view the complete list of which pallets are included in Bridge Hub, visit the Subscan [Runtime Modules](https://bridgehub-polkadot.subscan.io/runtime){target=\_blank} page. Alternatively, the source code for those pallets can be found in the Polkadot SDK [Snowbridge Pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/bridges/snowbridge/pallets){target=\_blank} repository. - -## Deployed Bridges - -- [**Snowbridge**](https://wiki.polkadot.com/learn/learn-snowbridge/){target=\_blank}: A general-purpose, trustless bridge between Polkadot and Ethereum. -- [**Hyperbridge**](https://wiki.polkadot.com/learn/learn-hyperbridge/){target=\_blank}: A cross-chain solution built as an interoperability coprocessor, providing state-proof-based interoperability across all blockchains. -- [**Polkadot <> Kusama Bridge**](https://wiki.polkadot.com/learn/learn-dot-ksm-bridge/){target=\_blank}: A bridge that utilizes relayers to bridge the Polkadot and Kusama relay chains trustlessly. - -## Where to Go Next - -- Go over the Bridge Hub README in the Polkadot SDK [Bridge-hub Parachains](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/cumulus/parachains/runtimes/bridge-hubs/README.md){target=\_blank} repository. -- Take a deeper dive into bridging architecture in the Polkadot SDK [High-Level Bridge](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/bridges/docs/high-level-overview.md){target=\_blank} documentation. -- Read more about [BEEFY and Bridging in the Polkadot Wiki](/reference/polkadot-hub/consensus-and-security/pos-consensus/#bridging-beefy){target=\_blank}. diff --git a/.ai/pages/reference-polkadot-hub-collectives-and-daos.md b/.ai/pages/reference-polkadot-hub-collectives-and-daos.md deleted file mode 100644 index 0a35af313..000000000 --- a/.ai/pages/reference-polkadot-hub-collectives-and-daos.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Collectives Chain -description: Learn how the Collectives chain provides infrastructure for governance organizations, enabling decentralized network stewardship and decision-making. -categories: Polkadot Protocol -url: https://docs.polkadot.com/reference/polkadot-hub/collectives-and-daos/ ---- - -## Introduction - -Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem. - -The architecture enables entire networks to function as unified entities, allowing them to present cohesive positions and participate in cross-network governance through [Bridge Hub](/polkadot-protocol/architecture/system-chains/bridge-hub){target=\_blank}. This capability represents a fundamental advancement in Web3 principles, eliminating dependencies on traditional third-party intermediaries such as legal systems or jurisdictional authorities. - -## Key Collectives - -The Collectives chain hosts several important governance bodies: - -- [**Polkadot Technical Fellowship**](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\_blank}: A self-governing assembly of protocol experts and developers who oversee technical aspects of the Polkadot and Kusama networks. The Fellowship operates both on-chain through the collectives system and off-chain via GitHub repositories, public discussion forums, and monthly development calls that are publicly accessible. - -- [**Polkadot Alliance**](https://wiki.polkadot.com/general/glossary/#polkadot-alliance){target=\_blank}: A consortium founded by seven leading parachain projects (Acala, Astar, Interlay, Kilt, Moonbeam, Phala, and Subscan) to establish development standards and ethical guidelines within the ecosystem. This ranked collective, comprised of "Fellows" and "Allies," focuses on promoting best practices and identifying potential bad actors. Membership is primarily designed for organizations, projects, and other networks rather than individuals. - -These collectives serve as pillars of Polkadot's decentralized governance model, enabling community-driven decision-making and establishing technical standards that shape the network's evolution. Through structured on-chain representation, they provide transparent mechanisms for ecosystem development while maintaining the core Web3 principles of trustlessness and decentralization. diff --git a/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md b/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md deleted file mode 100644 index 3efbd5901..000000000 --- a/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: Agile Coretime -description: Explore the efficient scheduling mechanisms to access Polkadot cores to produce blockspace continuously or on-demand. -categories: Polkadot Protocol -url: https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/agile-coretime/ ---- - -# Agile Coretime - -## Introduction - -Agile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains. - -``` mermaid -graph TB - A[Cores Designation] - B[Bulk Coretime] - C[On-Demand Coretime] - A --continuous--> B - A --flexible--> C -``` - -Cores can be designated to a parachain either continuously through [bulk coretime](#bulk-coretime) or dynamically via [on-demand coretime](#on-demand-coretime). Additionally, Polkadot supports scheduling multiple cores in parallel through [elastic scaling](https://wiki.polkadot.com/learn/learn-elastic-scaling/){target=\_blank}, which is a feature under active development on Polkadot. This flexibility empowers parachains to optimize their resource usage and block production according to their unique needs. - -In this guide, you'll learn how bulk coretime enables continuous core access with features like interlacing and splitting, and how on-demand coretime provides flexible, pay-per-use scheduling for parachains. For a deep dive on Agile Coretime and its terminology, refer to the [Wiki doc](https://wiki.polkadot.com/learn/learn-agile-coretime/#introduction-to-agile-coretime){target=\_blank}. - -## Bulk Coretime - -Bulk coretime is a fixed duration of continuous coretime represented by an NFT that can be purchased through [coretime sales](#coretime-sales) in DOT and can be split, shared, or resold. Currently, the duration of bulk coretime is set to 28 days. Coretime purchased in bulk and assigned to a single parachain is eligible for a price-capped renewal, providing a form of rent-controlled access, which is important for predicting the running costs in the near future. Suppose the bulk coretime is [interlaced](#coretime-interlacing) or [split](#coretime-splitting) or is kept idle without assigning it to a parachain. In that case, it will be ineligible for the price-capped renewal. - -### Coretime Interlacing - -It is the action of dividing bulk coretime across multiple parachains that produce blocks spaced uniformly in time. For example, think of multiple parachains taking turns producing blocks, demonstrating a simple form of interlacing. This feature can be used by parachains with a low transaction volume and need not continuously produce blocks. - -### Coretime Splitting - -It is the action of dividing bulk coretime into multiple contiguous regions. This feature can be used by parachains that need to produce blocks continuously but do not require the whole 28 days of bulk coretime and require only part of it. - -## On-Demand Coretime - -Polkadot has dedicated cores assigned to provide core time on demand. These cores are excluded from the coretime sales and are reserved for on-demand parachains, which pay in DOT per block. diff --git a/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md b/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md deleted file mode 100644 index db10157e0..000000000 --- a/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Proof of Stake Consensus -description: Explore Polkadot's consensus protocols for secure, scalable, and decentralized network operation, including NPoS, BABE, GRANDPA, and BEEFY. -categories: Polkadot Protocol -url: https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/pos-consensus/ ---- - -# Proof of Stake Consensus - -## Introduction - -Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank} model and a combination of advanced consensus mechanisms to ensure efficient block production and strong finality guarantees. This combination enables the Polkadot network to scale while maintaining security and decentralization. - -## Nominated Proof of Stake - -Polkadot uses Nominated Proof of Stake (NPoS) to select the validator set and secure the network. This model is designed to maximize decentralization and security by balancing the roles of [validators](https://wiki.polkadot.com/learn/learn-validator/){target=\_blank} and [nominators](https://wiki.polkadot.com/learn/learn-nominator/){target=\_blank}. - -- **Validators**: Play a key role in maintaining the network's integrity. They produce new blocks, validate parachain blocks, and ensure the finality of transactions across the relay chain. -- **Nominators**: Support the network by selecting validators to back with their stake. This mechanism allows users who don't want to run a validator node to still participate in securing the network and earn rewards based on the validators they support. - -In Polkadot's NPoS system, nominators can delegate their tokens to trusted validators, giving them voting power in selecting validators while spreading security responsibilities across the network. - -## Hybrid Consensus - -Polkadot employs a hybrid consensus model that combines two key protocols: a finality gadget called [GRANDPA](#finality-gadget-grandpa) and a block production mechanism known as [BABE](#block-production-babe). This hybrid approach enables the network to benefit from both rapid block production and provable finality, ensuring security and performance. - -The hybrid consensus model has some key advantages: - -- **Probabilistic finality**: With BABE constantly producing new blocks, Polkadot ensures that the network continues to make progress, even when a final decision has not yet been reached on which chain is the true canonical chain. - -- **Provable finality**: GRANDPA guarantees that once a block is finalized, it can never be reverted, ensuring that all network participants agree on the finalized chain. - -By using separate protocols for block production and finality, Polkadot can achieve rapid block creation and strong guarantees of finality while avoiding the typical trade-offs seen in traditional consensus mechanisms. - -## Block Production - BABE - -Blind Assignment for Blockchain Extension (BABE) is Polkadot's block production mechanism, working with GRANDPA to ensure blocks are produced consistently across the network. As validators participate in BABE, they are assigned block production slots through a randomness-based lottery system. This helps determine which validator is responsible for producing a block at a given time. BABE shares similarities with [Ouroboros Praos](https://eprint.iacr.org/2017/573.pdf){target=\_blank} but differs in key aspects like chain selection rules and slot timing. - -Key features of BABE include: - -- **Epochs and slots**: BABE operates in phases called epochs, each of which is divided into slots (around 6 seconds per slot). Validators are assigned slots at the beginning of each epoch based on stake and randomness. - -- **Randomized block production**: Validators enter a lottery to determine which will produce a block in a specific slot. This randomness is sourced from the relay chain's [randomness cycle](/reference/parachains/randomness/){target=\_blank}. - -- **Multiple block producers per slot**: In some cases, more than one validator might win the lottery for the same slot, resulting in multiple blocks being produced. These blocks are broadcasted, and the network's fork choice rule helps decide which chain to follow. - -- **Handling empty slots**: If no validators win the lottery for a slot, a secondary selection algorithm ensures that a block is still produced. Validators selected through this method always produce a block, ensuring no slots are skipped. - -BABE's combination of randomness and slot allocation creates a secure, decentralized system for consistent block production while also allowing for fork resolution when multiple validators produce blocks for the same slot. - -### Validator Participation - -In BABE, validators participate in a lottery for every slot to determine whether they are responsible for producing a block during that slot. This process's randomness ensures a decentralized and unpredictable block production mechanism. - -There are two lottery outcomes for any given slot that initiate additional processes: - -- **Multiple validators in a slot**: Due to the randomness, multiple validators can be selected to produce a block for the same slot. When this happens, each validator produces a block and broadcasts it to the network resulting in a race condition. The network's topology and latency then determine which block reaches the majority of nodes first. BABE allows both chains to continue building until the finalization process resolves which one becomes canonical. The [Fork Choice](#fork-choice) rule is then used to decide which chain the network should follow. - -- **No validators in a slot**: On occasions when no validator is selected by the lottery, a [secondary validator selection algorithm](https://spec.polkadot.network/sect-block-production#defn-babe-secondary-slots){target=\_blank} steps in. This backup ensures that a block is still produced, preventing skipped slots. However, if the primary block produced by a verifiable random function [(VRF)-selected](/reference/parachains/randomness/#vrf){target=\_blank} validator exists for that slot, the secondary block will be ignored. As a result, every slot will have either a primary or a secondary block. - -This design ensures continuous block production, even in cases of multiple competing validators or an absence of selected validators. - -### Additional Resources - -For further technical insights about BABE, including cryptographic details and formal proofs, see the [BABE paper](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\_blank} from Web3 Foundation. - -For BABE technical definitions, constants, and formulas, see the [Block Production Lottery](https://spec.polkadot.network/sect-block-production#sect-block-production-lottery){target=\_blank} section of the Polkadot Protocol Specification. - -## Finality Gadget - GRANDPA - -GRANDPA (GHOST-based Recursive ANcestor Deriving Prefix Agreement) serves as the finality gadget for Polkadot's relay chain. Operating alongside the BABE block production mechanism, it ensures provable finality, giving participants confidence that blocks finalized by GRANDPA cannot be reverted. - -Key features of GRANDPA include: - -- **Independent finality service**: GRANDPA runs separately from the block production process, operating in parallel to ensure seamless finalization. -- **Chain-based finalization**: Instead of finalizing one block at a time, GRANDPA finalizes entire chains, speeding up the process significantly. -- **Batch finalization**: Can finalize multiple blocks in a single round, enhancing efficiency and minimizing delays in the network. -- **Partial synchrony tolerance**: GRANDPA works effectively in a partially synchronous network environment, managing both asynchronous and synchronous conditions. -- **Byzantine fault tolerance**: Can handle up to 1/5 Byzantine (malicious) nodes, ensuring the system remains secure even when faced with adversarial behavior. - -??? note "What is GHOST?" - [GHOST (Greedy Heaviest-Observed Subtree)](https://eprint.iacr.org/2018/104.pdf){target=\blank} is a consensus protocol used in blockchain networks to select the heaviest branch in a block tree. Unlike traditional longest-chain rules, GHOST can more efficiently handle high block production rates by considering the weight of subtrees rather than just the chain length. - -### Probabilistic vs. Provable Finality - -In traditional Proof of Work (PoW) blockchains, finality is probabilistic. As blocks are added to the chain, the probability that a block is final increases, but it can never be guaranteed. Eventual consensus means that all nodes will agree on a single version of the blockchain over time, but this process can be unpredictable and slow. - -Conversely, GRANDPA provides provable finality, which means that once a block is finalized, it is irreversible. By using Byzantine fault-tolerant agreements, GRANDPA finalizes blocks more efficiently and securely than probabilistic mechanisms like Nakamoto consensus. Like Ethereum's Casper the Friendly Finality Gadget (FFG), GRANDPA ensures that finalized blocks cannot be reverted, offering stronger consensus guarantees. - -### Additional Resources - -For technical insights, including formal proofs and detailed algorithms, see the [GRANDPA paper](https://github.com/w3f/consensus/blob/master/pdf/grandpa.pdf){target=\_blank} from Web3 Foundation. - -For a deeper look at the code behind GRANDPA, see the following GitHub repositories: - -- [GRANDPA Rust implementation](https://github.com/paritytech/finality-grandpa){target=\_blank} -- [GRANDPA Pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/grandpa/src/lib.rs){target=\_blank} - -## Fork Choice - -The fork choice of the relay chain combines BABE and GRANDPA: - -1. BABE must always build on the chain that GRANDPA has finalized. -2. When there are forks after the finalized head, BABE builds on the chain with the most primary blocks to provide probabilistic finality. - -![Fork choice diagram](/images/reference/polkadot-hub/consensus-and-security/pos-consensus/consensus-protocols-01.webp) - -In the preceding diagram, finalized blocks are black, and non-finalized blocks are yellow. Primary blocks are labeled '1', and secondary blocks are labeled '2.' The topmost chain is the longest chain originating from the last finalized block, but it is not selected because it only has one primary block at the time of evaluation. In comparison, the one below it originates from the last finalized block and has three primary blocks. - -### Additional Resources - -To learn more about how BABE and GRANDPA work together to produce and finalize blocks on Kusama, see this [Block Production and Finalization in Polkadot](https://youtu.be/FiEAnVECa8c){target=\_blank} talk from Web3 Foundation's Bill Laboon. - -For an in-depth academic discussion about Polkadot's hybrid consensus model, see this [Block Production and Finalization in Polkadot: Understanding the BABE and GRANDPA Protocols](https://www.youtube.com/watch?v=1CuTSluL7v4&t=4s){target=\_blank} MIT Cryptoeconomic Systems 2020 talk by Web3 Foundation's Bill Laboon. - -## Bridging - BEEFY - -Bridge Efficiency Enabling Finality Yielder (BEEFY) is a specialized protocol that extends the finality guarantees provided by GRANDPA. It is specifically designed to facilitate efficient bridging between Polkadot relay chains (such as Polkadot and Kusama) and external blockchains like Ethereum. While GRANDPA is well-suited for finalizing blocks within Polkadot, it has limitations when bridging external chains that weren't built with Polkadot's interoperability features in mind. BEEFY addresses these limitations by ensuring other networks can efficiently verify finality proofs. - -Key features of BEEFY include: - -- **Efficient finality proof verification**: BEEFY enables external networks to easily verify Polkadot finality proofs, ensuring seamless communication between chains. -- **Merkle Mountain Ranges (MMR)**: This data structure is used to efficiently store and transmit proofs between chains, optimizing data storage and reducing transmission overhead. -- **ECDSA signature schemes**: BEEFY uses ECDSA signatures, which are widely supported on Ethereum and other EVM-based chains, making integration with these ecosystems smoother. -- **Light client optimization**: BEEFY reduces the computational burden on light clients by allowing them to check for a super-majority of validator votes rather than needing to process all validator signatures, improving performance. - -### Additional Resources - -For BEEFY technical definitions, constants, and formulas, see the [Bridge design (BEEFY)](https://spec.polkadot.network/sect-finality#sect-grandpa-beefy){target=\_blank} section of the Polkadot Protocol Specification. diff --git a/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md b/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md deleted file mode 100644 index 94eee0632..000000000 --- a/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: Overview of the Polkadot Relay Chain -description: Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. -categories: Basics, Polkadot Protocol, Parachains -url: https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/ ---- - -# Overview - -## Introduction - -Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\_blank}, and cross-chain interactions via its native [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank}. - -This guide covers key aspects of Polkadot’s architecture, including its high-level protocol structure, blockspace commoditization, and the role of its native token, DOT, in governance, staking, and resource allocation. - -## Polkadot 1.0 - -Polkadot 1.0 represents the state of Polkadot as of 2023, coinciding with the release of [Polkadot runtime v1.0.0](https://github.com/paritytech/polkadot/releases/tag/v1.0.0){target=\_blank}. This section will focus on Polkadot 1.0, along with philosophical insights into network resilience and blockspace. - -As a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including: - -- **Application-specific Layer-1 blockchains (parachains)**: Polkadot's sharded network allows for parallel transaction processing, with shards that can have unique state transition functions, enabling custom-built L1 chains optimized for specific applications. - -- **Shared security and scalability**: L1 chains connected to Polkadot benefit from its [Nominated Proof of Stake (NPoS)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#nominated-proof-of-stake){target=\_blank} system, providing security out-of-the-box without the need to bootstrap their own. - -- **Secure interoperability**: Polkadot's native interoperability enables seamless data and value exchange between parachains. This interoperability can also be used outside of the ecosystem for bridging with external networks. - -- **Resilient infrastructure**: Decentralized and scalable, Polkadot ensures ongoing support for development and community initiatives via its on-chain [treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\_blank} and governance. - -- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\_blank} allows fast, flexible creation and deployment of Layer-1 chains. - -- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as. - - - [Polkadot Blockchain Academy](https://polkadot.com/blockchain-academy){target=\_blank} - - [EdX courses](https://www.edx.org/school/web3x){target=\_blank} - - Rust and Substrate courses (coming soon) - -### High-Level Architecture - -Polkadot features a chain that serves as the central component of the system. This chain is depicted as a ring encircled by several parachains that are connected to it. - -According to Polkadot's design, any blockchain that can compile to WebAssembly (Wasm) and adheres to the Parachains Protocol becomes a parachain on the Polkadot network. - -Here’s a high-level overview of the Polkadot protocol architecture: - -![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style="background:white" } - -Parachains propose blocks to Polkadot validators, who check for availability and validity before finalizing them. With the relay chain providing security, collators—full nodes of parachains—can focus on their tasks without needing strong incentives. - -The [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\_blank} allows parachains to exchange messages freely, leveraging the chain's security for trust-free communication. - -In order to interact with chains that want to use their own finalization process (e.g., Bitcoin), Polkadot has [bridges](/reference/parachains/interoperability/#bridges-connecting-external-networks){target=\_blank} that offer two-way compatibility, meaning that transactions can be made between different parachains. - -### Polkadot's Additional Functionalities - -Historically, obtaining core slots on Polkadot chain relied upon crowdloans and auctions. Chain cores were leased through auctions for three-month periods, up to a maximum of two years. Crowdloans enabled users to securely lend funds to teams for lease deposits in exchange for pre-sale tokens, which is the only way to access slots on Polkadot 1.0. Auctions are now deprecated in favor of [coretime](/polkadot-protocol/architecture/system-chains/coretime/){target=\_blank}. - -Additionally, the chain handles [staking](https://wiki.polkadot.com/learn/learn-staking/){target=\_blank}, [accounts](/reference/parachains/accounts/){target=\_blank}, balances, and [governance](/reference/governance/){target=\_blank}. - -#### Agile Coretime - -The new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime. - -[Agile coretime](/reference/polkadot-hub/consensus-and-security/agile-coretime/){target=\_blank} improves the efficient use of Polkadot's network resources and offers economic flexibility for developers, extending Polkadot's capabilities far beyond the original vision outlined in the [whitepaper](https://polkadot.com/papers/Polkadot-whitepaper.pdf){target=\_blank}. - -It enables parachains to purchase monthly "bulk" allocations of coretime (the time allocated for utilizing a core, measured in Polkadot relay chain blocks), ensuring heavy-duty parachains that can author a block every six seconds with [Asynchronous Backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\_blank} can reliably renew their coretime each month. Although six-second block times are now the default, parachains have the option of producing blocks less frequently. - -Renewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs. - -### Polkadot's Resilience - -Decentralization is a vital component of blockchain networks, but it comes with trade-offs: - -- An overly decentralized network may face challenges in reaching consensus and require significant energy to operate. -- Also, a network that achieves consensus quickly risks centralization, making it easier to manipulate or attack. - -A network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience. - -Polkadot 1.0 currently achieves resilience through several strategies: - -- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators. - -- **Decentralized nodes**: Designed to encourage operators to join the network. This program aims to expand and diversify the validators in the ecosystem who aim to become independent of the program during their term. Feel free to explore more about the program on the official [Decentralized Nodes](https://nodes.web3.foundation/){target=\_blank} page. - -- **On-chain treasury and governance**: Known as [OpenGov](/reference/governance/){target=\_blank}, this system allows every decision to be made through public referenda, enabling any token holder to cast a vote. - -### Polkadot's Blockspace - -Polkadot 1.0’s design allows for the commoditization of blockspace. - -Blockspace is a blockchain's capacity to finalize and commit operations, encompassing its security, computing, and storage capabilities. Its characteristics can vary across different blockchains, affecting security, flexibility, and availability. - -- **Security**: Measures the robustness of blockspace in Proof of Stake (PoS) networks linked to the stake locked on validator nodes, the variance in stake among validators, and the total number of validators. It also considers social centralization (how many validators are owned by single operators) and physical centralization (how many validators run on the same service provider). - -- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes. - -- **Availability**: Indicates how easily users can access blockspace. It should be easily accessible, allowing diverse business models to thrive, ideally regulated by a marketplace based on demand and supplemented by options for "second-hand" blockspace. - -Polkadot is built on core blockspace principles, but there's room for improvement. Tasks like balance transfers, staking, and governance are managed on the relay chain. - -Delegating these responsibilities to [system chains](/polkadot-protocol/architecture/system-chains/){target=\_blank} could enhance flexibility and allow the relay chain to concentrate on providing shared security and interoperability. - -For more information about blockspace, watch [Robert Habermeier’s interview](https://www.youtube.com/watch?v=e1vISppPwe4){target=\_blank} or read his [technical blog post](https://www.rob.tech/blog/polkadot-blockspace-over-blockchains/){target=\_blank}. - -## DOT Token - -DOT is the native token of the Polkadot network, much like BTC for Bitcoin and Ether for the Ethereum blockchain. DOT has 10 decimals, uses the Planck base unit, and has a balance type of `u128`. The same is true for Kusama's KSM token with the exception of having 12 decimals. - -### Redenomination of DOT - -Polkadot conducted a community poll, which ended on 27 July 2020 at block 888,888, to decide whether to redenominate the DOT token. The stakeholders chose to redenominate the token, changing the value of 1 DOT from 1e12 plancks to 1e10 plancks. - -Importantly, this did not affect the network's total number of base units (plancks); it only affects how a single DOT is represented. The redenomination became effective 72 hours after transfers were enabled, occurring at block 1,248,328 on 21 August 2020 around 16:50 UTC. - -### The Planck Unit - -The smallest unit of account balance on Polkadot SDK-based blockchains (such as Polkadot and Kusama) is called _Planck_, named after the Planck length, the smallest measurable distance in the physical universe. - -Similar to how BTC's smallest unit is the Satoshi and ETH's is the Wei, Polkadot's native token DOT equals 1e10 Planck, while Kusama's native token KSM equals 1e12 Planck. - -### Uses for DOT - -DOT serves three primary functions within the Polkadot network: - -- **Governance**: It is used to participate in the governance of the network. -- **Staking**: DOT is staked to support the network's operation and security. -- **Buying coretime**: Used to purchase coretime in-bulk or on-demand and access the chain to benefit from Polkadot's security and interoperability. - -Additionally, DOT can serve as a transferable token. For example, DOT, held in the treasury, can be allocated to teams developing projects that benefit the Polkadot ecosystem. - -## JAM and the Road Ahead - -The Join-Accumulate Machine (JAM) represents a transformative redesign of Polkadot's core architecture, envisioned as the successor to the current relay chain. Unlike traditional blockchain architectures, JAM introduces a unique computational model that processes work through two primary functions: - -- **Join**: Handles data integration. -- **Accumulate**: Folds computations into the chain's state. - -JAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include: - -- **Permissionless code execution**: JAM is designed to be more generic and flexible, allowing for permissionless code execution through services that can be deployed without governance approval. -- **More effective block time utilization**: JAM's efficient pipeline processing model places the prior state root in block headers instead of the posterior state root, enabling more effective utilization of block time for computations. - -This architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes. diff --git a/.ai/pages/reference-polkadot-hub-people-and-identity.md b/.ai/pages/reference-polkadot-hub-people-and-identity.md deleted file mode 100644 index 7cfca970e..000000000 --- a/.ai/pages/reference-polkadot-hub-people-and-identity.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: People Chain -description: Learn how People chain secures decentralized identity management, empowering users to control and verify digital identities without central authorities. -categories: Polkadot Protocol -url: https://docs.polkadot.com/reference/polkadot-hub/people-and-identity/ ---- - -# People Chain - -## Introduction - -People chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management. - -This solution empowers users to create, control, and verify their digital identities without reliance on centralized authorities. By prioritizing user sovereignty and data privacy, People chain establishes a foundation for trusted interactions throughout the Polkadot ecosystem while returning control of personal information to individuals. - -## Identity Management System - -People chain provides a comprehensive identity framework allowing users to: - -- Establish verifiable on-chain identities. -- Control disclosure of personal information. -- Receive verification from trusted registrars. -- Link multiple accounts under a unified identity. - -Users must reserve funds in a bond to store their information on chain. These funds are locked, not spent, and returned when the identity is cleared. - -### Sub-Identities - -The platform supports hierarchical identity structures through sub-accounts: - -- Primary accounts can establish up to 100 linked sub-accounts. -- Each sub-account maintains its own distinct identity. -- All sub-accounts require a separate bond deposit. - -## Verification Process - -### Judgment Requests - -After establishing an on-chain identity, users can request verification from [registrars](#registrars): - -1. Users specify the maximum fee they're willing to pay for judgment. -2. Only registrars whose fees fall below this threshold can provide verification. -3. Registrars assess the provided information and issue a judgment. - -### Judgment Classifications - -Registrars can assign the following confidence levels to identity information: - -- **Unknown**: Default status; no judgment rendered yet. -- **Reasonable**: Data appears valid but without formal verification (standard for most verified identities). -- **Known good**: Information certified correct through formal verification (requires documentation; limited to registrars). -- **Out of date**: Previously verified information that requires updating. -- **Low quality**: Imprecise information requiring correction. -- **Erroneous**: Incorrect information, potentially indicating fraudulent intent. - -A temporary "Fee Paid" status indicates judgment in progress. Both "Fee Paid" and "Erroneous" statuses lock identity information from modification until resolved. - -### Registrars - -Registrars serve as trusted verification authorities within the People chain ecosystem. These entities validate user identities and provide attestations that build trust in the network. - -- Registrars set specific fees for their verification services. -- They can specialize in verifying particular identity fields. -- Verification costs vary based on complexity and thoroughness. - -When requesting verification, users specify their maximum acceptable fee. Only registrars whose fees fall below this threshold can provide judgment. Upon completing the verification process, the user pays the registrar's fee, and the registrar issues an appropriate confidence level classification based on their assessment. - -Multiple registrars operate across the Polkadot and People chain ecosystems, each with unique specializations and fee structures. To request verification: - -1. Research available registrars and their verification requirements. -2. Contact your chosen registrar directly through their specified channels. -3. Submit required documentation according to their verification process. -4. Pay the associated verification fee. - -You must contact specific registrars individually to request judgment. Each registrar maintains its own verification procedures and communication channels. - -## Where to Go Next - -
    - -- External __Polkadot.js Guides about Identity__ - - --- - - Step-by-step instructions for managing identities through the Polkadot.js interface, with practical examples and visual guides. - - [:octicons-arrow-right-24: Reference](https://wiki.polkadot.com/learn/learn-guides-identity/) - -- External __How to Set and Clear an Identity__ - - --- - - Practical walkthrough covering identity setup and removal process on People chain. - - [:octicons-arrow-right-24: Reference](https://support.polkadot.network/support/solutions/articles/65000181981-how-to-set-and-clear-an-identity) - -- External __People Chain Runtime Implementation__ - - --- - - Source code for the People chain runtime, detailing the technical architecture of decentralized identity management. - - [:octicons-arrow-right-24: Reference](https://github.com/polkadot-fellows/runtimes/tree/main/system-parachains/people) - -
    diff --git a/.ai/pages/reference-polkadot-hub.md b/.ai/pages/reference-polkadot-hub.md deleted file mode 100644 index 1eae456d6..000000000 --- a/.ai/pages/reference-polkadot-hub.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/reference/polkadot-hub/ ---- - -TODO diff --git a/.ai/pages/reference-tools-chopsticks.md b/.ai/pages/reference-tools-chopsticks.md deleted file mode 100644 index 61efd3be3..000000000 --- a/.ai/pages/reference-tools-chopsticks.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/reference/tools/chopsticks/ ---- - -TODO diff --git a/.ai/pages/reference-tools-dedot.md b/.ai/pages/reference-tools-dedot.md deleted file mode 100644 index 1580e7ca0..000000000 --- a/.ai/pages/reference-tools-dedot.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Dedot -description: Dedot is a next-gen JavaScript client for Polkadot and Polkadot SDK-based blockchains, offering lightweight, tree-shakable APIs with strong TypeScript support. -categories: Tooling, Dapps -url: https://docs.polkadot.com/reference/tools/dedot/ ---- - -# Dedot - -## Introduction - -[Dedot](https://github.com/dedotdev/dedot){target=\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\_blank}. - -### Key Features - -- **Lightweight and tree-shakable**: No more bn.js or WebAssembly blobs, optimized for dapps bundle size. -- **Fully typed API**: Comprehensive TypeScript support for seamless on-chain interaction and ink! smart contract integration. -- **Multi-version JSON-RPC support**: Compatible with both [legacy](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md){target=\_blank} and [new](https://paritytech.github.io/json-rpc-interface-spec/introduction.html){target=\_blank} JSON-RPC APIs for broad ecosystem interoperability. -- **Light client support**: Designed to work with light clients such as [Smoldot](https://github.com/smol-dot/smoldot){target=\_blank}. -- **Native TypeScript for scale codec**: Implements scale codec parsing directly in TypeScript without relying on custom wrappers. -- **Wallet integration**: Works out-of-the-box with [@polkadot/extension-based](https://github.com/polkadot-js/extension?tab=readme-ov-file#api-interface){target=\_blank} wallets. -- **Familiar API design**: Similar API style to Polkadot.js for easy and fast migration. - -## Installation - -To add Dedot to your project, use the following command: - -=== "npm" - - ```bash - npm i dedot - ``` - -=== "pnpm" - - ```bash - pnpm add dedot - ``` - -=== "yarn" - - ```bash - yarn add dedot - ``` - -To enable auto-completion/IntelliSense for individual chains, install the [`@dedot/chaintypes`](https://www.npmjs.com/package/@dedot/chaintypes){target=\_blank} package as a development dependency: - -=== "npm" - - ```bash - npm i -D @dedot/chaintypes - ``` - -=== "pnpm" - - ```bash - pnpm add -D @dedot/chaintypes - ``` - -=== "yarn" - - ```bash - yarn add -D @dedot/chaintypes - ``` - -## Get Started - -### Initialize a Client Instance - -To connect to and interact with different networks, Dedot provides two client options depending on your needs: - -- **[`DedotClient`](https://docs.dedot.dev/clients-and-providers/clients#dedotclient){target=\_blank}**: Interacts with chains via the [new JSON-RPC APIs](https://paritytech.github.io/json-rpc-interface-spec/introduction.html){target=\_blank}. -- **[`LegacyClient`](https://docs.dedot.dev/clients-and-providers/clients#legacyclient){target=\_blank}**: Interacts with chains via the [legacy JSON-RPC APIs](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md){target=\_blank}. - -Use the following snippets to connect to Polkadot using `DedotClient`: - -=== "WebSocket" - - ```typescript - import { DedotClient, WsProvider } from 'dedot'; - import type { PolkadotApi } from '@dedot/chaintypes'; - - // Initialize providers & clients - const provider = new WsProvider('wss://rpc.polkadot.io'); - const client = await DedotClient.new(provider); - - ``` - -=== "Light Client (Smoldot)" - - ```typescript - import { DedotClient, SmoldotProvider } from 'dedot'; - import type { PolkadotApi } from '@dedot/chaintypes'; - import * as smoldot from 'smoldot'; - - // import `polkadot` chain spec to connect to Polkadot - import { polkadot } from '@substrate/connect-known-chains'; - - // Start smoldot instance & initialize a chain - const client = smoldot.start(); - const chain = await client.addChain({ chainSpec: polkadot }); - - // Initialize providers & clients - const provider = new SmoldotProvider(chain); - const client = await DedotClient.new(provider); - - ``` - -If the node doesn't support new JSON-RPC APIs yet, you can connect to the network using the `LegacyClient`, which is built on top of the legacy JSON-RPC APIs. - -```typescript -import { LegacyClient, WsProvider } from 'dedot'; -import type { PolkadotApi } from '@dedot/chaintypes'; - -const provider = new WsProvider('wss://rpc.polkadot.io'); -const client = await LegacyClient.new(provider); - -``` - -### Enable Type and API Suggestions - -It is recommended to specify the `ChainApi` interface (e.g., `PolkadotApi` in the example in the previous section) of the chain you want to interact with. This enables type and API suggestions/autocompletion for that particular chain (via IntelliSense). If you don't specify a `ChainApi` interface, a default `SubstrateApi` interface will be used. - -```typescript -import { DedotClient, WsProvider } from 'dedot'; -import type { PolkadotApi, KusamaApi } from '@dedot/chaintypes'; - -const polkadotClient = await DedotClient.new( - new WsProvider('wss://rpc.polkadot.io') -); -const kusamaClient = await DedotClient.new( - new WsProvider('wss://kusama-rpc.polkadot.io') -); -const genericClient = await DedotClient.new( - new WsProvider('ws://localhost:9944') -); - -``` - -If you don't find the `ChainApi` for the network you're working with in [the list](https://github.com/dedotdev/chaintypes?tab=readme-ov-file#supported-networks){target=\_blank}, you can generate the `ChainApi` (types and APIs) using the built-in [`dedot` cli](https://docs.dedot.dev/cli){target=\_blank}. - -```bash -# Generate ChainApi interface for Polkadot network via rpc endpoint: wss://rpc.polkadot.io -npx dedot chaintypes -w wss://rpc.polkadot.io -``` - -Or open a pull request to add your favorite network to the [`@dedot/chaintypes`](https://github.com/dedotdev/chaintypes){target=\_blank} repo. - -### Read On-Chain Data - -Dedot provides several ways to read data from the chain: - -- **Access runtime constants**: Use the syntax `client.consts..` to inspect runtime constants (parameter types). - - ```typescript - const ss58Prefix = client.consts.system.ss58Prefix; - console.log('Polkadot ss58Prefix:', ss58Prefix); - - ``` - -- **Storage queries**: Use the syntax `client.query..` to query on-chain storage. - - ```typescript - const balance = await client.query.system.account('INSERT_ADDRESS'); - console.log('Balance:', balance.data.free); - - ``` - -- **Subscribe to storage changes**: - - ```typescript - const unsub = await client.query.system.number((blockNumber) => { - console.log(`Current block number: ${blockNumber}`); - }); - - ``` - -- **Call Runtime APIs**: Use the syntax `client.call..` to execute Runtime APIs. - - ```typescript - const metadata = await client.call.metadata.metadataAtVersion(15); - console.log('Metadata V15', metadata); - - ``` - -- **Watch on-chain events**: Use the syntax `client.events..` to access pallet events. - - ```typescript - const unsub = await client.events.system.NewAccount.watch((events) => { - console.log('New Account Created', events); - }); - - ``` - -### Sign and Send Transactions - -Sign the transaction using `IKeyringPair` from Keyring ([`@polkadot/keyring`](https://polkadot.js.org/docs/keyring/start/sign-verify/){target=\_blank}) and send the transaction. - -```typescript -import { cryptoWaitReady } from '@polkadot/util-crypto'; -import { Keyring } from '@polkadot/keyring'; -// Setup keyring -await cryptoWaitReady(); -const keyring = new Keyring({ type: 'sr25519' }); -const alice = keyring.addFromUri('//Alice'); -// Send transaction -const unsub = await client.tx.balances - .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n) - .signAndSend(alice, async ({ status }) => { - console.log('Transaction status', status.type); - if (status.type === 'BestChainBlockIncluded') { - console.log(`Transaction is included in best block`); - } - if (status.type === 'Finalized') { - console.log( - `Transaction completed at block hash ${status.value.blockHash}` - ); - await unsub(); - } - }); - -``` - -You can also use `Signer` from wallet extensions: - -```typescript -const injected = await window.injectedWeb3['polkadot-js'].enable('My dApp'); -const account = (await injected.accounts.get())[0]; -const signer = injected.signer; -const unsub = await client.tx.balances - .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n) - .signAndSend(account.address, { signer }, async ({ status }) => { - console.log('Transaction status', status.type); - if (status.type === 'BestChainBlockIncluded') { - console.log(`Transaction is included in best block`); - } - if (status.type === 'Finalized') { - console.log( - `Transaction completed at block hash ${status.value.blockHash}` - ); - await unsub(); - } - }); - -``` - -## Where to Go Next - -For more detailed information about Dedot, check the [official documentation](https://dedot.dev/){target=\_blank}. diff --git a/.ai/pages/reference-tools-light-clients.md b/.ai/pages/reference-tools-light-clients.md deleted file mode 100644 index 9d14cdac5..000000000 --- a/.ai/pages/reference-tools-light-clients.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: Light Clients -description: Light clients enable secure and efficient blockchain interaction without running a full node. Learn everything you need to know about light clients on Polkadot. -categories: Parachains, Tooling -url: https://docs.polkadot.com/reference/tools/light-clients/ ---- - -# Light Clients - -## Introduction - -Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes. - -This guide covers: - -- What light clients are and how they work. -- Their advantages compared to full nodes and JSON-RPC. -- Available implementations in the Polkadot ecosystem. -- How to use light clients in your applications. - -Light clients are particularly valuable for resource-constrained environments and applications requiring secure, decentralized blockchain access without the overhead of maintaining full nodes. - -!!!note "Light node or light client?" - The terms _light node_ and _light client_ are interchangeable. Both refer to a blockchain client that syncs without downloading the entire blockchain state. All nodes in a blockchain network are fundamentally clients, engaging in peer-to-peer communication. - -## Light Clients Workflow - -Unlike JSON-RPC interfaces, where an application must maintain a list of providers or rely on a single node, light clients are not limited to or dependent on a single node. They use cryptographic proofs to verify the blockchain's state, ensuring it is up-to-date and accurate. By verifying only block headers, light clients avoid syncing the entire state, making them ideal for resource-constrained environments. - -```mermaid -flowchart LR -DAPP([dApp])-- Query Account Info -->LC([Light Client]) -LC -- Request --> FN(((Full Node))) -LC -- Response --> DAPP -FN -- Response (validated via Merkle proof) --> LC -``` - -In the diagram above, the decentralized application queries on-chain account information through the light client. The light client runs as part of the application and requires minimal memory and computational resources. It uses Merkle proofs to verify the state retrieved from a full node in a trust-minimized manner. Polkadot-compatible light clients utilize [warp syncing](https://spec.polkadot.network/sect-lightclient#sect-sync-warp-lightclient){target=\_blank}, which downloads only block headers. - -Light clients can quickly verify the blockchain's state, including [GRANDPA finality](/polkadot-protocol/glossary#grandpa){target=\_blank} justifications. - -!!!note "What does it mean to be trust-minimized?" - _Trust-minimized_ means that the light client does not need to fully trust the full node from which it retrieves the state. This is achieved through the use of Merkle proofs, which allow the light client to verify the correctness of the state by checking the Merkle tree root. - -## JSON-RPC and Light Client Comparison - -Another common method of communication between a user interface (UI) and a node is through the JSON-RPC protocol. Generally, the UI retrieves information from the node, fetches network or [pallet](/polkadot-protocol/glossary#pallet){target=\_blank} data, and interacts with the blockchain. This is typically done in one of two ways: - -- **User-controlled nodes**: The UI connects to a node client installed on the user's machine. - - These nodes are secure, but installation and maintenance can be inconvenient. -- **Publicly accessible nodes**: The UI connects to a third-party-owned publicly accessible node client. - - These nodes are convenient but centralized and less secure. Applications must maintain a list of backup nodes in case the primary node becomes unavailable. - -While light clients still communicate with [full nodes](/polkadot-protocol/glossary#full-node), they offer significant advantages for applications requiring a secure alternative to running a full node: - -| Full Node | Light Client | -| :---------------------------------------------------------------------------------------------: | :------------------------------------------------------------: | -| Fully verifies all blocks of the chain | Verifies only the authenticity of blocks | -| Stores previous block data and the chain's storage in a database | Does not require a database | -| Installation, maintenance, and execution are resource-intensive and require technical expertise | No installation is typically included as part of the application | - -## Using Light Clients - -The [`smoldot`](https://github.com/smol-dot/smoldot){target=\_blank} client is the cornerstone of light client implementation for Polkadot SDK-based chains. It provides the primitives needed to build light clients and is also integrated into libraries such as [PAPI](#papi-light-client-support). - -### PAPI Light Client Support - -The [Polkadot API (PAPI)](/develop/toolkit/api-libraries/papi){target=\_blank} library natively supports light client configurations powered by [`smoldot`](https://github.com/smol-dot/smoldot){target=\_blank}. This allows developers to connect to multiple chains simultaneously using a light client. - -### Substrate Connect - Browser Extension - -The [Substrate Connect browser extension](https://www.npmjs.com/package/@substrate/connect-extension-protocol){target=\_blank} enables end-users to interact with applications connected to multiple blockchains or to connect their own blockchains to supported applications. - -Establishing a sufficient number of peers can be challenging due to browser limitations on WebSocket connections from HTTPS pages, as many nodes require TLS. The Substrate Connect browser extension addresses this limitation by keeping chains synced in the background, enabling faster application performance. - -Substrate Connect automatically detects whether the user has the extension installed. If not, an in-page Wasm light client is created for them. - -## Resources - -- [What is a light client and why you should care?](https://medium.com/paritytech/what-is-a-light-client-and-why-you-should-care-75f813ae2670){target=\_blank} -- [Introducing Substrate Connect: Browser-Based Light Clients for Connecting to Substrate Chains](https://www.parity.io/blog/introducing-substrate-connect){target=\_blank} -- [Substrate Connect GitHub Repository](https://github.com/paritytech/substrate-connect/tree/master/projects/extension){target=\_blank} -- [Light Clients - Polkadot Specification](https://spec.polkadot.network/sect-lightclient){target=\_blank} diff --git a/.ai/pages/reference-tools-moonwall.md b/.ai/pages/reference-tools-moonwall.md deleted file mode 100644 index 03bce9823..000000000 --- a/.ai/pages/reference-tools-moonwall.md +++ /dev/null @@ -1,288 +0,0 @@ ---- -title: E2E Testing with Moonwall -description: Enhance blockchain end-to-end testing with Moonwall's standardized environment setup, comprehensive configuration management, and simple network interactions. -categories: Parachains, Tooling -url: https://docs.polkadot.com/reference/tools/moonwall/ ---- - -# E2E Testing with Moonwall - -## Introduction - -Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations. - -Moonwall consolidates this complexity by providing the following: - -- A centralized configuration management system that explicitly defines all network parameters. -- A standardized approach to environment setup across different Substrate-based chains. -- Built-in utilities for common testing scenarios and network interactions. - -Developers can focus on writing meaningful tests rather than managing infrastructure complexities or searching through documentation for configuration options. - -## Prerequisites - -Before you begin, ensure you have the following installed: - -- [Node.js](https://nodejs.org/en/){target=\_blank} (version 20.10 or higher). -- A package manager such as [npm](https://www.npmjs.com/){target=\_blank}, [yarn](https://yarnpkg.com/){target=\_blank}, or [pnpm](https://pnpm.io/){target=\_blank}. - -## Install Moonwall - -Moonwall can be installed globally for system-wide access or locally within specific projects. This section covers both installation methods. - -!!! tip - This documentation corresponds to Moonwall version `5.15.0`. To avoid compatibility issues with the documented features, ensure you're using the matching version. - -### Global Installation - -Global installation provides system-wide access to the Moonwall CLI, making it ideal for developers working across multiple blockchain projects. Install it by running one of the following commands: - -=== "npm" - - ```bash - npm install -g @moonwall/cli@5.15.0 - ``` - -=== "pnpm" - - ```bash - pnpm -g install @moonwall/cli@5.15.0 - ``` - -=== "yarn" - - ```bash - yarn global add @moonwall/cli@5.15.0 - ``` - -Now, you can run the `moonwall` command from your terminal. - -### Local Installation - -Local installation is recommended for better dependency management and version control within a specific project. First, initialize your project: - -```bash -mkdir my-moonwall-project -cd my-moonwall-project -npm init -y -``` - -Then, install it as a local dependency: - -=== "npm" - - ```bash - npm install @moonwall/cli@5.15.0 - ``` - -=== "pnpm" - - ```bash - pnpm install @moonwall/cli@5.15.0 - ``` - -=== "yarn" - - ```bash - yarn add @moonwall/cli@5.15.0 - ``` - -## Initialize Moonwall - -The `moonwall init` command launches an interactive wizard to create your configuration file: - -```bash -moonwall init -``` - -During setup, you will see prompts for the following parameters: - -- **`label`**: Identifies your test configuration. -- **`global timeout`**: Maximum time (ms) for test execution. -- **`environment name`**: Name for your testing environment. -- **`network foundation`**: Type of blockchain environment to use. -- **`tests directory`**: Location of your test files. - -Select `Enter` to accept defaults or input custom values. You should see something like this: - -
    - moonwall init - ✔ Provide a label for the config file moonwall_config - ✔ Provide a global timeout value 30000 - ✔ Provide a name for this environment default_env - ✔ What type of network foundation is this? dev - ✔ Provide the path for where tests for this environment are kept tests/ - ? Would you like to generate this config? (no to restart from beginning) (Y/n) -
    - -The wizard generates a `moonwall.config` file: - -```json -{ - "label": "moonwall_config", - "defaultTestTimeout": 30000, - "environments": [ - { - "name": "default_env", - "testFileDir": ["tests/"], - "foundation": { - "type": "dev" - } - } - ] -} - -``` - -The default configuration requires specific details about your blockchain node and test requirements: - -- The `foundation` object defines how your test blockchain node will be launched and managed. The dev foundation, which runs a local node binary, is used for local development. - - For more information about available options, check the [Foundations](https://moonsong-labs.github.io/moonwall/guide/intro/foundations.html){target=\_blank} section. - -- The `connections` array specifies how your tests will interact with the blockchain node. This typically includes provider configuration and endpoint details. - - A provider is a tool that allows you or your application to connect to a blockchain network and simplifies the low-level details of the process. A provider handles submitting transactions, reading state, and more. For more information on available providers, check the [Providers supported](https://moonsong-labs.github.io/moonwall/guide/intro/providers.html#providers-supported){target=\_blank} page in the Moonwall documentation. - -Here's a complete configuration example for testing a local node using Polkadot.js as a provider: - -```json -{ - "label": "moonwall_config", - "defaultTestTimeout": 30000, - "environments": [ - { - "name": "default_env", - "testFileDir": ["tests/"], - "foundation": { - "launchSpec": [ - { - "binPath": "./node-template", - "newRpcBehaviour": true, - "ports": { "rpcPort": 9944 } - } - ], - "type": "dev" - }, - "connections": [ - { - "name": "myconnection", - "type": "polkadotJs", - "endpoints": ["ws://127.0.0.1:9944"] - } - ] - } - ] -} - -``` - -## Writing Tests - -Moonwall uses the [`describeSuite`](https://github.com/Moonsong-Labs/moonwall/blob/7568048c52e9f7844f38fb4796ae9e1b9205fdaa/packages/cli/src/lib/runnerContext.ts#L65){target=\_blank} function to define test suites, like using [Mocha](https://mochajs.org/){target=\_blank}. Each test suite requires the following: - -- **`id`**: Unique identifier for the suite. -- **`title`**: Descriptive name for the suite. -- **`foundationMethods`**: Specifies the testing environment (e.g., `dev` for local node testing). -- **`testCases`**: A callback function that houses the individual test cases of this suite. - -The following example shows how to test a balance transfer between two accounts: - -```ts -import '@polkadot/api-augment'; -import { describeSuite, expect } from '@moonwall/cli'; -import { Keyring } from '@polkadot/api'; - -describeSuite({ - id: 'D1', - title: 'Demo suite', - foundationMethods: 'dev', - testCases: ({ it, context, log }) => { - it({ - id: 'T1', - title: 'Test Case', - test: async () => { - // Set up polkadot.js API and testing accounts - let api = context.polkadotJs(); - let alice = new Keyring({ type: 'sr25519' }).addFromUri('//Alice'); - let charlie = new Keyring({ type: 'sr25519' }).addFromUri('//Charlie'); - - // Query Charlie's account balance before transfer - const balanceBefore = (await api.query.system.account(charlie.address)) - .data.free; - - // Before transfer, Charlie's account balance should be 0 - expect(balanceBefore.toString()).toEqual('0'); - log('Balance before: ' + balanceBefore.toString()); - - // Transfer from Alice to Charlie - const amount = 1000000000000000; - await api.tx.balances - .transferAllowDeath(charlie.address, amount) - .signAndSend(alice); - - // Wait for the transaction to be included in a block. - // This is necessary because the balance is not updated immediately. - // Block time is 6 seconds. - await new Promise((resolve) => setTimeout(resolve, 6000)); - - // Query Charlie's account balance after transfer - const balanceAfter = (await api.query.system.account(charlie.address)) - .data.free; - - // After transfer, Charlie's account balance should be 1000000000000000 - expect(balanceAfter.toString()).toEqual(amount.toString()); - log('Balance after: ' + balanceAfter.toString()); - }, - }); - }, -}); - -``` - -This test demonstrates several key concepts: - -- Initializing the Polkadot.js API through Moonwall's context and setting up test accounts. -- Querying on-chain state. -- Executing transactions. -- Waiting for block inclusion. -- Verifying results using assertions. - -## Running the Tests - -Execute your tests using the `test` Moonwall CLI command. For the default environment setup run: - -```bash -moonwall test default_env -c moonwall.config -``` - -The test runner will output detailed results showing: - -- Test suite execution status. -- Individual test case results. -- Execution time. -- Detailed logs and error messages (if any). - -Example output: -
    - moonwall test default_env -c moonwall.config - stdout | tests/test1.ts > 🗃️ D1 Demo suite > 📁 D1T1 Test Case - 2025-01-21T19:27:55.624Z test:default_env Balance before: 0 - - stdout | tests/test1.ts > 🗃️ D1 Demo suite > 📁 D1T1 Test Case - 2025-01-21T19:28:01.637Z test:default_env Balance after: 1000000000000000 - - ✓ default_env tests/test1.ts (1 test) 6443ms - ✓ 🗃️ D1 Demo suite > 📁 D1T1 Test Case 6028ms - - Test Files 1 passed (1) - Tests 1 passed (1) - Start at 16:27:53 - Duration 7.95s (transform 72ms, setup 0ms, collect 1.31s, tests 6.44s, environment 0ms, prepare 46ms) - - ✅ All tests passed -
    - -## Where to Go Next - -For a comprehensive guide to Moonwall's full capabilities, available configurations, and advanced usage, see the official [Moonwall](https://moonsong-labs.github.io/moonwall/){target=\_blank} documentation. diff --git a/.ai/pages/reference-tools-omninode.md b/.ai/pages/reference-tools-omninode.md deleted file mode 100644 index 40d0db6e5..000000000 --- a/.ai/pages/reference-tools-omninode.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: Polkadot Omni Node -description: Run parachain nodes easily with the polkadot-omni-node, a white-labeled binary that can run parachain nodes using a single pre-built solution. -categories: Parachains, Tooling -url: https://docs.polkadot.com/reference/tools/omninode/ ---- - -# Polkadot Omni Node - -## Introduction - -The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\_blank} file, allowing it to adapt dynamically to different parachains. - -This approach enables it to act as a white-labeled node binary, capable of running most parachains that do not require custom node-level logic or extensions. Developers can leverage this flexibility to test, deploy, or operate parachain nodes without maintaining a dedicated codebase for each network. - -This guide provides step-by-step instructions for installing the `polkadot-omni-node`, obtaining a chain specification, and spinning up a parachain node. - -## Prerequisites - -Before getting started, ensure you have the following prerequisites: - -- **[Rust](https://rust-lang.org/tools/install/){target=\_blank}**: Required to build and install the `polkadot-omni-node` binary. - -Ensure Rust's `cargo` command is available in your terminal by running: - -```bash -cargo --version -``` - -## Install Polkadot Omni Node - -To install `polkadot-omni-node` globally using `cargo`, run: - -```bash -cargo install --locked polkadot-omni-node@0.7.0 -``` - -This command downloads and installs version 0.7.0 of the binary, making it available system-wide. - -To confirm the installation, run: - -```bash -polkadot-omni-node --version -``` - -You should see the installed version number printed to the terminal, confirming a successful installation. - -## Obtain Chain Specifications - -The `polkadot-omni-node` binary uses a chain specification file to configure and launch a parachain node. This file defines the parachain's genesis state and network settings. - -The most common source for official chain specifications is the [`paritytech/chainspecs`](https://github.com/paritytech/chainspecs){target=\_blank} repository. These specifications are also browsable in a user-friendly format via the [Chainspec Collection](https://paritytech.github.io/chainspecs/){target=\_blank} website. - -To obtain a chain specification: - -1. Visit the [Chainspec Collection](https://paritytech.github.io/chainspecs/){target=\_blank} website. -2. Find the parachain you want to run. -3. Click the chain spec to open it. -4. Copy the JSON content and save it locally as a `.json` file, e.g., `chain_spec.json`. - -## Run a Parachain Full Node - -Once you've installed `polkadot-omni-node` and saved the appropriate chain specification file, you can start a full node for your chosen parachain. - -To see all available flags and configuration options, run: - -```bash -polkadot-omni-node --help -``` - -To launch the node, run the following command, replacing `./INSERT_PARACHAIN_CHAIN_SPEC.json` with the actual path to your saved chain spec file. - -This command will: - -- Load the chain specification. -- Initialize the node using the provided network configuration. -- Begin syncing with the parachain network. - -```bash -polkadot-omni-node --chain ./INSERT_PARACHAIN_CHAIN_SPEC.json --sync warp -``` - -- The `--chain` flag tells the `polkadot-omni-node` which parachain to run by pointing to its chain specification file. -- The `--sync warp` flag enables warp sync, allowing the node to quickly catch up to the latest finalized state. Historical blocks are fetched in the background as the node continues operating. - -Once started, the node will begin connecting to peers and syncing with the network. You’ll see logs in your terminal reflecting its progress. - -## Interact with the Node - -By default, `polkadot-omni-node` exposes a WebSocket endpoint at `ws://localhost:9944`, which you can use to interact with the running node. You can connect using: - -- **[Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\_blank}**: A web-based interface for exploring and interacting with Polkadot SDK-based chains. -- Custom scripts using compatible [libraries](/develop/toolkit/api-libraries/){target=\_blank}. - -Once connected, you can review blocks, call extrinsics, inspect storage, and interact with the runtime. - -## Parachain Compatibility - -The `polkadot-omni-node` is designed to work with most parachains out of the box; however, your parachain's runtime must meet specific requirements and follow certain conventions to be compatible. This section outlines what your runtime needs to implement and configure to work seamlessly with the `polkadot-omni-node`: - -- Your runtime must implement the required runtime APIs (see below). -- Your runtime must include and configure the required pallets. - -The [`parachain-template`](https://github.com/paritytech/polkadot-sdk-parachain-template/tree/v0.0.4){target=_blank} provides a complete reference implementation that is fully compatible with the `polkadot-omni-node`. You can use it as a starting point or reference for ensuring your runtime meets all compatibility requirements. - -### Required Runtime APIs - -Your parachain runtime must implement the following runtime APIs for the `polkadot-omni-node` to function properly: - -- **GetParachainInfo Runtime API**: The omni-node requires the [`GetParachainInfo`](https://paritytech.github.io/polkadot-sdk/master/cumulus_primitives_core/trait.GetParachainInfo.html){target=\_blank} runtime API to identify and configure the parachain correctly. This API provides the parachain ID to the node. - - ```rust title="runtime/src/apis.rs" - impl cumulus_primitives_core::GetParachainInfo for Runtime { - fn parachain_id() -> cumulus_primitives_core::ParaId { - // Return your parachain ID - ParachainInfo::parachain_id() - } - } - ``` - -- **Aura Runtime API**: For consensus, the `polkadot-omni-node` expects the [Aura runtime API](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/apis/trait.AuraApi.html){target=\_blank} to be implemented. - - ```rust title="runtime/src/apis.rs" - impl sp_consensus_aura::AuraApi for Runtime { - fn slot_duration() -> sp_consensus_aura::SlotDuration { - sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION) - } - - fn authorities() -> Vec { - Aura::authorities().into_inner() - } - } - ``` - -### Required Pallets - -Your runtime must include and properly configure the following pallets: - -- **System Pallet**: The System pallet ([`frame-system`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/prelude/frame_system/index.html){target=\_blank}) is fundamental and must be configured with appropriate types. - - ```rust title="runtime/src/lib.rs" - #[frame_support::runtime] - impl frame_system::Config for Runtime { - type Block = Block; - type BlockNumber = BlockNumber; - // ... other configurations - } - - // Must be named "System" for omni-node compatibility - pub type System = frame_system::Pallet; - ``` - -- **ParachainSystem Pallet**: This pallet ([`cumulus-pallet-parachain-system`](https://paritytech.github.io/polkadot-sdk/master/cumulus_pallet_parachain_system/index.html){target=\_blank}) enables parachain functionality and handles low-level details of being a parachain. - - ```rust title="runtime/src/lib.rs" - impl cumulus_pallet_parachain_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - // ... other configurations - } - - // Must be named "ParachainSystem" for omni-node compatibility - pub type ParachainSystem = cumulus_pallet_parachain_system::Pallet; - ``` - -- **Aura Pallet**: For block authoring consensus ([`pallet-aura`](https://paritytech.github.io/polkadot-sdk/master/pallet_aura/index.html){target=\_blank}). - - ```rust title="runtime/src/lib.rs" - impl pallet_aura::Config for Runtime { - type AuthorityId = AuraId; - type DisabledValidators = (); - type MaxAuthorities = MaxAuthorities; - type AllowMultipleBlocksPerSlot = ConstBool; - } - - pub type Aura = pallet_aura::Pallet; - ``` - -- **ParachainInfo Pallet**: Provides parachain metadata ([`parachain-info`](https://paritytech.github.io/polkadot-sdk/master/staging_parachain_info/index.html){target=\_blank}). - - ```rust title="runtime/src/lib.rs" - impl parachain_info::Config for Runtime {} - - pub type ParachainInfo = parachain_info::Pallet; - ``` - -If you're migrating an existing parachain to use the `polkadot-omni-node`, you may need to perform runtime upgrades to add the required runtime APIs and pallets. Follow the standard parachain [runtime upgrade](/parachains/runtime-maintenance/runtime-upgrades/){target=\_blank} procedures to implement these changes on your live network. diff --git a/.ai/pages/reference-tools-papi.md b/.ai/pages/reference-tools-papi.md deleted file mode 100644 index dce9d5063..000000000 --- a/.ai/pages/reference-tools-papi.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -title: Polkadot-API -description: Polkadot-API (PAPI) is a modular, composable library set designed for efficient interaction with Polkadot chains, prioritizing a "light-client first" approach. -categories: Tooling, Dapps -url: https://docs.polkadot.com/reference/tools/papi/ ---- - -# Polkadot-API - -## Introduction - -[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications. - -PAPI is optimized for light-client functionality, using the new JSON-RPC spec to support decentralized interactions fully. It provides strong TypeScript support with types and documentation generated directly from on-chain metadata, and it offers seamless access to storage reads, constants, transactions, events, and runtime calls. Developers can connect to multiple chains simultaneously and prepare for runtime updates through multi-descriptor generation and compatibility checks. PAPI is lightweight and performant, leveraging native BigInt, dynamic imports, and modular subpaths to avoid bundling unnecessary assets. It supports promise-based and observable-based APIs, integrates easily with Polkadot.js extensions, and offers signing options through browser extensions or private keys. - -## Get Started - -### API Instantiation - -To instantiate the API, you can install the package by using the following command: - -=== "npm" - - ```bash - npm i polkadot-api@1.17.2 - ``` - -=== "pnpm" - - ```bash - pnpm add polkadot-api@1.17.2 - ``` - -=== "yarn" - - ```bash - yarn add polkadot-api@1.17.2 - ``` - -Then, obtain the latest metadata from the target chain and generate the necessary types: - -```bash -# Add the target chain -npx papi add dot -n polkadot -``` - -The `papi add` command initializes the library by generating the corresponding types needed for the chain used. It assigns the chain a custom name and specifies downloading metadata from the Polkadot chain. You can replace `dot` with the name you prefer or with another chain if you want to add a different one. Once the latest metadata is downloaded, generate the required types: - -```bash -# Generate the necessary types -npx papi -``` - -You can now set up a [`PolkadotClient`](https://github.com/polkadot-api/polkadot-api/blob/main/packages/client/src/types.ts#L153){target=\_blank} with your chosen provider to begin interacting with the API. Choose from Smoldot via WebWorker, Node.js, or direct usage, or connect through the WSS provider. The examples below show how to configure each option for your setup. - -=== "Smoldot (WebWorker)" - - ```typescript - // `dot` is the identifier assigned during `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - import { getSmProvider } from 'polkadot-api/sm-provider'; - import { chainSpec } from 'polkadot-api/chains/polkadot'; - import { startFromWorker } from 'polkadot-api/smoldot/from-worker'; - import SmWorker from 'polkadot-api/smoldot/worker?worker'; - - const worker = new SmWorker(); - const smoldot = startFromWorker(worker); - const chain = await smoldot.addChain({ chainSpec }); - - // Establish connection to the Polkadot relay chain - const client = createClient(getSmProvider(chain)); - - // To interact with the chain, obtain the `TypedApi`, which provides - // the necessary types for every API call on this chain - const dotApi = client.getTypedApi(dot); - - ``` - -=== "Smoldot (Node.js)" - - ```typescript - // `dot` is the alias assigned during `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - import { getSmProvider } from 'polkadot-api/sm-provider'; - import { chainSpec } from 'polkadot-api/chains/polkadot'; - import { startFromWorker } from 'polkadot-api/smoldot/from-node-worker'; - import { fileURLToPath } from 'url'; - import { Worker } from 'worker_threads'; - - // Get the path for the worker file in ESM - const workerPath = fileURLToPath( - import.meta.resolve('polkadot-api/smoldot/node-worker'), - ); - - const worker = new Worker(workerPath); - const smoldot = startFromWorker(worker); - const chain = await smoldot.addChain({ chainSpec }); - - // Set up a client to connect to the Polkadot relay chain - const client = createClient(getSmProvider(chain)); - - // To interact with the chain's API, use `TypedApi` for access to - // all the necessary types and calls associated with this chain - const dotApi = client.getTypedApi(dot); - - ``` - -=== "Smoldot" - - ```typescript - // `dot` is the alias assigned when running `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - import { getSmProvider } from 'polkadot-api/sm-provider'; - import { chainSpec } from 'polkadot-api/chains/polkadot'; - import { start } from 'polkadot-api/smoldot'; - - // Initialize Smoldot client - const smoldot = start(); - const chain = await smoldot.addChain({ chainSpec }); - - // Set up a client to connect to the Polkadot relay chain - const client = createClient(getSmProvider(chain)); - - // Access the `TypedApi` to interact with all available chain calls and types - const dotApi = client.getTypedApi(dot); - - ``` - -=== "WSS" - - ```typescript - // `dot` is the identifier assigned when executing `npx papi add` - import { dot } from '@polkadot-api/descriptors'; - import { createClient } from 'polkadot-api'; - // Use this import for Node.js environments - import { getWsProvider } from 'polkadot-api/ws-provider/web'; - import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat'; - - // Establish a connection to the Polkadot relay chain - const client = createClient( - // The Polkadot SDK nodes may have compatibility issues; using this enhancer is recommended. - // Refer to the Requirements page for additional details - withPolkadotSdkCompat(getWsProvider('wss://dot-rpc.stakeworld.io')), - ); - - // To interact with the chain, obtain the `TypedApi`, which provides - // the types for all available calls in that chain - const dotApi = client.getTypedApi(dot); - - ``` - -Now that you have set up the client, you can interact with the chain by reading and sending transactions. - -### Reading Chain Data - -The `TypedApi` provides a streamlined way to read blockchain data through three main interfaces, each designed for specific data access patterns: - -- **Constants**: Access fixed values or configurations on the blockchain using the `constants` interface. - - ```typescript - const version = await typedApi.constants.System.Version(); - ``` - -- **Storage queries**: Retrieve stored values by querying the blockchain’s storage via the `query` interface. - - ```typescript - const asset = await api.query.ForeignAssets.Asset.getValue( - token.location, - { at: 'best' }, - ); - ``` - -- **Runtime APIs**: Interact directly with runtime APIs using the `apis` interface. - - ```typescript - const metadata = await typedApi.apis.Metadata.metadata(); - ``` - -To learn more about the different actions you can perform with the `TypedApi`, refer to the [TypedApi reference](https://papi.how/typed){target=\_blank}. - -### Sending Transactions - -In PAPI, the `TypedApi` provides the `tx` and `txFromCallData` methods to send transactions. - -- The `tx` method allows you to directly send a transaction with the specified parameters by using the `typedApi.tx.Pallet.Call` pattern: - - ```typescript - const tx: Transaction = typedApi.tx.Pallet.Call({arg1, arg2, arg3}); - ``` - - For instance, to execute the `balances.transferKeepAlive` call, you can use the following snippet: - - ```typescript - import { MultiAddress } from '@polkadot-api/descriptors'; - - const tx: Transaction = typedApi.tx.Balances.transfer_keep_alive({ - dest: MultiAddress.Id('INSERT_DESTINATION_ADDRESS'), - value: BigInt(INSERT_VALUE), - }); - - ``` - - Ensure you replace `INSERT_DESTINATION_ADDRESS` and `INSERT_VALUE` with the actual destination address and value, respectively. - -- The `txFromCallData` method allows you to send a transaction using the call data. This option accepts binary call data and constructs the transaction from it. It validates the input upon creation and will throw an error if invalid data is provided. The pattern is as follows: - - ```typescript - const callData = Binary.fromHex('0x...'); - const tx: Transaction = typedApi.txFromCallData(callData); - ``` - - For instance, to execute a transaction using the call data, you can use the following snippet: - - ```typescript - const callData = Binary.fromHex('0x00002470617065726d6f6f6e'); - const tx: Transaction = typedApi.txFromCallData(callData); - ``` - -For more information about sending transactions, refer to the [Transactions](https://papi.how/typed/tx#transactions){target=\_blank} page. - -## Where to Go Next - -For an in-depth guide on how to use PAPI, refer to the official [PAPI](https://papi.how/){target=\_blank} documentation. diff --git a/.ai/pages/reference-tools-paraspell.md b/.ai/pages/reference-tools-paraspell.md deleted file mode 100644 index f285118e8..000000000 --- a/.ai/pages/reference-tools-paraspell.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: ParaSpell XCM SDK -description: A powerful open-source library that simplifies XCM integration, enabling developers to easily build interoperable dApps on Polkadot. -url: https://docs.polkadot.com/reference/tools/paraspell/ ---- - -# ParaSpell XCM SDK - -## Introduction - -[ParaSpell](https://paraspell.github.io/docs/){target=\_blank} is a comprehensive suite of open-source tools designed to simplify cross-chain interactions within the Polkadot ecosystem. At its core, ParaSpell is dedicated to enhancing the functionality of the [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\_blank} protocol by providing developers with a unified and streamlined experience for building interoperable decentralized applications (dApps). - -The primary goal of ParaSpell is to abstract away the complexities of the XCM protocol. While XCM is a powerful feature of the Polkadot network, its implementation can vary significantly between different parachains. ParaSpell addresses this challenge by providing a standardized set of tools that enable developers to easily integrate cross-chain functionality into their applications, saving valuable time and effort. ParaSpell is a "common good" software, meaning it is free, open-source, and dedicated to the growth of the Polkadot ecosystem. - -The ParaSpell suite includes: - -- **[XCM SDK](https://paraspell.xyz/#xcm-sdk){target=\_blank}**: Provides a unified layer to incorporate XCM into decentralized applications, simplifying complex cross-chain interactions. -- **[XCM API](https://paraspell.xyz/#xcm-api){target=\_blank}**: Offers an efficient, package-free approach to integrating XCM functionality while offloading heavy computing tasks, minimizing costs and improving application performance. -- **[XCM Router](https://paraspell.xyz/#xcm-router){target=\_blank}**: Enables cross-chain asset swaps in a single command, allowing developers to send one asset type (such as DOT on Polkadot) and receive a different asset on another chain (like ASTR on Astar). -- **[XCM Analyser](https://paraspell.xyz/#xcm-analyser){target=\_blank}**: Decodes and translates complex XCM multilocation data into readable information, supporting easier troubleshooting and debugging. -- **[XCM Visualizator](https://paraspell.xyz/#xcm-visualizator){target=\_blank}**: A tool designed to give developers a clear, interactive view of XCM activity across the Polkadot ecosystem, providing insights into cross-chain communication flow. -- **[XCM Playground](https://paraspell.xyz/#try-it){target=\_blank}**: An interactive playground for testing different XCM scenarios. - -### ParaSpell XCM SDK - -The [ParaSpell XCM SDK](https://paraspell.github.io/docs/sdk/getting-started.html){target=\_blank} is a core component of the ParaSpell toolset and a foundational library for developers looking to leverage XCM in their applications. It is the first and only XCM SDK in the ecosystem to support both PolkadotJS and Polkadot API, providing developers with flexibility and choice. - -The SDK simplifies the process of creating and sending XCM messages by providing a user-friendly builder pattern. This allows developers to construct complex XCM calls with just a few lines of code, reducing the likelihood of errors and ensuring that messages are constructed correctly. - -By using the ParaSpell XCM SDK, developers can significantly accelerate their development workflow and build powerful, interoperable dApps that take full advantage of the Polkadot network's cross-chain capabilities. - -## Install ParaSpell - -If you want to use ParaSpell in your project you can add it as a dependency with the following command: - -=== "npm" - - ```bash - npm install --save @paraspell/sdk@11.12.6 - ``` - -=== "pnpm" - - ```bash - pnpm add @paraspell/sdk@11.12.6 - ``` - -=== "yarn" - - ```bash - yarn add @paraspell/sdk@11.12.6 - ``` - - -## Where to Go Next - -Explore more about ParaSpell through these resources: - -
    - -- Tutorial __Transfer Assets Between Parachains__ - - --- - - Learn how to transfer assets across chains with ParaSpell. - - [:octicons-arrow-right-24: Get Started](/chain-interactions/send-transactions/interoperability/transfer-assets-parachains/) - -
    diff --git a/.ai/pages/reference-tools-polkadart.md b/.ai/pages/reference-tools-polkadart.md deleted file mode 100644 index 7ea7262dd..000000000 --- a/.ai/pages/reference-tools-polkadart.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: Polkadart -description: Polkadart is a type-safe, native Dart, SDK for Polkadot and any compatible Polkadot-SDK blockchain network. -categories: Tooling, Dapps -url: https://docs.polkadot.com/reference/tools/polkadart/ ---- - -# Polkadart - -Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications. - -This page will outline some of the core components of Polkadart. For more details, refer to the [official documentation](https://polkadart.dev){target=\_blank}. - -## Installation - -Add Polkadart to your `pubspec.yaml`: - -=== "All packages" - - ```bash - dart pub add polkadart polkadart_cli polkadart_keyring polkadart_scale_codec secp256k1_ecdsa sr25519 ss58 substrate_bip39 substrate_metadata - ``` - -=== "Core only" - - ```bash - dart pub add polkadart polkadart_cli polkadart_keyring - ``` - -For type-safe API generation, add the following to your `pubspec.yaml`: - -{% raw %} -```yaml title="pubspec.yaml" -polkadart: - output_dir: lib/generated - chains: - polkadot: wss://rpc.polkadot.io - kusama: wss://kusama-rpc.polkadot.io - custom: wss://your-node.example.com -``` -{% endraw %} - -## Get Started - -### Type Generation - -Polkadart provides a CLI tool to generate type definitions from any Polkadot-SDK compatible blockchain network. This allows you to build type-safe Dart applications without dealing with the low-level details of the blockchain. - -### Run Generator - -```bash -dart run polkadart_cli:generate -v -``` - -### Use Generated Types - -```dart -import 'package:your_app/generated/polkadot/polkadot.dart'; -import 'package:polkadart/polkadart.dart'; -import 'package:ss58/ss58.dart'; - -final provider = Provider.fromUri(Uri.parse('wss://rpc.polkadot.io')); -final polkadot = Polkadot(provider); - -// Account from SS58 address -final account = Address.decode('19t9Q2ay58hMDaeg6eeBhqmHsRnc2jDMV3cYYw9zbc59HLj'); - -// Retrieve Account Balance -final accountInfo = await polkadot.query.system.account(account.pubkey); -print('Balance: ${accountInfo.data.free}') -``` - -### Creating an API Instance - -An API instance is required to interact with the blockchain. Polkadart provides a `Provider` class that allows you to connect to any network. - -```dart -import 'package:demo/generated/polkadot/polkadot.dart'; -import 'package:polkadart/provider.dart'; - -Future main(List arguments) async { - final provider = Provider.fromUri(Uri.parse('wss://rpc.polkadot.io')); - final polkadot = Polkadot(provider); -} -``` - -### Reading Chain Data - -Besides querying the data using the `query` from the generated API, you can also use the State API for querying storage data, metadata, runtime information, and other chain information. - -```dart -final stateApi = StateApi(provider); - -// Get current runtime version -final runtimeVersion = await stateApi.getRuntimeVersion(); -print(runtimeVersion.toJson()); - -// Get metadata -final metadata = await stateApi.getMetadata(); -print('Metadata version: ${metadata.version}'); -``` - -### Subscribe to New Blocks - -You can subscribe to new blocks on the blockchain using the `subscribe` method. - -```dart -final subscription = await provider.subscribe('chain_subscribeNewHeads', []); - -subscription.stream.forEach((response) { - print('New head: ${response.result}'); -}); -``` - -### Send a Transaction - -Perhaps the most common operation done in any blockchain is transferring funds. Here you can see how that can be done using Polkadart: - -```dart -final wallet = await KeyPair.sr25519.fromUri("//Alice"); -print('Alice\' wallet: ${wallet.address}'); - -// Get information necessary to build a proper extrinsic -final runtimeVersion = await polkadot.rpc.state.getRuntimeVersion(); -final currentBlockNumber = (await polkadot.query.system.number()) - 1; -final currentBlockHash = await polkadot.query.system.blockHash(currentBlockNumber); -final genesisHash = await polkadot.query.system.blockHash(0); -final nonce = await polkadot.rpc.system.accountNextIndex(wallet.address); - -// Make the encoded call -final multiAddress = $MultiAddress().id(wallet.publicKey.bytes); -final transferCall = polkadot.tx.balances.transferKeepAlive(dest: multiAddress, value: BigInt.one).encode(); - -// Make the payload -final payload = SigningPayload( - method: transferCall, - specVersion: runtimeVersion.specVersion, - transactionVersion: runtimeVersion.transactionVersion, - genesisHash: encodeHex(genesisHash), - blockHash: encodeHex(currentBlockHash), - blockNumber: currentBlockNumber, - eraPeriod: 64, - nonce: nonce, - tip: 0, -).encode(polkadot.registry); - -// Sign the payload and build the final extrinsic -final signature = wallet.sign(payload); -final extrinsic = ExtrinsicPayload( - signer: wallet.bytes(), - method: transferCall, - signature: signature, - eraPeriod: 64, - blockNumber: currentBlockNumber, - nonce: nonce, - tip: 0, -).encode(polkadot.registry, SignatureType.sr25519); - -// Send the extrinsic to the blockchain -final author = AuthorApi(provider); -await author.submitAndWatchExtrinsic(extrinsic, (data) { - print(data); -}); -``` - -## Where to Go Next - -To dive deeper into Polkadart, refer to the [official Polkadart documentation](https://polkadart.dev/){target=\_blank}, where you can find comprehensive guides for common use cases and advanced usage. diff --git a/.ai/pages/reference-tools-polkadot-js-api.md b/.ai/pages/reference-tools-polkadot-js-api.md deleted file mode 100644 index d04cab65a..000000000 --- a/.ai/pages/reference-tools-polkadot-js-api.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Polkadot.js API -description: Interact with Polkadot SDK-based chains easily using the Polkadot.js API. Query chain data, submit transactions, and more via JavaScript or Typescript. -categories: Tooling, Dapps -url: https://docs.polkadot.com/reference/tools/polkadot-js-api/ ---- - -# Polkadot.js API - -!!! warning "Maintenance Mode Only" - The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\_blank} (modern, type-safe API) as actively maintained alternatives. - -## Introduction - -The [Polkadot.js API](https://github.com/polkadot-js/api){target=\_blank} uses JavaScript/TypeScript to interact with Polkadot SDK-based chains. It allows you to query nodes, read chain state, and submit transactions through a dynamic, auto-generated API interface. - -### Dynamic API Generation - -Unlike traditional static APIs, the Polkadot.js API generates its interfaces automatically when connecting to a node. Here's what happens when you connect: - -1. The API connects to your node. -2. It retrieves the chain's metadata. -3. Based on this metadata, it creates specific endpoints in this format: `api...
    `. - -### Available API Categories - -You can access three main categories of chain interactions: - -- **[Runtime constants](https://polkadot.js.org/docs/api/start/api.consts){target=\_blank}** (`api.consts`): - - - Access runtime constants directly. - - Returns values immediately without function calls. - - **Example**: `api.consts.balances.existentialDeposit` - -- **[State queries](https://polkadot.js.org/docs/api/start/api.query/){target=\_blank}** (`api.query`): - - - Read chain state. - - **Example**: `api.query.system.account(accountId)` - -- **[Transactions](https://polkadot.js.org/docs/api/start/api.tx/){target=\_blank}** (`api.tx`): - - Submit extrinsics (transactions). - - **Example**: `api.tx.balances.transfer(accountId, value)` - -The available methods and interfaces will automatically reflect what's possible on your connected chain. - -## Installation - -To add the Polkadot.js API to your project, use the following command to install the version `16.4.7` which supports any Polkadot SDK-based chain: - -=== "npm" - ```bash - npm i @polkadot/api@16.4.7 - ``` - -=== "pnpm" - ```bash - pnpm add @polkadot/api@16.4.7 - ``` - -=== "yarn" - ```bash - yarn add @polkadot/api@16.4.7 - ``` - -For more detailed information about installation, see the [Installation](https://polkadot.js.org/docs/api/start/install/){target=\_blank} section in the official Polkadot.js API documentation. - -## Get Started - -### Creating an API Instance - -To interact with a Polkadot SDK-based chain, you must establish a connection through an API instance. The API provides methods for querying chain state, sending transactions, and subscribing to updates. - -To create an API connection: - -```js -import { ApiPromise, WsProvider } from '@polkadot/api'; - -// Create a WebSocket provider -const wsProvider = new WsProvider('wss://rpc.polkadot.io'); - -// Initialize the API -const api = await ApiPromise.create({ provider: wsProvider }); - -// Verify the connection by getting the chain's genesis hash -console.log('Genesis Hash:', api.genesisHash.toHex()); - -``` - -!!!warning - All `await` operations must be wrapped in an async function or block since the API uses promises for asynchronous operations. - -### Reading Chain Data - -The API provides several ways to read data from the chain. You can access: - -- **Constants**: Values that are fixed in the runtime and don't change without a runtime upgrade. - - ```js - // Get the minimum balance required for a new account - const minBalance = api.consts.balances.existentialDeposit.toNumber(); - - ``` - -- **State**: Current chain state that updates with each block. - - ```js - // Example address - const address = '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE'; - - // Get current timestamp - const timestamp = await api.query.timestamp.now(); - - // Get account information - const { nonce, data: balance } = await api.query.system.account(address); - - console.log(` - Timestamp: ${timestamp} - Free Balance: ${balance.free} - Nonce: ${nonce} - `); - - ``` - -### Sending Transactions - -Transactions (also called extrinsics) modify the chain state. Before sending a transaction, you need: - -- A funded account with sufficient balance to pay transaction fees. -- The account's keypair for signing. - -To make a transfer: - -```js -// Assuming you have an `alice` keypair from the Keyring -const recipient = 'INSERT_RECIPIENT_ADDRESS'; -const amount = 'INSERT_VALUE'; // Amount in the smallest unit (e.g., Planck for DOT) - -// Sign and send a transfer -const txHash = await api.tx.balances - .transfer(recipient, amount) - .signAndSend(alice); - -console.log('Transaction Hash:', txHash); - -``` - -The `alice` keypair in the example comes from a `Keyring` object. For more details about managing keypairs, see the [Keyring documentation](https://polkadot.js.org/docs/keyring){target=\_blank}. - -## Where to Go Next - -For more detailed information about the Polkadot.js API, check the [official documentation](https://polkadot.js.org/docs/){target=\_blank}. diff --git a/.ai/pages/reference-tools-py-substrate-interface.md b/.ai/pages/reference-tools-py-substrate-interface.md deleted file mode 100644 index d719afeb0..000000000 --- a/.ai/pages/reference-tools-py-substrate-interface.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: Python Substrate Interface -description: Learn how to connect to Polkadot SDK-based nodes, query data, submit transactions, and manage blockchain interactions using the Python Substrate Interface. -categories: Tooling, Dapps -url: https://docs.polkadot.com/reference/tools/py-substrate-interface/ ---- - -# Python Substrate Interface - -## Introduction - -The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for: - -- Querying on-chain storage. -- Composing and submitting extrinsics. -- SCALE encoding/decoding. -- Interacting with Substrate runtime metadata. -- Managing blockchain interactions through convenient utility methods. - -## Installation - -Install the library using `pip`: - -```py -pip install substrate-interface -``` - -For more installation details, see the [Installation](https://jamdottech.github.io/py-polkadot-sdk/getting-started/installation/){target=\_blank} section in the official Python Substrate Interface documentation. - -## Get Started - -This guide will walk you through the basic operations with the Python Substrate Interface: connecting to a node, reading chain state, and submitting transactions. - -### Establishing Connection - -The first step is to establish a connection to a Polkadot SDK-based node. You can connect to either a local or remote node: - -```py -from substrateinterface import SubstrateInterface - -# Connect to a node using websocket -substrate = SubstrateInterface( - # For local node: "ws://127.0.0.1:9944" - # For Polkadot: "wss://rpc.polkadot.io" - # For Kusama: "wss://kusama-rpc.polkadot.io" - url="INSERT_WS_URL" -) - -# Verify connection -print(f"Connected to chain: {substrate.chain}") - -``` - -### Reading Chain State - -You can query various on-chain storage items. To retrieve data, you need to specify three key pieces of information: - -- **Pallet name**: Module or pallet that contains the storage item you want to access. -- **Storage item**: Specific storage entry you want to query within the pallet. -- **Required parameters**: Any parameters needed to retrieve the desired data. - -Here's an example of how to check an account's balance and other details: - -```py -# ... - -# Query account balance and info -account_info = substrate.query( - module="System", # The pallet name - storage_function="Account", # The storage item - params=["INSERT_ADDRESS"], # Account address in SS58 format -) - -# Access account details from the result -free_balance = account_info.value["data"]["free"] -reserved = account_info.value["data"]["reserved"] -nonce = account_info.value["nonce"] - -print( - f""" - Account Details: - - Free Balance: {free_balance} - - Reserved: {reserved} - - Nonce: {nonce} - """ -) - -``` - -### Submitting Transactions - -To modify the chain state, you need to submit transactions (extrinsics). Before proceeding, ensure you have: - -- A funded account with sufficient balance to pay transaction fees. -- Access to the account's keypair. - -Here's how to create and submit a balance transfer: - -```py -#... - -# Compose the transfer call -call = substrate.compose_call( - call_module="Balances", # The pallet name - call_function="transfer_keep_alive", # The extrinsic function - call_params={ - 'dest': 'INSERT_ADDRESS', # Recipient's address - 'value': 'INSERT_VALUE' # Amount in smallest unit (e.g., Planck for DOT) - } -) - -# Create a signed extrinsic -extrinsic = substrate.create_signed_extrinsic( - call=call, keypair=keypair # Your keypair for signing -) - -# Submit and wait for inclusion -receipt = substrate.submit_extrinsic( - extrinsic, wait_for_inclusion=True # Wait until the transaction is in a block -) - -if receipt.is_success: - print( - f""" - Transaction successful: - - Extrinsic Hash: {receipt.extrinsic_hash} - - Block Hash: {receipt.block_hash} - """ - ) -else: - print(f"Transaction failed: {receipt.error_message}") - -``` - -The `keypair` object is essential for signing transactions. See the [Keypair](https://jamdottech.github.io/py-polkadot-sdk/reference/keypair/){target=\_blank} documentation for more details. - -## Where to Go Next - -Now that you understand the basics, you can: - -- Explore more complex queries and transactions. -- Learn about batch transactions and utility functions. -- Discover how to work with custom pallets and types. - -For comprehensive reference materials and advanced features, see the [Python Substrate Interface](https://jamdottech.github.io/py-polkadot-sdk/){target=\_blank} documentation. diff --git a/.ai/pages/reference-tools-sidecar.md b/.ai/pages/reference-tools-sidecar.md deleted file mode 100644 index 5ea46ab69..000000000 --- a/.ai/pages/reference-tools-sidecar.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -title: Sidecar REST API -description: Learn about Substrate API Sidecar, a REST service that provides endpoints for interacting with Polkadot SDK-based chains and simplifies blockchain interactions. -categories: Tooling, Dapps -url: https://docs.polkadot.com/reference/tools/sidecar/ ---- - -# Sidecar API - -## Introduction - -The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more. - -Sidecar functions as a caching layer between your application and a Polkadot SDK-based node, offering standardized REST endpoints that simplify interactions without requiring complex, direct RPC calls. This approach is especially valuable for developers who prefer REST APIs or build applications in languages with limited WebSocket support. - -Some of the key features of the Sidecar API include: - -- **REST API interface**: Provides a familiar REST API interface for interacting with Polkadot SDK-based chains. -- **Standardized endpoints**: Offers consistent endpoint formats across different chain implementations. -- **Caching layer**: Acts as a caching layer to improve performance and reduce direct node requests. -- **Multiple chain support**: Works with any Polkadot SDK-based chain, including Polkadot, Kusama, and custom chains. - -## Prerequisites - -Sidecar API requires Node.js version 18.14 LTS or higher. Verify your Node.js version: - -```bash -node --version -``` - -If you need to install or update Node.js, visit the [official Node.js website](https://nodejs.org/){target=\_blank} to download and install the latest LTS version. - -## Installation - -To install Substrate API Sidecar, use one of the following commands: - -=== "npm" - - ```bash - npm install -g @substrate/api-sidecar - ``` - -=== "pnpm" - - ```bash - pnpm install -g @substrate/api-sidecar - ``` - -=== "yarn" - - ```bash - yarn global add @substrate/api-sidecar - ``` - -You can confirm the installation by running: - -```bash -substrate-api-sidecar --version -``` - -For more information about the Sidecar API installation, see the [installation and usage](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#npm-package-installation-and-usage){target=\_blank} section of the Sidecar API README. - -## Usage - -To use the Sidecar API, you have two options: - -- **Local node**: Run a node locally, which Sidecar will connect to by default, requiring no additional configuration. To start, run the following: - - ```bash - substrate-api-sidecar - ``` - -- **Remote node**: Connect Sidecar to a remote node by specifying the RPC endpoint for that chain. For example, to gain access to the Polkadot Asset Hub associated endpoints. - - ```bash - SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io substrate-api-sidecar - ``` - - For more configuration details, see the [Configuration](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#configuration){target=\_blank} section of the Sidecar API documentation. - -Once the Sidecar API is running, you’ll see output similar to this: - -
    - SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io substrate-api-sidecar -
    - SAS: - 📦 LOG: - ✅ LEVEL: "info" - ✅ JSON: false - ✅ FILTER_RPC: false - ✅ STRIP_ANSI: false - ✅ WRITE: false - ✅ WRITE_PATH: "/opt/homebrew/lib/node_modules/@substrate/api-sidecar/build/src/logs" - ✅ WRITE_MAX_FILE_SIZE: 5242880 - ✅ WRITE_MAX_FILES: 5 - 📦 SUBSTRATE: - ✅ URL: "wss://polkadot-asset-hub-rpc.polkadot.io" - ✅ TYPES_BUNDLE: undefined - ✅ TYPES_CHAIN: undefined - ✅ TYPES_SPEC: undefined - ✅ TYPES: undefined - ✅ CACHE_CAPACITY: undefined - 📦 EXPRESS: - ✅ BIND_HOST: "127.0.0.1" - ✅ PORT: 8080 - ✅ KEEP_ALIVE_TIMEOUT: 5000 - 📦 METRICS: - ✅ ENABLED: false - ✅ PROM_HOST: "127.0.0.1" - ✅ PROM_PORT: 9100 - ✅ LOKI_HOST: "127.0.0.1" - ✅ LOKI_PORT: 3100 - ✅ INCLUDE_QUERYPARAMS: false -
    - 2024-11-06 08:06:01 info: Version: 19.3.0 - 2024-11-06 08:06:02 warn: API/INIT: RPC methods not decorated: chainHead_v1_body, chainHead_v1_call, chainHead_v1_continue, chainHead_v1_follow, chainHead_v1_header, chainHead_v1_stopOperation, chainHead_v1_storage, chainHead_v1_unfollow, chainHead_v1_unpin, chainSpec_v1_chainName, chainSpec_v1_genesisHash, chainSpec_v1_properties, transactionWatch_v1_submitAndWatch, transactionWatch_v1_unwatch, transaction_v1_broadcast, transaction_v1_stop - 2024-11-06 08:06:02 info: Connected to chain Polkadot Asset Hub on the statemint client at wss://polkadot-asset-hub-rpc.polkadot.io - 2024-11-06 08:06:02 info: Listening on http://127.0.0.1:8080/ - 2024-11-06 08:06:02 info: Check the root endpoint (http://127.0.0.1:8080/) to see the available endpoints for the current node -
    -With Sidecar running, you can access the exposed endpoints via a browser, [`Postman`](https://www.postman.com/){target=\_blank}, [`curl`](https://curl.se/){target=\_blank}, or your preferred tool. - -### Endpoints - -Sidecar API provides a set of REST endpoints that allow you to query different aspects of the chain, including blocks, accounts, and transactions. Each endpoint offers specific insights into the chain’s state and activities. - -For example, to retrieve the version of the node, use the `/node/version` endpoint: - -```bash -curl -X 'GET' \ - 'http://127.0.0.1:8080/node/version' \ - -H 'accept: application/json' -``` - -Alternatively, you can access `http://127.0.0.1:8080/node/version` directly in a browser since it’s a `GET` request. - -In response, you’ll see output similar to this (assuming you’re connected to Polkadot Asset Hub): - -
    - curl -X 'GET' 'http://127.0.0.1:8080/node/version' -H 'accept: application/json' -
    - { - "clientVersion": "1.16.1-835e0767fe8", - "clientImplName": "statemint", - "chain": "Polkadot Asset Hub" - } -
    -For a complete list of available endpoints and their documentation, visit the [Sidecar API list endpoints](https://paritytech.github.io/substrate-api-sidecar/dist/){target=\_blank}. You can learn about the endpoints and how to use them in your applications. - -## Where to Go Next - -To dive deeper, refer to the [official Sidecar documentation](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#substrateapi-sidecar){target=\_blank}. This provides a comprehensive guide to the available configurations and advanced usage. diff --git a/.ai/pages/reference-tools-subxt.md b/.ai/pages/reference-tools-subxt.md deleted file mode 100644 index d0406c923..000000000 --- a/.ai/pages/reference-tools-subxt.md +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: Subxt Rust API -description: Subxt is a Rust library for type-safe interaction with Polkadot SDK blockchains, enabling transactions, state queries, runtime API access, and more. -categories: Tooling, Dapps -url: https://docs.polkadot.com/reference/tools/subxt/ ---- - -# Subxt Rust API - -## Introduction - -Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability. - -## Prerequisites - -Before using subxt, ensure you have the following requirements: - -- Rust and Cargo installed on your system. You can install them using [Rustup](https://rustup.rs/){target=\_blank}. -- A Rust project initialized. If you don't have one, create it with: - ```bash - cargo new my_project && cd my_project - ``` - -## Installation - -To use subxt in your project, you must install the necessary dependencies. Each plays a specific role in enabling interaction with the blockchain: - -1. **Install the subxt CLI**: [`subxt-cli`](https://crates.io/crates/subxt-cli){target=\_blank} is a command-line tool that provides utilities for working with Polkadot SDK metadata. In the context of subxt, it is essential to download chain metadata, which is required to generate type-safe Rust interfaces for interacting with the blockchain. Install it using the following: - - ```bash - cargo install subxt-cli@0.44.0 - ``` - -2. **Add core dependencies**: These dependencies are essential for interacting with the blockchain. - - - **[subxt](https://crates.io/crates/subxt){target=\_blank}**: The main library for communicating with Polkadot SDK nodes. It handles RPC requests, encoding/decoding, and type generation. - - ```bash - cargo add subxt@0.44.0 - ``` - - - **[subxt-signer](https://crates.io/crates/subxt-signer){target=\_blank}**: Provides cryptographic functionality for signing transactions. Without this, you can only read data but cannot submit transactions. - - ```bash - cargo add subxt-signer@0.44.0 - ``` - - - **[tokio](https://crates.io/crates/tokio){target=\_blank}**: An asynchronous runtime for Rust. Since blockchain operations are async, Tokio enables the efficient handling of network requests. The `rt` feature enables Tokio's runtime, including the current-thread single-threaded scheduler, which is necessary for async execution. The `macros` feature provides procedural macros like `#[tokio::main]` to simplify runtime setup. - - ```bash - cargo add tokio@1.44.2 --features rt,macros - ``` - - After adding the dependencies, your `Cargo.toml` should look like this: - - ```toml - [package] - name = "my_project" - version = "0.1.0" - edition = "2021" - - [dependencies] - subxt = "0.41.0" - subxt-signer = "0.41.0" - tokio = { version = "1.44.2", features = ["rt", "macros"] } - - ``` - -## Get Started - -This guide will walk you through the fundamental operations of subxt, from setting up your environment to executing transactions and querying blockchain state. - -### Download Chain Metadata - -Before interacting with a blockchain, you need to retrieve its metadata. This metadata defines storage structures, extrinsics, and other runtime details. Use the `subxt-cli` tool to download the metadata, replacing `INSERT_NODE_URL` with the URL of the node you want to interact with: - -```bash -subxt metadata --url INSERT_NODE_URL > polkadot_metadata.scale -``` - -### Generate Type-Safe Interfaces - -Use the `#[subxt::subxt]` macro to generate a type-safe Rust interface from the downloaded metadata: - -```rust -// Generate an interface that we can use from the node's metadata. -#[subxt::subxt(runtime_metadata_path = "./polkadot_metadata.scale")] -pub mod polkadot {} -``` - -Once subxt interfaces are generated, you can interact with your node in the following ways. You can use the links below to view the related subxt documentation: - -- **[Transactions](https://docs.rs/subxt/latest/subxt/book/usage/transactions/index.html){target=\_blank}**: Builds and submits transactions, monitors their inclusion in blocks, and retrieves associated events. -- **[Storage](https://docs.rs/subxt/latest/subxt/book/usage/storage/index.html){target=\_blank}**: Enables querying of node storage data. -- **[Events](https://docs.rs/subxt/latest/subxt/book/usage/events/index.html){target=\_blank}**: Retrieves events emitted from recent blocks. -- **[Constants](https://docs.rs/subxt/latest/subxt/book/usage/constants/index.html){target=\_blank}**: Accesses constant values stored in nodes that remain unchanged across a specific runtime version. -- **[Blocks](https://docs.rs/subxt/latest/subxt/book/usage/blocks/index.html){target=\_blank}**: Loads recent blocks or subscribes to new/finalized blocks, allowing examination of extrinsics, events, and storage at those blocks. -- **[Runtime APIs](https://docs.rs/subxt/latest/subxt/book/usage/runtime_apis/index.html){target=\_blank}**: Makes calls into pallet runtime APIs to fetch data. -- **[Custom values](https://docs.rs/subxt/latest/subxt/book/usage/custom_values/index.html){target=\_blank}**: Accesses "custom values" contained within metadata. -- **[Raw RPC calls](https://docs.rs/subxt/latest/subxt/book/usage/rpc/index.html){target=\_blank}**: Facilitates raw RPC requests to compatible nodes. - -### Initialize the Subxt Client - -To interact with a blockchain node using subxt, create an asynchronous main function and initialize the client. Replace `INSERT_NODE_URL` with the URL of your target node: - -```rust -use std::str::FromStr; -use subxt::utils::AccountId32; -use subxt::{OnlineClient, PolkadotConfig}; -use subxt_signer::{bip39::Mnemonic,sr25519::Keypair}; - -// Generate an interface that we can use from the node's metadata. -#[subxt::subxt(runtime_metadata_path = "./polkadot_metadata.scale")] -pub mod polkadot {} - -#[tokio::main(flavor = "current_thread")] -async fn main() -> Result<(), Box> { - // Define the node URL. - const NODE_URL: &str = "INSERT_NODE_URL"; - - // Initialize the Subxt client to interact with the blockchain. - let api = OnlineClient::::from_url(NODE_URL).await?; - - // Your code here... - - Ok(()) -} -``` - -### Read Chain Data - -subxt provides multiple ways to access on-chain data: - -- **Constants**: Constants are predefined values in the runtime that remain unchanged unless modified by a runtime upgrade. - - For example, to retrieve the existential deposit, use: - - ```rust - // A query to obtain some constant. - let constant_query = polkadot::constants().balances().existential_deposit(); - - // Obtain the value. - let value = api.constants().at(&constant_query)?; - - println!("Existential deposit: {:?}", value); - ``` - -- **State**: State refers to the current chain data, which updates with each block. - - To fetch account information, replace `INSERT_ADDRESS` with the address you want to fetch data from and use: - - ```rust - // Define the target account address. - const ADDRESS: &str = "INSERT_ADDRESS"; - let account = AccountId32::from_str(ADDRESS).unwrap(); - - // Build a storage query to access account information. - let storage_query = polkadot::storage().system().account(&account.into()); - - // Fetch the latest state for the account. - let result = api - .storage() - .at_latest() - .await? - .fetch(&storage_query) - .await? - .unwrap(); - - println!("Account info: {:?}", result); - ``` - -### Submit Transactions - -To submit a transaction, you must construct an extrinsic, sign it with your private key, and send it to the blockchain. Replace `INSERT_DEST_ADDRESS` with the recipient's address, `INSERT_AMOUNT` with the amount to transfer, and `INSERT_SECRET_PHRASE` with the sender's mnemonic phrase: - -```rust - // Define the recipient address and transfer amount. - const DEST_ADDRESS: &str = "INSERT_DEST_ADDRESS"; - const AMOUNT: u128 = INSERT_AMOUNT; - - // Convert the recipient address into an `AccountId32`. - let dest = AccountId32::from_str(DEST_ADDRESS).unwrap(); - - // Build the balance transfer extrinsic. - let balance_transfer_tx = polkadot::tx() - .balances() - .transfer_allow_death(dest.into(), AMOUNT); - - // Load the sender's keypair from a mnemonic phrase. - const SECRET_PHRASE: &str = "INSERT_SECRET_PHRASE"; - let mnemonic = Mnemonic::parse(SECRET_PHRASE).unwrap(); - let sender_keypair = Keypair::from_phrase(&mnemonic, None).unwrap(); - - // Sign and submit the extrinsic, then wait for it to be finalized. - let events = api - .tx() - .sign_and_submit_then_watch_default(&balance_transfer_tx, &sender_keypair) - .await? - .wait_for_finalized_success() - .await?; - - // Check for a successful transfer event. - if let Some(event) = events.find_first::()? { - println!("Balance transfer successful: {:?}", event); - } -``` - -## Where to Go Next - -Now that you've covered the basics dive into the official [subxt documentation](https://docs.rs/subxt/latest/subxt/book/index.html){target=\_blank} for comprehensive reference materials and advanced features. diff --git a/.ai/pages/reference-tools-xcm-tools.md b/.ai/pages/reference-tools-xcm-tools.md deleted file mode 100644 index dad6dfb50..000000000 --- a/.ai/pages/reference-tools-xcm-tools.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: XCM Tools -description: Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. -categories: Basics, Tooling, Dapps -url: https://docs.polkadot.com/reference/tools/xcm-tools/ ---- - -# XCM Tools - -## Introduction - -As described in the [Interoperability](/develop/interoperability){target=\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem. - -As XCM is central to enabling communication between blockchains, developers need robust tools to help interact with, build, and test XCM messages. Several XCM tools simplify working with the protocol by providing libraries, frameworks, and utilities that enhance the development process, ensuring that applications built within the Polkadot ecosystem can efficiently use cross-chain functionalities. - -## Popular XCM Tools - -### Moonsong Labs XCM Tools - -[Moonsong Labs XCM Tools](https://github.com/Moonsong-Labs/xcm-tools){target=\_blank} provides a collection of scripts for managing and testing XCM operations between Polkadot SDK-based runtimes. These tools allow performing tasks like asset registration, channel setup, and XCM initialization. Key features include: - -- **Asset registration**: Registers assets, setting units per second (up-front fees), and configuring error (revert) codes. -- **XCM initializer**: Initializes XCM, sets default XCM versions, and configures revert codes for XCM-related precompiles. -- **HRMP manipulator**: Manages HRMP channel actions, including opening, accepting, or closing channels. -- **XCM-Transactor-Info-Setter**: Configures transactor information, including extra weight and fee settings. -- **Decode XCM**: Decodes XCM messages on the relay chain or parachains to help interpret cross-chain communication. - -To get started, clone the repository and install the required dependencies: - -```bash -git clone https://github.com/Moonsong-Labs/xcm-tools && -cd xcm-tools && -yarn install -``` - -For a full overview of each script, visit the [scripts](https://github.com/Moonsong-Labs/xcm-tools/tree/main/scripts){target=\_blank} directory or refer to the [official documentation](https://github.com/Moonsong-Labs/xcm-tools/blob/main/README.md){target=\_blank} on GitHub. - -### ParaSpell - -[ParaSpell](/reference/tools/paraspell/){target=\_blank} is a collection of open-source XCM tools that streamline cross-chain asset transfers and interactions across the Polkadot and Kusama ecosystems. It provides developers with an intuitive interface to build, test, and deploy interoperable dApps, featuring message composition, decoding, and practical utilities for parachain interactions that simplify debugging and cross-chain communication optimization. - -### Astar XCM Tools - -The [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks: - -- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command. -- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments. -- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs. - -To start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\_blank} and compile the xcm-tools package: - -```bash -git clone https://github.com/AstarNetwork/Astar && -cd Astar && -cargo build --release -p xcm-tools -``` - -After compiling, verify the setup with the following command: - -```bash -./target/release/xcm-tools --help -``` -For more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\_blank}. - -### Chopsticks - -The Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\_blank} about XCM. - -### Moonbeam XCM SDK - -The [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\_blank} of the origin or destination assets or which extrinsics are used on which networks. - -The SDK consists of two main packages: - -- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem. -- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum. - -Key features include: - -- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection. -- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems. -- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality. -- **Comprehensive documentation**: Includes usage guides and API references for both packages. - -For detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\_blank}. diff --git a/.ai/pages/reference-tools-zombienet.md b/.ai/pages/reference-tools-zombienet.md deleted file mode 100644 index 0b80ea446..000000000 --- a/.ai/pages/reference-tools-zombienet.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/reference/tools/zombienet/ ---- - -TODO diff --git a/.ai/pages/reference.md b/.ai/pages/reference.md deleted file mode 100644 index 59bc64741..000000000 --- a/.ai/pages/reference.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Technical Reference Overview -description: Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. -categories: Basics, Polkadot Protocol, Reference -url: https://docs.polkadot.com/reference/ ---- - -## Introduction - -The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need. - -Polkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\_blank} to the [governance](/reference/glossary#governance){target=\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants. - -This guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem. - -## Polkadot Hub - -[Polkadot Hub](/reference/polkadot-hub/){target=\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain. - -The Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include: - -- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications. -- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem. -- **Staking**: Participate in network security and earn rewards by staking DOT. -- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov. -- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities. -- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem. -- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations. - -## Parachains - -[Parachains](/reference/parachains/){target=\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers: - -- **Accounts**: Deep dive into account types, storage, and management on parachains. -- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms. -- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus. -- **Chain data**: Explore data structures, storage layouts, and state management. -- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains. -- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility. -- **Networks**: Learn about networking protocols and peer-to-peer communication. -- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\_blank}, the standard for cross-chain communication. -- **Randomness**: Understand how randomness is generated and used in Polkadot chains. -- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\_blank}. - -## On-Chain Governance - -[On-Chain governance](/reference/governance/){target=\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details: - -- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums. -- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity. -- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance. -- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system. - -## Glossary - -The [Glossary](/reference/glossary/){target=\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include: - -- Blockchain concepts (blocks, transactions, state) -- Consensus mechanisms (validators, collators, finality) -- Polkadot-specific terms (relay chain, parachain, XCM, FRAME) -- Network components (nodes, runtimes, storage) -- Governance terminology (origins, tracks, referendums) - -## Tools - -The [Tools](/reference/tools/){target=\_blank} section documents essential development and interaction tools for the Polkadot ecosystem: - -- **Light clients**: Lightweight solutions for interacting with the network without running full nodes. -- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\_blank} and [PAPI](/reference/tools/papi/){target=\_blank} for building applications. -- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\_blank} and other Rust-based libraries for SDK development. -- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\_blank} for Python developers. -- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\_blank}, and [Omninode](/reference/tools/omninode/){target=\_blank} for smart contract and parachain testing. -- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\_blank} for substrate interaction. -- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\_blank} for XCM integration and asset transfers. - -## Where to Go Next - -For detailed exploration of specific areas, proceed to any of the main sections: - -
    - -- Learn **Polkadot Hub** - - --- - - Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance. - - [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/) - -- Learn **Parachains** - - --- - - Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains. - - [:octicons-arrow-right-24: Reference](/reference/parachains/) - -- Learn **On-Chain Governance** - - --- - - Explore Polkadot's decentralized governance framework and how to participate in network decision-making. - - [:octicons-arrow-right-24: Reference](/reference/governance/) - -- Guide **Glossary** - - --- - - Quick reference for Polkadot-specific terminology and concepts used throughout the documentation. - - [:octicons-arrow-right-24: Reference](/reference/glossary/) - -- Guide **Tools** - - --- - - Discover development tools, libraries, and frameworks for building and interacting with Polkadot. - - [:octicons-arrow-right-24: Reference](/reference/tools/) - -
    diff --git a/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md b/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md index b0cc72fa0..c97d65455 100644 --- a/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md +++ b/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md @@ -241,7 +241,7 @@ After deployment, you'll need the contract's Application Binary Interface (ABI) Now that you have your contract deployed, you're ready to build the dApp that will interact with it! -## Set Up the dApp Project +## Set Up the DApp Project Navigate to the root of the project, and create a new Next.js project called `dapp`: diff --git a/.ai/pages/smart-contracts-faucet.md b/.ai/pages/smart-contracts-faucet.md index 3cf7691c3..65da79ac1 100644 --- a/.ai/pages/smart-contracts-faucet.md +++ b/.ai/pages/smart-contracts-faucet.md @@ -1,5 +1,5 @@ --- -title: Faucet +title: Get Tokens from the Official Faucet description: Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. categories: Smart Contracts url: https://docs.polkadot.com/smart-contracts/faucet/ diff --git a/.ai/pages/smart-contracts-for-eth-devs-gas-model.md b/.ai/pages/smart-contracts-for-eth-devs-gas-model.md index cf3071ada..ebe94d4f0 100644 --- a/.ai/pages/smart-contracts-for-eth-devs-gas-model.md +++ b/.ai/pages/smart-contracts-for-eth-devs-gas-model.md @@ -6,7 +6,7 @@ url: https://docs.polkadot.com/smart-contracts/for-eth-devs/gas-model/ # Gas Model -## Overview +## Introduction The Polkadot Hub implements a gas model that bridges Ethereum's familiar gas concept with Polkadot's more sophisticated resource metering system. This page explains how gas works in the Polkadot Hub and what developers need to know when building smart contracts. diff --git a/.ai/pages/smart-contracts-integrations-.indexers.md b/.ai/pages/smart-contracts-integrations-.indexers.md new file mode 100644 index 000000000..8d162612d --- /dev/null +++ b/.ai/pages/smart-contracts-integrations-.indexers.md @@ -0,0 +1,5 @@ +--- +url: https://docs.polkadot.com/smart-contracts/integrations/.indexers/ +--- + +TODO diff --git a/.ai/pages/smart-contracts-integrations-.oracles.md b/.ai/pages/smart-contracts-integrations-.oracles.md new file mode 100644 index 000000000..2bedccd9e --- /dev/null +++ b/.ai/pages/smart-contracts-integrations-.oracles.md @@ -0,0 +1,5 @@ +--- +url: https://docs.polkadot.com/smart-contracts/integrations/.oracles/ +--- + +TODO diff --git a/.ai/pages/smart-contracts-integrations-indexers.md b/.ai/pages/smart-contracts-integrations-indexers.md deleted file mode 100644 index 492eac73a..000000000 --- a/.ai/pages/smart-contracts-integrations-indexers.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/smart-contracts/integrations/indexers/ ---- - -TODO diff --git a/.ai/pages/smart-contracts-integrations-oracles.md b/.ai/pages/smart-contracts-integrations-oracles.md deleted file mode 100644 index 942fc9a57..000000000 --- a/.ai/pages/smart-contracts-integrations-oracles.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -url: https://docs.polkadot.com/smart-contracts/integrations/oracles/ ---- - -TODO diff --git a/.ai/site-index.json b/.ai/site-index.json index ed6c41e58..46c15edae 100644 --- a/.ai/site-index.json +++ b/.ai/site-index.json @@ -1,3498 +1,213 @@ [ { - "id": "chain-interactions-accounts-create-account", - "title": "chain-interactions-accounts-create-account", - "slug": "chain-interactions-accounts-create-account", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-accounts-create-account.md", - "html_url": "https://docs.polkadot.com/chain-interactions/accounts/create-account/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-accounts-query-accounts", - "title": "chain-interactions-accounts-query-accounts", - "slug": "chain-interactions-accounts-query-accounts", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-accounts-query-accounts.md", - "html_url": "https://docs.polkadot.com/chain-interactions/accounts/query-accounts/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-query-data-query-rest", - "title": "chain-interactions-query-data-query-rest", - "slug": "chain-interactions-query-data-query-rest", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-query-data-query-rest.md", - "html_url": "https://docs.polkadot.com/chain-interactions/query-data/query-rest/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-query-data-query-sdks", - "title": "chain-interactions-query-data-query-sdks", - "slug": "chain-interactions-query-data-query-sdks", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-query-data-query-sdks.md", - "html_url": "https://docs.polkadot.com/chain-interactions/query-data/query-sdks/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-query-data-runtime-api-calls", - "title": "chain-interactions-query-data-runtime-api-calls", - "slug": "chain-interactions-query-data-runtime-api-calls", + "id": "get-support-ai-ready-docs", + "title": "AI Ready Docs", + "slug": "get-support-ai-ready-docs", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-query-data-runtime-api-calls.md", - "html_url": "https://docs.polkadot.com/chain-interactions/query-data/runtime-api-calls/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-send-transactions-calculate-transaction-fees", - "title": "chain-interactions-send-transactions-calculate-transaction-fees", - "slug": "chain-interactions-send-transactions-calculate-transaction-fees", - "categories": [ - "Uncategorized" + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-ai-ready-docs.md", + "html_url": "https://docs.polkadot.com/get-support/ai-ready-docs/", + "preview": "Polkadot provides files to make documentation content available in a structure optimized for use with large language models (LLMs) and AI tools. These resources help build AI assistants, power code search, or enable custom tooling trained on Polkadot’s documentation.", + "outline": [ + { + "depth": 2, + "title": "How to Use These Files", + "anchor": "how-to-use-these-files" + }, + { + "depth": 2, + "title": "Download LLM Files", + "anchor": "download-llm-files" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-calculate-transaction-fees.md", - "html_url": "https://docs.polkadot.com/chain-interactions/send-transactions/calculate-transaction-fees/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 7998, + "words": 825, + "headings": 2, + "estimated_token_count_total": 2232 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:5a8da69a5cea8bd598ee4d102b9abed5d1a29153802a567e22bb4ee720410b32", "token_estimator": "heuristic-v1" }, { - "id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", - "title": "Replay and Dry Run XCMs", - "slug": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", + "id": "get-support-explore-resources", + "title": "Subscribe to Updates", + "slug": "get-support-explore-resources", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-interoperability-debug-and-preview-xcms.md", - "html_url": "https://docs.polkadot.com/chain-interactions/send-transactions/interoperability/debug-and-preview-xcms/", - "preview": "In this tutorial, you'll learn how to replay and dry-run XCMs using [Chopsticks](/parachains/testing/fork-a-parachain/){target=\\_blank}, a powerful tool for forking live Polkadot SDK-based chains in your local environment. These techniques are essential for:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md", + "html_url": "https://docs.polkadot.com/get-support/explore-resources/", + "preview": "Looking for answers beyond the documentation? These platforms are full of useful content and experienced developers sharing insights.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Set Up Your Project", - "anchor": "set-up-your-project" + "title": "🧠 Stack Exchange", + "anchor": "stack-exchange" }, { "depth": 2, - "title": "Capture the XCM to Replay", - "anchor": "capture-the-xcm-to-replay" + "title": "🧵 Reddit: r/Polkadot", + "anchor": "reddit-rpolkadot" }, { "depth": 2, - "title": "Fork the Relevant Chains", - "anchor": "fork-the-relevant-chains" - }, - { - "depth": 3, - "title": "Set the Block Numbers", - "anchor": "set-the-block-numbers" - }, - { - "depth": 3, - "title": "Enable Logging and Wasm Override", - "anchor": "enable-logging-and-wasm-override" + "title": "💬 Discord (Community Threads Only)", + "anchor": "discord-community-threads-only" }, { "depth": 2, - "title": "Identify and Extract the XCM", - "anchor": "identify-and-extract-the-xcm" + "title": "🎥 YouTube: @PolkadotNetwork", + "anchor": "youtube-polkadotnetwork" }, { "depth": 2, - "title": "Replay the XCM", - "anchor": "replay-the-xcm" - }, - { - "depth": 3, - "title": "Add the Asset Hub Descriptor", - "anchor": "add-the-asset-hub-descriptor" + "title": "Community-Led Platforms and Ecosystem Updates", + "anchor": "community-led-platforms-and-ecosystem-updates" }, { "depth": 3, - "title": "Create a Replay Script", - "anchor": "create-a-replay-script" + "title": "🔷 X (Twitter): Official Accounts", + "anchor": "x-twitter-official-accounts" }, { "depth": 3, - "title": "Execute the Replay Script", - "anchor": "execute-the-replay-script" + "title": "🔁 X (Twitter): Community Accounts", + "anchor": "x-twitter-community-accounts" }, { "depth": 3, - "title": "Expected Output", - "anchor": "expected-output" - }, - { - "depth": 2, - "title": "Dry Run the XCM", - "anchor": "dry-run-the-xcm" + "title": "🗣️ Polkadot Forum", + "anchor": "polkadot-forum" }, { "depth": 3, - "title": "Create a Dry Run Script", - "anchor": "create-a-dry-run-script" + "title": "🧑‍⚖️ Polkassembly: OpenGov", + "anchor": "polkassembly-opengov" }, { "depth": 3, - "title": "Execute the Dry Run Script", - "anchor": "execute-the-dry-run-script" - }, - { - "depth": 2, - "title": "Review and Debug", - "anchor": "review-and-debug" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "📸 Instagram", + "anchor": "instagram" } ], "stats": { - "chars": 18942, - "words": 2362, - "headings": 18, - "estimated_token_count_total": 4830 + "chars": 2426, + "words": 295, + "headings": 10, + "estimated_token_count_total": 579 }, - "hash": "sha256:a6bf7623a535e7a9162c0913b07bd59d43c8535025ad8225fb3e5adc83084c7a", + "hash": "sha256:670221ac20ab1f1b550ba2a1db06cd924c24bd3afc4d8a768b617d8a409243cb", "token_estimator": "heuristic-v1" }, { - "id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", - "title": "XCM Fee Estimation", - "slug": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", + "id": "get-support-get-in-touch", + "title": "Get in Touch", + "slug": "get-support-get-in-touch", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-interoperability-estimate-xcm-fees.md", - "html_url": "https://docs.polkadot.com/chain-interactions/send-transactions/interoperability/estimate-xcm-fees/", - "preview": "When sending cross-chain messages, ensure that the transaction will be successful not only in the local chain but also in the destination chain and any intermediate chains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-get-in-touch.md", + "html_url": "https://docs.polkadot.com/get-support/get-in-touch/", + "preview": "Use one of the channels below to get live technical support or ask questions.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Fee Mechanism", - "anchor": "fee-mechanism" - }, - { - "depth": 2, - "title": "Environment Setup", - "anchor": "environment-setup" - }, - { - "depth": 2, - "title": "Client and API Setup", - "anchor": "client-and-api-setup" + "title": "Need Help Fast?", + "anchor": "need-help-fast" }, { "depth": 2, - "title": "Create the XCM Message", - "anchor": "create-the-xcm-message" + "title": "📱 Telegram: Polkadot Developer Support", + "anchor": "telegram-polkadot-developer-support" }, { "depth": 2, - "title": "Fee Estimation Function", - "anchor": "fee-estimation-function" + "title": "🔌 Discord: Polkadot Official Server", + "anchor": "discord-polkadot-official-server" }, { "depth": 2, - "title": "Complete Implementation", - "anchor": "complete-implementation" - }, + "title": "🧬 Matrix: Polkadot Developer Support", + "anchor": "matrix-polkadot-developer-support" + } + ], + "stats": { + "chars": 1949, + "words": 258, + "headings": 4, + "estimated_token_count_total": 557 + }, + "hash": "sha256:993e93b05c8fbdfc2f7510c61ac86bc4c2ff0f03e573695b2f260933c8b62f78", + "token_estimator": "heuristic-v1" + }, + { + "id": "get-support", + "title": "Support", + "slug": "get-support", + "categories": [ + "Uncategorized" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support.md", + "html_url": "https://docs.polkadot.com/get-support/", + "preview": "Use one of the channels below to get live technical support or ask questions.", + "outline": [ { "depth": 2, - "title": "Full Code", - "anchor": "full-code" + "title": "Need More than Just Documentation?", + "anchor": "need-more-than-just-documentation" }, { "depth": 2, - "title": "Running the Script", - "anchor": "running-the-script" + "title": "What You Can Do Here", + "anchor": "what-you-can-do-here" }, { "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" + "title": "Help Us Improve", + "anchor": "help-us-improve" } ], "stats": { - "chars": 38625, - "words": 3786, - "headings": 10, - "estimated_token_count_total": 7755 + "chars": 1658, + "words": 244, + "headings": 3, + "estimated_token_count_total": 280 }, - "hash": "sha256:086a87823ab67ceac102358030e316583cd733c0ec326316e7f29061fe7f6934", + "hash": "sha256:5bdc575ac798a971867a15651c2b4d5139bf0b1fe6854d1865deff280ae6d7f6", "token_estimator": "heuristic-v1" }, { - "id": "chain-interactions-send-transactions-interoperability-transfer-assets-out-of-polkadot", - "title": "chain-interactions-send-transactions-interoperability-transfer-assets-out-of-polkadot", - "slug": "chain-interactions-send-transactions-interoperability-transfer-assets-out-of-polkadot", + "id": "index", + "title": "Polkadot Developer Docs", + "slug": "index", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-out-of-polkadot.md", - "html_url": "https://docs.polkadot.com/chain-interactions/send-transactions/interoperability/transfer-assets-out-of-polkadot/", - "preview": "TODO", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/index.md", + "html_url": "https://docs.polkadot.com/index/", + "preview": "Explore everything you need to start building on top of Polkadot, a protocol that provides parachains with shared security and interoperability using XCM.", "outline": [], "stats": { - "chars": 5, - "words": 1, + "chars": 0, + "words": 0, "headings": 0, "estimated_token_count_total": 0 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "token_estimator": "heuristic-v1" }, { - "id": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", - "title": "Transfer Assets Between Parachains", - "slug": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", + "id": "nodes-and-validators-run-a-node-bootnode", + "title": "Set Up a Bootnode", + "slug": "nodes-and-validators-run-a-node-bootnode", "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-parachains.md", - "html_url": "https://docs.polkadot.com/chain-interactions/send-transactions/interoperability/transfer-assets-parachains/", - "preview": "This guide walks you through transferring tokens between two parachains using the [ParaSpell XCM SDK](/reference/tools/paraspell/){target=\\_blank}. This example utilizes [Asset Hub](/polkadot-protocol/architecture/system-chains/asset-hub/){target=\\_blank} and the [People Chain](/polkadot-protocol/architecture/system-chains/people/){target=\\_blank}. However, the same approach can be applied to transfers between other parachains.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 3, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Initialize Your Project", - "anchor": "initialize-your-project" - }, - { - "depth": 2, - "title": "Build a Token Transfer Transaction", - "anchor": "build-a-token-transfer-transaction" - }, - { - "depth": 2, - "title": "Perform a Dry Run", - "anchor": "perform-a-dry-run" - }, - { - "depth": 2, - "title": "Verify the Existential Deposit", - "anchor": "verify-the-existential-deposit" - }, - { - "depth": 2, - "title": "Get Transfer Info and Fee Estimates", - "anchor": "get-transfer-info-and-fee-estimates" - }, - { - "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 26764, - "words": 2289, - "headings": 8, - "estimated_token_count_total": 5257 - }, - "hash": "sha256:681b3f8e3bae1727c0f3742484dfc58ac817ad131199adb1f6f802592006fc69", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", - "title": "Send a Transaction While Paying the Fee with a Different Token", - "slug": "chain-interactions-send-transactions-pay-fees-with-different-tokens", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-pay-fees-with-different-tokens.md", - "html_url": "https://docs.polkadot.com/chain-interactions/send-transactions/pay-fees-with-different-tokens/", - "preview": "The Asset Hub provides a powerful feature that allows users to pay transaction fees using alternative tokens instead of the native token of the chain.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Environment Setup", - "anchor": "environment-setup" - }, - { - "depth": 2, - "title": "Local Asset Hub Setup", - "anchor": "local-asset-hub-setup" - }, - { - "depth": 2, - "title": "Implementation", - "anchor": "implementation" - }, - { - "depth": 3, - "title": "Import Dependencies", - "anchor": "import-dependencies" - }, - { - "depth": 3, - "title": "Define Constants", - "anchor": "define-constants" - }, - { - "depth": 3, - "title": "Create a Signer", - "anchor": "create-a-signer" - }, - { - "depth": 3, - "title": "Setup the Client and API", - "anchor": "setup-the-client-and-api" - }, - { - "depth": 3, - "title": "Create the Transaction", - "anchor": "create-the-transaction" - }, - { - "depth": 3, - "title": "Sign and Submit with Alternative Fee Payment", - "anchor": "sign-and-submit-with-alternative-fee-payment" - }, - { - "depth": 2, - "title": "Full Code", - "anchor": "full-code" - }, - { - "depth": 2, - "title": "Running the Script", - "anchor": "running-the-script" - }, - { - "depth": 2, - "title": "Expected Output", - "anchor": "expected-output" - }, - { - "depth": 2, - "title": "Conclusion", - "anchor": "conclusion" - } - ], - "stats": { - "chars": 9257, - "words": 1126, - "headings": 14, - "estimated_token_count_total": 2132 - }, - "hash": "sha256:1b9efd2fe00b251d3b4054c9cfcb55f9b5a1384238eeaca81a6f1542fc36d75c", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-send-transactions-with-sdks", - "title": "chain-interactions-send-transactions-with-sdks", - "slug": "chain-interactions-send-transactions-with-sdks", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-with-sdks.md", - "html_url": "https://docs.polkadot.com/chain-interactions/send-transactions/with-sdks/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-token-operations-convert-assets", - "title": "Convert Assets on Asset Hub", - "slug": "chain-interactions-token-operations-convert-assets", - "categories": [ - "dApps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-convert-assets.md", - "html_url": "https://docs.polkadot.com/chain-interactions/token-operations/convert-assets/", - "preview": "Asset Conversion is an Automated Market Maker (AMM) utilizing [Uniswap V2](https://github.com/Uniswap/v2-core){target=\\_blank} logic and implemented as a pallet on Polkadot's Asset Hub.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Create a Liquidity Pool", - "anchor": "create-a-liquidity-pool" - }, - { - "depth": 2, - "title": "Add Liquidity to a Pool", - "anchor": "add-liquidity-to-a-pool" - }, - { - "depth": 2, - "title": "Swap Assets", - "anchor": "swap-assets" - }, - { - "depth": 3, - "title": "Swap from an Exact Amount of Tokens", - "anchor": "swap-from-an-exact-amount-of-tokens" - }, - { - "depth": 3, - "title": "Swap to an Exact Amount of Tokens", - "anchor": "swap-to-an-exact-amount-of-tokens" - }, - { - "depth": 2, - "title": "Withdraw Liquidity from a Pool", - "anchor": "withdraw-liquidity-from-a-pool" - }, - { - "depth": 2, - "title": "Test Environment Setup", - "anchor": "test-environment-setup" - } - ], - "stats": { - "chars": 18507, - "words": 2590, - "headings": 9, - "estimated_token_count_total": 4063 - }, - "hash": "sha256:bd07cdae71bf63786994865d2f33fba5f7bf8855dce6399414ad44ab0ec6635c", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-token-operations-register-foreign-asset", - "title": "Register a Foreign Asset on Asset Hub", - "slug": "chain-interactions-token-operations-register-foreign-asset", - "categories": [ - "dApps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-foreign-asset.md", - "html_url": "https://docs.polkadot.com/chain-interactions/token-operations/register-foreign-asset/", - "preview": "As outlined in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\\_blank}, Asset Hub supports two categories of assets: local and foreign. Local assets are created on the Asset Hub system parachain and are identified by integer IDs. On the other hand, foreign assets, which originate outside of Asset Hub, are recognized by [Multilocations](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\\_b", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Steps to Register a Foreign Asset", - "anchor": "steps-to-register-a-foreign-asset" - }, - { - "depth": 3, - "title": "Asset Hub", - "anchor": "asset-hub" - }, - { - "depth": 3, - "title": "Source Parachain", - "anchor": "source-parachain" - }, - { - "depth": 2, - "title": "Asset Registration Verification", - "anchor": "asset-registration-verification" - }, - { - "depth": 2, - "title": "Test Environment Setup", - "anchor": "test-environment-setup" - } - ], - "stats": { - "chars": 9757, - "words": 1422, - "headings": 7, - "estimated_token_count_total": 2225 - }, - "hash": "sha256:e916033f54c2874eb5ce9a43d58af058eb935429f73b7b1acc7da1592218e0b8", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions-token-operations-register-local-asset", - "title": "Register a Local Asset", - "slug": "chain-interactions-token-operations-register-local-asset", - "categories": [ - "Basics", - "dApps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md", - "html_url": "https://docs.polkadot.com/chain-interactions/token-operations/register-local-asset/", - "preview": "As detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Steps to Register a Local Asset", - "anchor": "steps-to-register-a-local-asset" - }, - { - "depth": 2, - "title": "Verify Asset Registration", - "anchor": "verify-asset-registration" - }, - { - "depth": 2, - "title": "Test Setup Environment", - "anchor": "test-setup-environment" - } - ], - "stats": { - "chars": 6355, - "words": 1015, - "headings": 5, - "estimated_token_count_total": 1523 - }, - "hash": "sha256:d9d85827d2c14bff8dd6b3301617345430cf63db603e37859720713004ecafae", - "token_estimator": "heuristic-v1" - }, - { - "id": "chain-interactions", - "title": "Chain Interactions Overview", - "slug": "chain-interactions", - "categories": [ - "Chain Interactions" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions.md", - "html_url": "https://docs.polkadot.com/chain-interactions/", - "preview": "Chain interactions form the foundation of building applications on Polkadot. Whether you're querying on-chain data, executing transactions, enabling cross-chain communication, or managing accounts, understanding how to interact with Polkadot-based chains is essential for application developers.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Core Interaction Patterns", - "anchor": "core-interaction-patterns" - }, - { - "depth": 3, - "title": "Query On-Chain Data", - "anchor": "query-on-chain-data" - }, - { - "depth": 3, - "title": "Send Transactions", - "anchor": "send-transactions" - }, - { - "depth": 3, - "title": "Send Cross-Chain Transactions", - "anchor": "send-cross-chain-transactions" - }, - { - "depth": 3, - "title": "Manage Tokens", - "anchor": "manage-tokens" - }, - { - "depth": 3, - "title": "Manage Accounts", - "anchor": "manage-accounts" - }, - { - "depth": 2, - "title": "Development Tools and SDKs", - "anchor": "development-tools-and-sdks" - }, - { - "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 6632, - "words": 831, - "headings": 9, - "estimated_token_count_total": 1488 - }, - "hash": "sha256:ff1d106bd19f80de0c8108b0a658cfef83d73a4560a012ace9c842acdeefd1a5", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support-ai-ready-docs", - "title": "AI Ready Docs", - "slug": "get-support-ai-ready-docs", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-ai-ready-docs.md", - "html_url": "https://docs.polkadot.com/get-support/ai-ready-docs/", - "preview": "Polkadot provides files to make documentation content available in a structure optimized for use with large language models (LLMs) and AI tools. These resources help build AI assistants, power code search, or enable custom tooling trained on Polkadot’s documentation.", - "outline": [ - { - "depth": 2, - "title": "How to Use These Files", - "anchor": "how-to-use-these-files" - }, - { - "depth": 2, - "title": "Download LLM Files", - "anchor": "download-llm-files" - } - ], - "stats": { - "chars": 7998, - "words": 825, - "headings": 2, - "estimated_token_count_total": 2232 - }, - "hash": "sha256:5a8da69a5cea8bd598ee4d102b9abed5d1a29153802a567e22bb4ee720410b32", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support-explore-resources", - "title": "Subscribe to Updates", - "slug": "get-support-explore-resources", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md", - "html_url": "https://docs.polkadot.com/get-support/explore-resources/", - "preview": "Looking for answers beyond the documentation? These platforms are full of useful content and experienced developers sharing insights.", - "outline": [ - { - "depth": 2, - "title": "🧠 Stack Exchange", - "anchor": "stack-exchange" - }, - { - "depth": 2, - "title": "🧵 Reddit: r/Polkadot", - "anchor": "reddit-rpolkadot" - }, - { - "depth": 2, - "title": "💬 Discord (Community Threads Only)", - "anchor": "discord-community-threads-only" - }, - { - "depth": 2, - "title": "🎥 YouTube: @PolkadotNetwork", - "anchor": "youtube-polkadotnetwork" - }, - { - "depth": 2, - "title": "Community-Led Platforms and Ecosystem Updates", - "anchor": "community-led-platforms-and-ecosystem-updates" - }, - { - "depth": 3, - "title": "🔷 X (Twitter): Official Accounts", - "anchor": "x-twitter-official-accounts" - }, - { - "depth": 3, - "title": "🔁 X (Twitter): Community Accounts", - "anchor": "x-twitter-community-accounts" - }, - { - "depth": 3, - "title": "🗣️ Polkadot Forum", - "anchor": "polkadot-forum" - }, - { - "depth": 3, - "title": "🧑‍⚖️ Polkassembly: OpenGov", - "anchor": "polkassembly-opengov" - }, - { - "depth": 3, - "title": "📸 Instagram", - "anchor": "instagram" - } - ], - "stats": { - "chars": 2426, - "words": 295, - "headings": 10, - "estimated_token_count_total": 579 - }, - "hash": "sha256:670221ac20ab1f1b550ba2a1db06cd924c24bd3afc4d8a768b617d8a409243cb", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support-get-in-touch", - "title": "Get in Touch", - "slug": "get-support-get-in-touch", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-get-in-touch.md", - "html_url": "https://docs.polkadot.com/get-support/get-in-touch/", - "preview": "Use one of the channels below to get live technical support or ask questions.", - "outline": [ - { - "depth": 2, - "title": "Need Help Fast?", - "anchor": "need-help-fast" - }, - { - "depth": 2, - "title": "📱 Telegram: Polkadot Developer Support", - "anchor": "telegram-polkadot-developer-support" - }, - { - "depth": 2, - "title": "🔌 Discord: Polkadot Official Server", - "anchor": "discord-polkadot-official-server" - }, - { - "depth": 2, - "title": "🧬 Matrix: Polkadot Developer Support", - "anchor": "matrix-polkadot-developer-support" - } - ], - "stats": { - "chars": 1949, - "words": 258, - "headings": 4, - "estimated_token_count_total": 557 - }, - "hash": "sha256:993e93b05c8fbdfc2f7510c61ac86bc4c2ff0f03e573695b2f260933c8b62f78", - "token_estimator": "heuristic-v1" - }, - { - "id": "get-support", - "title": "Support", - "slug": "get-support", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support.md", - "html_url": "https://docs.polkadot.com/get-support/", - "preview": "Use one of the channels below to get live technical support or ask questions.", - "outline": [ - { - "depth": 2, - "title": "Need More than Just Documentation?", - "anchor": "need-more-than-just-documentation" - }, - { - "depth": 2, - "title": "What You Can Do Here", - "anchor": "what-you-can-do-here" - }, - { - "depth": 2, - "title": "Help Us Improve", - "anchor": "help-us-improve" - } - ], - "stats": { - "chars": 1658, - "words": 244, - "headings": 3, - "estimated_token_count_total": 280 - }, - "hash": "sha256:5bdc575ac798a971867a15651c2b4d5139bf0b1fe6854d1865deff280ae6d7f6", - "token_estimator": "heuristic-v1" - }, - { - "id": "index", - "title": "Polkadot Developer Docs", - "slug": "index", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/index.md", - "html_url": "https://docs.polkadot.com/index/", - "preview": "Explore everything you need to start building on top of Polkadot, a protocol that provides parachains with shared security and interoperability using XCM.", - "outline": [], - "stats": { - "chars": 0, - "words": 0, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-node-bootnode", - "title": "Set Up a Bootnode", - "slug": "nodes-and-validators-run-a-node-bootnode", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-bootnode.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/bootnode/", - "preview": "Bootnodes are essential for helping blockchain nodes discover peers and join the network. When a node starts, it needs to find other nodes, and bootnodes provide an initial point of contact. Once connected, a node can expand its peer connections and play its role in the network, like participating as a validator.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Accessing the Bootnode", - "anchor": "accessing-the-bootnode" - }, - { - "depth": 2, - "title": "Node Key", - "anchor": "node-key" - }, - { - "depth": 2, - "title": "Running the Bootnode", - "anchor": "running-the-bootnode" - }, - { - "depth": 2, - "title": "Testing Bootnode Connection", - "anchor": "testing-bootnode-connection" - }, - { - "depth": 3, - "title": "P2P", - "anchor": "p2p" - }, - { - "depth": 3, - "title": "P2P/WS", - "anchor": "p2pws" - }, - { - "depth": 3, - "title": "P2P/WSS", - "anchor": "p2pwss" - } - ], - "stats": { - "chars": 4538, - "words": 647, - "headings": 9, - "estimated_token_count_total": 1044 - }, - "hash": "sha256:d84a5af1a0237a911d25a68c077f508ebbce608f673ef4f9055e8e434daa96b9", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-node-full-node", - "title": "Set Up a Node", - "slug": "nodes-and-validators-run-a-node-full-node", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-full-node.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/full-node/", - "preview": "Running a node on Polkadot provides direct interaction with the network, enhanced privacy, and full control over RPC requests, transactions, and data queries. As the backbone of the network, nodes ensure decentralized data propagation, transaction validation, and seamless communication across the ecosystem.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Set Up a Node", - "anchor": "set-up-a-node" - }, - { - "depth": 3, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 3, - "title": "Install and Build the Polkadot Binary", - "anchor": "install-and-build-the-polkadot-binary" - }, - { - "depth": 3, - "title": "Use Docker", - "anchor": "use-docker" - }, - { - "depth": 2, - "title": "Configure and Run Your Node", - "anchor": "configure-and-run-your-node" - }, - { - "depth": 3, - "title": "RPC Configurations", - "anchor": "rpc-configurations" - }, - { - "depth": 2, - "title": "Sync Your Node", - "anchor": "sync-your-node" - }, - { - "depth": 3, - "title": "Connect to Your Node", - "anchor": "connect-to-your-node" - } - ], - "stats": { - "chars": 15944, - "words": 2481, - "headings": 9, - "estimated_token_count_total": 4196 - }, - "hash": "sha256:924fab837818610c825be5cefde0a7bacd46985b4fa05cfa0376a941105b9869", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-node-secure-wss", - "title": "Set Up Secure WebSocket", - "slug": "nodes-and-validators-run-a-node-secure-wss", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-secure-wss.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/secure-wss/", - "preview": "Ensuring secure WebSocket communication is crucial for maintaining the integrity and security of a Polkadot or Kusama node when interacting with remote clients. This guide walks you through setting up a secure WebSocket (WSS) connection for your node by leveraging SSL encryption with popular web server proxies like nginx or Apache.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Secure a WebSocket Port", - "anchor": "secure-a-websocket-port" - }, - { - "depth": 3, - "title": "Obtain an SSL Certificate", - "anchor": "obtain-an-ssl-certificate" - }, - { - "depth": 2, - "title": "Install a Proxy Server", - "anchor": "install-a-proxy-server" - }, - { - "depth": 3, - "title": "Use nginx", - "anchor": "use-nginx" - }, - { - "depth": 3, - "title": "Use Apache2", - "anchor": "use-apache2" - }, - { - "depth": 2, - "title": "Connect to the Node", - "anchor": "connect-to-the-node" - } - ], - "stats": { - "chars": 5568, - "words": 774, - "headings": 7, - "estimated_token_count_total": 1280 - }, - "hash": "sha256:992082e4ad87348b283f6c37ea886ae0e7bf016852b6470000876f3d169c65a4", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", - "title": "Validator Key Management", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/", - "preview": "After setting up your node environment as shown in the [Setup](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/){target=\\_blank} section, you'll need to configure multiple keys for your validator to operate properly. This includes setting up session keys, which are essential for participating in the consensus process, and configuring a node key that maintains a stable network identity. This guide walks you through the key management process, showing you how to g", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Set Session Keys", - "anchor": "set-session-keys" - }, - { - "depth": 3, - "title": "Generate Session Keys", - "anchor": "generate-session-keys" - }, - { - "depth": 3, - "title": "Submit Transaction to Set Keys", - "anchor": "submit-transaction-to-set-keys" - }, - { - "depth": 3, - "title": "Verify Session Key Setup", - "anchor": "verify-session-key-setup" - }, - { - "depth": 2, - "title": "Set the Node Key", - "anchor": "set-the-node-key" - }, - { - "depth": 3, - "title": "Generate the Node Key", - "anchor": "generate-the-node-key" - }, - { - "depth": 3, - "title": "Set Node Key", - "anchor": "set-node-key" - } - ], - "stats": { - "chars": 8227, - "words": 1183, - "headings": 8, - "estimated_token_count_total": 1840 - }, - "hash": "sha256:0fb5a83835aab263c0b9aa886028c8aa8a2d6d0897d7b9fff4b5258835d30dfe", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", - "title": "Set Up a Validator", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/", - "preview": "Setting up a Polkadot validator node is essential for securing the network and earning staking rewards. This guide walks you through the technical steps to set up a validator, from installing the necessary software to managing keys and synchronizing your node with the chain.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Initial Setup", - "anchor": "initial-setup" - }, - { - "depth": 3, - "title": "Install Network Time Protocol Client", - "anchor": "install-network-time-protocol-client" - }, - { - "depth": 3, - "title": "Verify Landlock is Activated", - "anchor": "verify-landlock-is-activated" - }, - { - "depth": 2, - "title": "Install the Polkadot Binaries", - "anchor": "install-the-polkadot-binaries" - }, - { - "depth": 3, - "title": "Install from Official Releases", - "anchor": "install-from-official-releases" - }, - { - "depth": 3, - "title": "Install with Package Managers", - "anchor": "install-with-package-managers" - }, - { - "depth": 3, - "title": "Install with Ansible", - "anchor": "install-with-ansible" - }, - { - "depth": 3, - "title": "Install with Docker", - "anchor": "install-with-docker" - }, - { - "depth": 3, - "title": "Build from Sources", - "anchor": "build-from-sources" - }, - { - "depth": 2, - "title": "Verify Installation", - "anchor": "verify-installation" - } - ], - "stats": { - "chars": 11921, - "words": 1678, - "headings": 12, - "estimated_token_count_total": 2592 - }, - "hash": "sha256:d2c1c91734bc8185057d8eeec6829ea91e0316f7ba884c5dc3922a5e5778815e", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", - "title": "Start Validating", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/start-validating/", - "preview": "After configuring your node keys as shown in the [Key Management](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/){target=\\_blank} section and ensuring your system is set up, you're ready to begin the validator setup process. This guide will walk you through choosing a network, synchronizing your node with the blockchain, bonding your DOT tokens, and starting your validator.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Choose a Network", - "anchor": "choose-a-network" - }, - { - "depth": 2, - "title": "Synchronize Chain Data", - "anchor": "synchronize-chain-data" - }, - { - "depth": 3, - "title": "Database Snapshot Services", - "anchor": "database-snapshot-services" - }, - { - "depth": 2, - "title": "Bond DOT", - "anchor": "bond-dot" - }, - { - "depth": 3, - "title": "Bonding DOT on Polkadot.js Apps", - "anchor": "bonding-dot-on-polkadotjs-apps" - }, - { - "depth": 2, - "title": "Validate", - "anchor": "validate" - }, - { - "depth": 3, - "title": "Verify Sync via Telemetry", - "anchor": "verify-sync-via-telemetry" - }, - { - "depth": 3, - "title": "Activate using Polkadot.js Apps", - "anchor": "activate-using-polkadotjs-apps" - }, - { - "depth": 3, - "title": "Monitor Validation Status and Slots", - "anchor": "monitor-validation-status-and-slots" - }, - { - "depth": 2, - "title": "Run a Validator Using Systemd", - "anchor": "run-a-validator-using-systemd" - }, - { - "depth": 3, - "title": "Create the Systemd Service File", - "anchor": "create-the-systemd-service-file" - }, - { - "depth": 3, - "title": "Run the Service", - "anchor": "run-the-service" - } - ], - "stats": { - "chars": 15820, - "words": 2446, - "headings": 13, - "estimated_token_count_total": 3861 - }, - "hash": "sha256:67a43e787805244196e1e9cb962069292c69ed5fdb1110df57c942019892b953", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", - "title": "Stop Validating", - "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/", - "preview": "If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Pause Versus Stop", - "anchor": "pause-versus-stop" - }, - { - "depth": 2, - "title": "Chill Validator", - "anchor": "chill-validator" - }, - { - "depth": 2, - "title": "Purge Validator Session Keys", - "anchor": "purge-validator-session-keys" - }, - { - "depth": 2, - "title": "Unbond Your Tokens", - "anchor": "unbond-your-tokens" - } - ], - "stats": { - "chars": 3230, - "words": 500, - "headings": 5, - "estimated_token_count_total": 629 - }, - "hash": "sha256:0d6db361bfa7a3022849bbe39989bfdac0429537498d7f534adadec131afca98", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-operational-tasks-general-management", - "title": "General Management", - "slug": "nodes-and-validators-run-a-validator-operational-tasks-general-management", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-general-management.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/general-management/", - "preview": "Validator performance is pivotal in maintaining the security and stability of the Polkadot network. As a validator, optimizing your setup ensures efficient transaction processing, minimizes latency, and maintains system reliability during high-demand periods. Proper configuration and proactive monitoring also help mitigate risks like slashing and service interruptions.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Configuration Optimization", - "anchor": "configuration-optimization" - }, - { - "depth": 3, - "title": "Deactivate Simultaneous Multithreading", - "anchor": "deactivate-simultaneous-multithreading" - }, - { - "depth": 3, - "title": "Deactivate Automatic NUMA Balancing", - "anchor": "deactivate-automatic-numa-balancing" - }, - { - "depth": 3, - "title": "Spectre and Meltdown Mitigations", - "anchor": "spectre-and-meltdown-mitigations" - }, - { - "depth": 2, - "title": "Monitor Your Node", - "anchor": "monitor-your-node" - }, - { - "depth": 3, - "title": "Environment Setup", - "anchor": "environment-setup" - }, - { - "depth": 3, - "title": "Install and Configure Prometheus", - "anchor": "install-and-configure-prometheus" - }, - { - "depth": 3, - "title": "Start Prometheus", - "anchor": "start-prometheus" - }, - { - "depth": 3, - "title": "Install and Configure Grafana", - "anchor": "install-and-configure-grafana" - }, - { - "depth": 3, - "title": "Install and Configure Alertmanager", - "anchor": "install-and-configure-alertmanager" - }, - { - "depth": 2, - "title": "Secure Your Validator", - "anchor": "secure-your-validator" - }, - { - "depth": 3, - "title": "Key Management", - "anchor": "key-management" - }, - { - "depth": 3, - "title": "Signing Outside the Client", - "anchor": "signing-outside-the-client" - }, - { - "depth": 3, - "title": "Secure-Validator Mode", - "anchor": "secure-validator-mode" - }, - { - "depth": 3, - "title": "Linux Best Practices", - "anchor": "linux-best-practices" - }, - { - "depth": 3, - "title": "Validator Best Practices", - "anchor": "validator-best-practices" - }, - { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 26673, - "words": 3357, - "headings": 18, - "estimated_token_count_total": 5866 - }, - "hash": "sha256:81eb0fe77f05155f1ec0511cd066120fc9994961e9d91e21b6666377e65b4586", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", - "title": "Pause Validating", - "slug": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-pause-validating.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/", - "preview": "If you need to temporarily stop participating in Polkadot staking activities without fully unbonding your funds, chilling your account allows you to do so efficiently. Chilling removes your node from active validation or nomination in the next era while keeping your funds bonded, making it ideal for planned downtimes or temporary pauses.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Chilling Your Node", - "anchor": "chilling-your-node" - }, - { - "depth": 2, - "title": "Staking Election Timing Considerations", - "anchor": "staking-election-timing-considerations" - }, - { - "depth": 2, - "title": "Chilling as a Nominator", - "anchor": "chilling-as-a-nominator" - }, - { - "depth": 2, - "title": "Chilling as a Validator", - "anchor": "chilling-as-a-validator" - }, - { - "depth": 2, - "title": "Chill Other", - "anchor": "chill-other" - } - ], - "stats": { - "chars": 4439, - "words": 679, - "headings": 6, - "estimated_token_count_total": 861 - }, - "hash": "sha256:1af153570ce57bd5b52d08493a300996765686f2a6d04519a2e0aa91191612c1", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", - "title": "Upgrade a Validator Node", - "slug": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/upgrade-your-node/", - "preview": "Upgrading a Polkadot validator node is essential for staying current with network updates and maintaining optimal performance. This guide covers routine and extended maintenance scenarios, including software upgrades and major server changes. Following these steps, you can manage session keys and transition smoothly between servers without risking downtime, slashing, or network disruptions. The process requires strategic planning, especially if you need to perform long-lead maintenance, ensuring", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Session Keys", - "anchor": "session-keys" - }, - { - "depth": 2, - "title": "Keystore", - "anchor": "keystore" - }, - { - "depth": 2, - "title": "Upgrade Using Backup Validator", - "anchor": "upgrade-using-backup-validator" - }, - { - "depth": 3, - "title": "Session `N`", - "anchor": "session-n" - }, - { - "depth": 3, - "title": "Session `N+3`", - "anchor": "session-n3" - } - ], - "stats": { - "chars": 5650, - "words": 851, - "headings": 7, - "estimated_token_count_total": 1185 - }, - "hash": "sha256:888230b128d8c648c4f06a18d3b1d1b06dd1bf22a0de4add1f28210ffccb2549", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-requirements", - "title": "Validator Requirements", - "slug": "nodes-and-validators-run-a-validator-requirements", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-requirements.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/requirements/", - "preview": "Running a validator in the Polkadot ecosystem is essential for maintaining network security and decentralization. Validators are responsible for validating transactions and adding new blocks to the chain, ensuring the system operates smoothly. In return for their services, validators earn rewards. However, the role comes with inherent risks, such as slashing penalties for misbehavior or technical failures. If you’re new to validation, starting on Kusama provides a lower-stakes environment to gai", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Minimum Hardware Requirements", - "anchor": "minimum-hardware-requirements" - }, - { - "depth": 2, - "title": "VPS Provider List", - "anchor": "vps-provider-list" - }, - { - "depth": 2, - "title": "Minimum Bond Requirement", - "anchor": "minimum-bond-requirement" - } - ], - "stats": { - "chars": 6842, - "words": 944, - "headings": 5, - "estimated_token_count_total": 1485 - }, - "hash": "sha256:46435b97c37ef6798d2c75c69df31c5e5f07e04b218c370ec5af6b1838d43aac", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", - "title": "Offenses and Slashes", - "slug": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/offenses-and-slashes/", - "preview": "In Polkadot's Nominated Proof of Stake (NPoS) system, validator misconduct is deterred through a combination of slashing, disabling, and reputation penalties. Validators and nominators who stake tokens face consequences for validator misbehavior, which range from token slashes to restrictions on network participation.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Offenses", - "anchor": "offenses" - }, - { - "depth": 3, - "title": "Invalid Votes", - "anchor": "invalid-votes" - }, - { - "depth": 3, - "title": "Equivocations", - "anchor": "equivocations" - }, - { - "depth": 2, - "title": "Penalties", - "anchor": "penalties" - }, - { - "depth": 3, - "title": "Slashing", - "anchor": "slashing" - }, - { - "depth": 3, - "title": "Disabling", - "anchor": "disabling" - }, - { - "depth": 3, - "title": "Reputation Changes", - "anchor": "reputation-changes" - }, - { - "depth": 3, - "title": "Penalties by Offense", - "anchor": "penalties-by-offense" - } - ], - "stats": { - "chars": 15427, - "words": 2103, - "headings": 9, - "estimated_token_count_total": 3409 - }, - "hash": "sha256:abe6bedab04f463ec07f554977b8d6355a5d2fad9bcda01cbe58568152295daa", - "token_estimator": "heuristic-v1" - }, - { - "id": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", - "title": "Rewards Payout", - "slug": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", - "categories": [ - "Infrastructure" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-rewards.md", - "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/rewards/", - "preview": "Understanding how rewards are distributed to validators and nominators is essential for network participants. In Polkadot and Kusama, validators earn rewards based on their era points, which are accrued through actions like block production and parachain validation.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Era Points", - "anchor": "era-points" - }, - { - "depth": 2, - "title": "Reward Variance", - "anchor": "reward-variance" - }, - { - "depth": 2, - "title": "Payout Scheme", - "anchor": "payout-scheme" - }, - { - "depth": 2, - "title": "Running Multiple Validators", - "anchor": "running-multiple-validators" - }, - { - "depth": 2, - "title": "Nominators and Validator Payments", - "anchor": "nominators-and-validator-payments" - } - ], - "stats": { - "chars": 10976, - "words": 1753, - "headings": 6, - "estimated_token_count_total": 2588 - }, - "hash": "sha256:d5d6d72eb2cf10f624d84c65f2274f7df90acb5d071bf170bc8eae8d98a810a5", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-add-existing-pallets", - "title": "Add an Existing Pallet to the Runtime", - "slug": "parachains-customize-runtime-add-existing-pallets", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-existing-pallets.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-existing-pallets/", - "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a functional runtime that includes default [FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} development modules ([pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}) to help you get started building a custo", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Check Prerequisites", - "anchor": "check-prerequisites" - }, - { - "depth": 2, - "title": "Add an Existing Polkadot SDK Pallet to Your Runtime", - "anchor": "add-an-existing-polkadot-sdk-pallet-to-your-runtime" - }, - { - "depth": 3, - "title": "Add an Existing Pallet as a Dependency", - "anchor": "add-an-existing-pallet-as-a-dependency" - }, - { - "depth": 3, - "title": "Enable Standard Library Features", - "anchor": "enable-standard-library-features" - }, - { - "depth": 3, - "title": "Review the Config Trait", - "anchor": "review-the-config-trait" - }, - { - "depth": 3, - "title": "Implement the Config Trait", - "anchor": "implement-the-config-trait" - }, - { - "depth": 3, - "title": "Add to Runtime Construct", - "anchor": "add-to-runtime-construct" - }, - { - "depth": 3, - "title": "Verify the Runtime Compiles", - "anchor": "verify-the-runtime-compiles" - }, - { - "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" - }, - { - "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" - }, - { - "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" - }, - { - "depth": 3, - "title": "Interact with the Pallet", - "anchor": "interact-with-the-pallet" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 11924, - "words": 1585, - "headings": 14, - "estimated_token_count_total": 2724 - }, - "hash": "sha256:93d123cbaaccc2515b4a70be8e1327b4f75b1051d16c5e3daf5a2035af7b7ca3", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-add-pallet-instances", - "title": "Add Multiple Pallet Instances", - "slug": "parachains-customize-runtime-add-pallet-instances", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-pallet-instances.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-pallet-instances/", - "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a solid foundation for building custom parachains. While most pallets are typically included as single instances within a runtime, some scenarios benefit from running multiple instances of the same pallet with different configurations. This approach lets you reuse pallet logic without reimplementing it, enabling diverse functionality from a single codebase.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Check Prerequisites", - "anchor": "check-prerequisites" - }, - { - "depth": 2, - "title": "Understanding Instantiable Pallets", - "anchor": "understanding-instantiable-pallets" - }, - { - "depth": 3, - "title": "Identifying an Instantiable Pallet", - "anchor": "identifying-an-instantiable-pallet" - }, - { - "depth": 3, - "title": "How Instance Generics Work", - "anchor": "how-instance-generics-work" - }, - { - "depth": 2, - "title": "Add Multiple Instances of a Pallet to Your Runtime", - "anchor": "add-multiple-instances-of-a-pallet-to-your-runtime" - }, - { - "depth": 3, - "title": "Add the Pallet as a Dependency", - "anchor": "add-the-pallet-as-a-dependency" - }, - { - "depth": 3, - "title": "Enable Standard Library Features", - "anchor": "enable-standard-library-features" - }, - { - "depth": 3, - "title": "Review the Config Trait", - "anchor": "review-the-config-trait" - }, - { - "depth": 3, - "title": "Define Pallet Parameters", - "anchor": "define-pallet-parameters" - }, - { - "depth": 3, - "title": "Create Instance Type Definitions", - "anchor": "create-instance-type-definitions" - }, - { - "depth": 3, - "title": "Implement Config Trait for First Instance", - "anchor": "implement-config-trait-for-first-instance" - }, - { - "depth": 3, - "title": "Implement Config Trait for Second Instance", - "anchor": "implement-config-trait-for-second-instance" - }, - { - "depth": 3, - "title": "Add Instances to Runtime Construct", - "anchor": "add-instances-to-runtime-construct" - }, - { - "depth": 3, - "title": "Verify the Runtime Compiles", - "anchor": "verify-the-runtime-compiles" - }, - { - "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" - }, - { - "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" - }, - { - "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" - }, - { - "depth": 3, - "title": "Interact with Both Pallet Instances", - "anchor": "interact-with-both-pallet-instances" - }, - { - "depth": 3, - "title": "Test Instance Independence", - "anchor": "test-instance-independence" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 17923, - "words": 2203, - "headings": 21, - "estimated_token_count_total": 3811 - }, - "hash": "sha256:d83e574726c524fa017236eb5e3b8a0676d598be4da1ce4fe25a60141baeee49", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-add-smart-contract-functionality", - "title": "Add Smart Contract Functionality", - "slug": "parachains-customize-runtime-add-smart-contract-functionality", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-smart-contract-functionality/", - "preview": "When building your custom blockchain with the Polkadot SDK, you can add smart contract capabilities through specialized pallets. These pallets enable users to deploy and execute smart contracts, enhancing your chain's programmability and allowing developers to build decentralized applications on your network.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "pallet-revive", - "anchor": "pallet-revive" - }, - { - "depth": 3, - "title": "Core Components", - "anchor": "core-components" - }, - { - "depth": 3, - "title": "Supported Languages and Compilers", - "anchor": "supported-languages-and-compilers" - }, - { - "depth": 3, - "title": "How It Works", - "anchor": "how-it-works" - }, - { - "depth": 3, - "title": "Key Benefits", - "anchor": "key-benefits" - }, - { - "depth": 3, - "title": "Implementation Examples", - "anchor": "implementation-examples" - }, - { - "depth": 2, - "title": "Frontier", - "anchor": "frontier" - }, - { - "depth": 3, - "title": "Integration Options", - "anchor": "integration-options" - }, - { - "depth": 3, - "title": "EVM Execution Only", - "anchor": "evm-execution-only" - }, - { - "depth": 3, - "title": "Full Ethereum Compatibility", - "anchor": "full-ethereum-compatibility" - }, - { - "depth": 3, - "title": "Key Benefits", - "anchor": "key-benefits-2" - }, - { - "depth": 3, - "title": "Implementation Examples", - "anchor": "implementation-examples-2" - }, - { - "depth": 2, - "title": "pallet-contracts (Legacy)", - "anchor": "pallet-contracts-legacy" - }, - { - "depth": 3, - "title": "Implementation Example", - "anchor": "implementation-example" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 6655, - "words": 833, - "headings": 16, - "estimated_token_count_total": 1631 - }, - "hash": "sha256:6297bb5e0809fdd0585d6170054599f7ab4a3ce7c687ad03ae43092057c493b7", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", - "title": "Add Pallets to the Runtime", - "slug": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", - "categories": [ - "Basics", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-add-pallet-to-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/", - "preview": "In previous tutorials, you learned how to [create a custom pallet](/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/){target=\\_blank} and [test it](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/){target=\\_blank}. The next step is to include this pallet in your runtime, integrating it into the core logic of your blockchain.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Add the Pallets as Dependencies", - "anchor": "add-the-pallets-as-dependencies" - }, - { - "depth": 3, - "title": "Update the Runtime Configuration", - "anchor": "update-the-runtime-configuration" - }, - { - "depth": 2, - "title": "Recompile the Runtime", - "anchor": "recompile-the-runtime" - }, - { - "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 13091, - "words": 1522, - "headings": 6, - "estimated_token_count_total": 3091 - }, - "hash": "sha256:87add0ae178e4970601a27efccadb58eff1375d19819201034ba2829914f1cd5", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-pallet-development-benchmark-pallet", - "title": "Benchmark Your Pallet", - "slug": "parachains-customize-runtime-pallet-development-benchmark-pallet", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/benchmark-pallet/", - "preview": "Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Create the Benchmarking Module", - "anchor": "create-the-benchmarking-module" - }, - { - "depth": 2, - "title": "Define the Weight Trait", - "anchor": "define-the-weight-trait" - }, - { - "depth": 2, - "title": "Add WeightInfo to Config", - "anchor": "add-weightinfo-to-config" - }, - { - "depth": 2, - "title": "Update Extrinsic Weight Annotations", - "anchor": "update-extrinsic-weight-annotations" - }, - { - "depth": 2, - "title": "Include the Benchmarking Module", - "anchor": "include-the-benchmarking-module" - }, - { - "depth": 2, - "title": "Configure Pallet Dependencies", - "anchor": "configure-pallet-dependencies" - }, - { - "depth": 2, - "title": "Update Mock Runtime", - "anchor": "update-mock-runtime" - }, - { - "depth": 2, - "title": "Configure Runtime Benchmarking", - "anchor": "configure-runtime-benchmarking" - }, - { - "depth": 2, - "title": "Test Benchmark Compilation", - "anchor": "test-benchmark-compilation" - }, - { - "depth": 2, - "title": "Build the Runtime with Benchmarks", - "anchor": "build-the-runtime-with-benchmarks" - }, - { - "depth": 2, - "title": "Install the Benchmarking Tool", - "anchor": "install-the-benchmarking-tool" - }, - { - "depth": 2, - "title": "Download the Weight Template", - "anchor": "download-the-weight-template" - }, - { - "depth": 2, - "title": "Execute Benchmarks", - "anchor": "execute-benchmarks" - }, - { - "depth": 2, - "title": "Use Generated Weights", - "anchor": "use-generated-weights" - }, - { - "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" - }, - { - "depth": 2, - "title": "Related Resources", - "anchor": "related-resources" - } - ], - "stats": { - "chars": 22752, - "words": 2813, - "headings": 18, - "estimated_token_count_total": 5191 - }, - "hash": "sha256:c1b53ecbfc3dea02097104c7a4c652e61ccc42ad56325a9c80684850a198fbdd", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-pallet-development-create-a-pallet", - "title": "Create a Custom Pallet", - "slug": "parachains-customize-runtime-pallet-development-create-a-pallet", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/create-a-pallet/", - "preview": "[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functional", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Core Pallet Components", - "anchor": "core-pallet-components" - }, - { - "depth": 2, - "title": "Create the Pallet Project", - "anchor": "create-the-pallet-project" - }, - { - "depth": 2, - "title": "Configure Dependencies", - "anchor": "configure-dependencies" - }, - { - "depth": 2, - "title": "Initialize the Pallet Structure", - "anchor": "initialize-the-pallet-structure" - }, - { - "depth": 2, - "title": "Configure the Pallet", - "anchor": "configure-the-pallet" - }, - { - "depth": 2, - "title": "Define Events", - "anchor": "define-events" - }, - { - "depth": 2, - "title": "Define Errors", - "anchor": "define-errors" - }, - { - "depth": 2, - "title": "Add Storage Items", - "anchor": "add-storage-items" - }, - { - "depth": 2, - "title": "Configure Genesis State", - "anchor": "configure-genesis-state" - }, - { - "depth": 2, - "title": "Implement Dispatchable Functions", - "anchor": "implement-dispatchable-functions" - }, - { - "depth": 3, - "title": "Dispatchable Function Details", - "anchor": "dispatchable-function-details" - }, - { - "depth": 2, - "title": "Verify Pallet Compilation", - "anchor": "verify-pallet-compilation" - }, - { - "depth": 2, - "title": "Add the Pallet to Your Runtime", - "anchor": "add-the-pallet-to-your-runtime" - }, - { - "depth": 3, - "title": "Add Runtime Dependency", - "anchor": "add-runtime-dependency" - }, - { - "depth": 3, - "title": "Implement the Config Trait", - "anchor": "implement-the-config-trait" - }, - { - "depth": 3, - "title": "Add to Runtime Construct", - "anchor": "add-to-runtime-construct" - }, - { - "depth": 3, - "title": "Configure Genesis for Your Runtime", - "anchor": "configure-genesis-for-your-runtime" - }, - { - "depth": 3, - "title": "Verify Runtime Compilation", - "anchor": "verify-runtime-compilation" - }, - { - "depth": 2, - "title": "Run Your Chain Locally", - "anchor": "run-your-chain-locally" - }, - { - "depth": 3, - "title": "Generate a Chain Specification", - "anchor": "generate-a-chain-specification" - }, - { - "depth": 3, - "title": "Start the Parachain Node", - "anchor": "start-the-parachain-node" - }, - { - "depth": 2, - "title": "Interact with Your Pallet", - "anchor": "interact-with-your-pallet" - }, - { - "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 26958, - "words": 3085, - "headings": 26, - "estimated_token_count_total": 6194 - }, - "hash": "sha256:dad68ea59fd05fd60dc8890c4cf5615243c7ea879830b0dcf3a5e5e53c3ccec7", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-pallet-development-mock-runtime", - "title": "Mock Your Runtime", - "slug": "parachains-customize-runtime-pallet-development-mock-runtime", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/", - "preview": "Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Understand Mock Runtimes", - "anchor": "understand-mock-runtimes" - }, - { - "depth": 2, - "title": "Create the Mock Runtime Module", - "anchor": "create-the-mock-runtime-module" - }, - { - "depth": 2, - "title": "Set Up Basic Mock", - "anchor": "set-up-basic-mock" - }, - { - "depth": 2, - "title": "Implement Essential Configuration", - "anchor": "implement-essential-configuration" - }, - { - "depth": 2, - "title": "Implement Your Pallet's Configuration", - "anchor": "implement-your-pallets-configuration" - }, - { - "depth": 2, - "title": "Configure Genesis Storage", - "anchor": "configure-genesis-storage" - }, - { - "depth": 3, - "title": "Basic Test Environment", - "anchor": "basic-test-environment" - }, - { - "depth": 3, - "title": "Custom Genesis Configurations", - "anchor": "custom-genesis-configurations" - }, - { - "depth": 2, - "title": "Verify Mock Compilation", - "anchor": "verify-mock-compilation" - }, - { - "depth": 2, - "title": "Key Takeaways", - "anchor": "key-takeaways" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 11766, - "words": 1369, - "headings": 13, - "estimated_token_count_total": 2514 - }, - "hash": "sha256:dd784a5d2daebb9a885fe09f6a967e6c84958d96ddb38d8366eabe9d860fa539", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime-pallet-development-pallet-testing", - "title": "Unit Test Pallets", - "slug": "parachains-customize-runtime-pallet-development-pallet-testing", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/", - "preview": "Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Writing Unit Tests", - "anchor": "writing-unit-tests" - }, - { - "depth": 3, - "title": "Test Initialization", - "anchor": "test-initialization" - }, - { - "depth": 3, - "title": "Function Call Testing", - "anchor": "function-call-testing" - }, - { - "depth": 3, - "title": "Storage Testing", - "anchor": "storage-testing" - }, - { - "depth": 3, - "title": "Event Testing", - "anchor": "event-testing" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 6895, - "words": 912, - "headings": 7, - "estimated_token_count_total": 1563 - }, - "hash": "sha256:041ccd82f0c1ddfb93be05feb6cf9d7d4a7e37af6caa8fa8fdab5d5538017122", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-customize-runtime", - "title": "Overview of FRAME", - "slug": "parachains-customize-runtime", - "categories": [ - "Basics", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md", - "html_url": "https://docs.polkadot.com/parachains/customize-runtime/", - "preview": "A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a run", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Understanding Your Runtime", - "anchor": "understanding-your-runtime" - }, - { - "depth": 2, - "title": "Runtime Architecture", - "anchor": "runtime-architecture" - }, - { - "depth": 2, - "title": "Building Blocks: Pallets", - "anchor": "building-blocks-pallets" - }, - { - "depth": 3, - "title": "Pre-Built Pallets vs. Custom Pallets", - "anchor": "pre-built-pallets-vs-custom-pallets" - }, - { - "depth": 3, - "title": "Pallet Structure", - "anchor": "pallet-structure" - }, - { - "depth": 2, - "title": "How Runtime Customization Works", - "anchor": "how-runtime-customization-works" - }, - { - "depth": 2, - "title": "Starting Templates", - "anchor": "starting-templates" - }, - { - "depth": 2, - "title": "Key Customization Scenarios", - "anchor": "key-customization-scenarios" - } - ], - "stats": { - "chars": 8237, - "words": 1101, - "headings": 9, - "estimated_token_count_total": 1828 - }, - "hash": "sha256:28501589d5290f932b55cd3319f6a3fd78d7297ba42810da5ad2784a297224fd", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-get-started", - "title": "Get Started with Parachain Development", - "slug": "parachains-get-started", - "categories": [ - "Basics", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md", - "html_url": "https://docs.polkadot.com/parachains/get-started/", - "preview": "The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples.", - "outline": [ - { - "depth": 2, - "title": "Quick Start Guides", - "anchor": "quick-start-guides" - }, - { - "depth": 2, - "title": "Launch a Simple Parachain", - "anchor": "launch-a-simple-parachain" - }, - { - "depth": 2, - "title": "Customize Your Runtime", - "anchor": "customize-your-runtime" - }, - { - "depth": 3, - "title": "Pallet Development", - "anchor": "pallet-development" - }, - { - "depth": 2, - "title": "Testing", - "anchor": "testing" - }, - { - "depth": 2, - "title": "Runtime Upgrades and Maintenance", - "anchor": "runtime-upgrades-and-maintenance" - }, - { - "depth": 2, - "title": "Interoperability", - "anchor": "interoperability" - }, - { - "depth": 2, - "title": "Integrations", - "anchor": "integrations" - }, - { - "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 7941, - "words": 631, - "headings": 9, - "estimated_token_count_total": 2292 - }, - "hash": "sha256:759ed27cf3d473445e33141089b652082c42a2c59eb822d6b506146fd9555e13", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-install-polkadot-sdk", - "title": "Install Polkadot SDK", - "slug": "parachains-install-polkadot-sdk", - "categories": [ - "Basics", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md", - "html_url": "https://docs.polkadot.com/parachains/install-polkadot-sdk/", - "preview": "This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts:", - "outline": [ - { - "depth": 2, - "title": "Install Dependencies: macOS", - "anchor": "install-dependencies-macos" - }, - { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-mac-os }", - "anchor": "before-you-begin-before-you-begin-mac-os" - }, - { - "depth": 3, - "title": "Install Homebrew", - "anchor": "install-homebrew" - }, - { - "depth": 3, - "title": "Support for Apple Silicon", - "anchor": "support-for-apple-silicon" - }, - { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-mac-os" - }, - { - "depth": 2, - "title": "Install Dependencies: Linux", - "anchor": "install-dependencies-linux" - }, - { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-linux }", - "anchor": "before-you-begin-before-you-begin-linux" - }, - { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-linux }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-linux" - }, - { - "depth": 2, - "title": "Install Dependencies: Windows (WSL)", - "anchor": "install-dependencies-windows-wsl" - }, - { - "depth": 3, - "title": "Before You Begin {: #before-you-begin-windows-wls }", - "anchor": "before-you-begin-before-you-begin-windows-wls" - }, - { - "depth": 3, - "title": "Set Up Windows Subsystem for Linux", - "anchor": "set-up-windows-subsystem-for-linux" - }, - { - "depth": 3, - "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls }", - "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-windows-wls" - }, - { - "depth": 2, - "title": "Build the Polkadot SDK", - "anchor": "build-the-polkadot-sdk" - }, - { - "depth": 3, - "title": "Clone the Polkadot SDK", - "anchor": "clone-the-polkadot-sdk" - }, - { - "depth": 3, - "title": "Compile the Polkadot SDK", - "anchor": "compile-the-polkadot-sdk" - }, - { - "depth": 3, - "title": "Verify the Build", - "anchor": "verify-the-build" - }, - { - "depth": 2, - "title": "Optional: Run the Kitchensink Node", - "anchor": "optional-run-the-kitchensink-node" - }, - { - "depth": 3, - "title": "Run the Kitchensink Node in Development Mode", - "anchor": "run-the-kitchensink-node-in-development-mode" - }, - { - "depth": 3, - "title": "Interact with the Kitchensink Node", - "anchor": "interact-with-the-kitchensink-node" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 16051, - "words": 2312, - "headings": 20, - "estimated_token_count_total": 3345 - }, - "hash": "sha256:a52c05b623f3780f14be3a5f36b3d79a6c1965c2fbfd6864b512a9a70c47cd60", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-integrations-indexers", - "title": "Indexers", - "slug": "parachains-integrations-indexers", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/indexers/", - "preview": "Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges:", - "outline": [ - { - "depth": 2, - "title": "The Challenge of Blockchain Data Access", - "anchor": "the-challenge-of-blockchain-data-access" - }, - { - "depth": 2, - "title": "What is a Blockchain Indexer?", - "anchor": "what-is-a-blockchain-indexer" - }, - { - "depth": 2, - "title": "Indexer Implementations", - "anchor": "indexer-implementations" - } - ], - "stats": { - "chars": 2230, - "words": 302, - "headings": 3, - "estimated_token_count_total": 428 - }, - "hash": "sha256:cfcc76bb24779c9b613f2c046b6f99a0f2529c25fd82287d804f6b945b936227", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-integrations-oracles", - "title": "Oracles", - "slug": "parachains-integrations-oracles", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/oracles/", - "preview": "Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the \"blockchain oracle problem.\" Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain.", - "outline": [ - { - "depth": 2, - "title": "What is a Blockchain Oracle?", - "anchor": "what-is-a-blockchain-oracle" - }, - { - "depth": 2, - "title": "Oracle Implementations", - "anchor": "oracle-implementations" - } - ], - "stats": { - "chars": 1343, - "words": 181, - "headings": 2, - "estimated_token_count_total": 245 - }, - "hash": "sha256:6d8e01281a5895fd2bc4438b24c170c72a496de0b838626a53e87685aea4aa25", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-integrations-wallets", - "title": "Wallets", - "slug": "parachains-integrations-wallets", - "categories": [ - "Tooling", - "Dapps" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md", - "html_url": "https://docs.polkadot.com/parachains/integrations/wallets/", - "preview": "A wallet serves as your gateway to interacting with blockchain networks. Rather than storing funds, wallets secure your private keys, controlling access to your blockchain assets. Your private key provides complete control over all permitted transactions on your blockchain account, making it essential to keep it secure.", - "outline": [ - { - "depth": 2, - "title": "What is a Blockchain Wallet?", - "anchor": "what-is-a-blockchain-wallet" - }, - { - "depth": 2, - "title": "Hot Wallets", - "anchor": "hot-wallets" - }, - { - "depth": 2, - "title": "Cold Wallets", - "anchor": "cold-wallets" - }, - { - "depth": 2, - "title": "Wallet Tools", - "anchor": "wallet-tools" - } - ], - "stats": { - "chars": 3588, - "words": 489, - "headings": 4, - "estimated_token_count_total": 786 - }, - "hash": "sha256:1c65342056983806d639fb8393fdfbdf2ef644ffd41ed749947a16fb3839753d", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-interoperability-channels-between-parachains", - "title": "Opening HRMP Channels Between Parachains", - "slug": "parachains-interoperability-channels-between-parachains", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/", - "preview": "For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required:", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Procedure to Initiate an HRMP Channel", - "anchor": "procedure-to-initiate-an-hrmp-channel" - }, - { - "depth": 3, - "title": "Fund Sender Sovereign Account", - "anchor": "fund-sender-sovereign-account" - }, - { - "depth": 3, - "title": "Create Channel Opening Extrinsic", - "anchor": "create-channel-opening-extrinsic" - }, - { - "depth": 3, - "title": "Craft and Submit the XCM Message from the Sender", - "anchor": "craft-and-submit-the-xcm-message-from-the-sender" - }, - { - "depth": 2, - "title": "Procedure to Accept an HRMP Channel", - "anchor": "procedure-to-accept-an-hrmp-channel" - }, - { - "depth": 3, - "title": "Fund Receiver Sovereign Account", - "anchor": "fund-receiver-sovereign-account" - }, - { - "depth": 3, - "title": "Create Channel Accepting Extrinsic", - "anchor": "create-channel-accepting-extrinsic" - }, - { - "depth": 3, - "title": "Craft and Submit the XCM Message from the Receiver", - "anchor": "craft-and-submit-the-xcm-message-from-the-receiver" - } - ], - "stats": { - "chars": 10934, - "words": 1549, - "headings": 10, - "estimated_token_count_total": 2285 - }, - "hash": "sha256:b8de1228b9976765accd18ff724038bed6f2449367f500bc3177ab2a053abe63", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-interoperability-channels-with-system-parachains", - "title": "Opening HRMP Channels with System Parachains", - "slug": "parachains-interoperability-channels-with-system-parachains", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/", - "preview": "While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Procedure to Establish an HRMP Channel", - "anchor": "procedure-to-establish-an-hrmp-channel" - }, - { - "depth": 3, - "title": "Fund Parachain Sovereign Account", - "anchor": "fund-parachain-sovereign-account" - }, - { - "depth": 3, - "title": "Create Establish Channel with System Extrinsic", - "anchor": "create-establish-channel-with-system-extrinsic" - }, - { - "depth": 3, - "title": "Craft and Submit the XCM Message", - "anchor": "craft-and-submit-the-xcm-message" - } - ], - "stats": { - "chars": 7203, - "words": 889, - "headings": 6, - "estimated_token_count_total": 1427 - }, - "hash": "sha256:b501d99c464fb049d46676827b6a325a195c90617becc4a7db305441c115350a", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-interoperability-get-started", - "title": "Introduction to XCM", - "slug": "parachains-interoperability-get-started", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md", - "html_url": "https://docs.polkadot.com/parachains/interoperability/get-started/", - "preview": "Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Messaging Format", - "anchor": "messaging-format" - }, - { - "depth": 2, - "title": "The Four Principles of XCM", - "anchor": "the-four-principles-of-xcm" - }, - { - "depth": 2, - "title": "The XCM Tech Stack", - "anchor": "the-xcm-tech-stack" - }, - { - "depth": 2, - "title": "Core Functionalities of XCM", - "anchor": "core-functionalities-of-xcm" - }, - { - "depth": 2, - "title": "XCM Example", - "anchor": "xcm-example" - }, - { - "depth": 2, - "title": "Overview", - "anchor": "overview" - } - ], - "stats": { - "chars": 7450, - "words": 974, - "headings": 7, - "estimated_token_count_total": 1501 - }, - "hash": "sha256:3b26606dd5310c4b8ade5d05270ebf1e06f59afcda4ca2b985e07948215a197e", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-launch-a-parachain-deploy-to-polkadot", - "title": "Deploy on Polkadot", - "slug": "parachains-launch-a-parachain-deploy-to-polkadot", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-deploy-to-polkadot.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/deploy-to-polkadot/", - "preview": "Previously, you learned how to [choose and set up a parachain template](/parachains/launch-a-parachain/choose-a-template/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to the Polkadot TestNet. Deploying to a TestNet is a crucial step for validating your parachain's functionality and preparing it for eventual MainNet deployment.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Get Started with an Account and Tokens", - "anchor": "get-started-with-an-account-and-tokens" - }, - { - "depth": 2, - "title": "Reserve a Parachain Identifier", - "anchor": "reserve-a-parachain-identifier" - }, - { - "depth": 2, - "title": "Generate Custom Keys for Your Collators", - "anchor": "generate-custom-keys-for-your-collators" - }, - { - "depth": 2, - "title": "Generate the Chain Specification", - "anchor": "generate-the-chain-specification" - }, - { - "depth": 2, - "title": "Export Required Files", - "anchor": "export-required-files" - }, - { - "depth": 2, - "title": "Register a Parathread", - "anchor": "register-a-parathread" - }, - { - "depth": 2, - "title": "Start the Collator Node", - "anchor": "start-the-collator-node" - }, - { - "depth": 2, - "title": "Producing Blocks", - "anchor": "producing-blocks" - } - ], - "stats": { - "chars": 20252, - "words": 2357, - "headings": 9, - "estimated_token_count_total": 4129 - }, - "hash": "sha256:7309d3487c653951bf264013eb3402a72a1cbb5e0b6f89ae4e678f239cd63b80", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-launch-a-parachain-obtain-coretime", - "title": "Obtain Coretime", - "slug": "parachains-launch-a-parachain-obtain-coretime", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/", - "preview": "After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Order On-Demand Coretime", - "anchor": "order-on-demand-coretime" - }, - { - "depth": 3, - "title": "On-Demand Extrinsics", - "anchor": "on-demand-extrinsics" - }, - { - "depth": 3, - "title": "Place an On-Demand Order", - "anchor": "place-an-on-demand-order" - }, - { - "depth": 2, - "title": "Purchase Bulk Coretime", - "anchor": "purchase-bulk-coretime" - }, - { - "depth": 3, - "title": "Connect Your Wallet to RegionX", - "anchor": "connect-your-wallet-to-regionx" - }, - { - "depth": 3, - "title": "Obtain Coretime Chain Funds", - "anchor": "obtain-coretime-chain-funds" - }, - { - "depth": 3, - "title": "Purchase a Core", - "anchor": "purchase-a-core" - }, - { - "depth": 3, - "title": "Verify Your Purchase", - "anchor": "verify-your-purchase" - }, - { - "depth": 3, - "title": "Assign Your Parachain to the Core", - "anchor": "assign-your-parachain-to-the-core" - }, - { - "depth": 2, - "title": "Next Steps", - "anchor": "next-steps" - } - ], - "stats": { - "chars": 9049, - "words": 1345, - "headings": 12, - "estimated_token_count_total": 2103 - }, - "hash": "sha256:15154f211753665d9af70dc81d15ceb3f0954e3febf9282c68c0074881d620c6", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-launch-a-parachain-set-up-the-parachain-template", - "title": "Set Up the Polkadot SDK Parachain Template", - "slug": "parachains-launch-a-parachain-set-up-the-parachain-template", - "categories": [ - "Basics", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md", - "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/", - "preview": "The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" - }, - { - "depth": 2, - "title": "Polkadot SDK Utility Tools", - "anchor": "polkadot-sdk-utility-tools" - }, - { - "depth": 2, - "title": "Clone the Template", - "anchor": "clone-the-template" - }, - { - "depth": 2, - "title": "Explore the Project Structure", - "anchor": "explore-the-project-structure" - }, - { - "depth": 2, - "title": "Compile the Runtime", - "anchor": "compile-the-runtime" - }, - { - "depth": 2, - "title": "Verify the Build", - "anchor": "verify-the-build" - }, - { - "depth": 2, - "title": "Run the Node Locally", - "anchor": "run-the-node-locally" - }, - { - "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" - }, - { - "depth": 2, - "title": "Stop the Node", - "anchor": "stop-the-node" - }, - { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 10588, - "words": 1510, - "headings": 11, - "estimated_token_count_total": 2375 - }, - "hash": "sha256:380063fe7c00ae8bde05fa76688b8ae4902e6566147f1cfe0e0260ad1aa05aa6", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-runtime-maintenance-runtime-upgrades", - "title": "Runtime Upgrades", - "slug": "parachains-runtime-maintenance-runtime-upgrades", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/", - "preview": "One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "How Runtime Upgrades Work", - "anchor": "how-runtime-upgrades-work" - }, - { - "depth": 3, - "title": "Runtime Versioning", - "anchor": "runtime-versioning" - }, - { - "depth": 3, - "title": "Accessing the Runtime Version", - "anchor": "accessing-the-runtime-version" - }, - { - "depth": 2, - "title": "Storage Migrations", - "anchor": "storage-migrations" - } - ], - "stats": { - "chars": 5837, - "words": 811, - "headings": 5, - "estimated_token_count_total": 1161 - }, - "hash": "sha256:ec31270001a6cd9d0a8ecb7974ad161d5c1ef4d3023d5a6af9fbc5a6ca46cbca", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-runtime-maintenance-storage-migrations", - "title": "Storage Migrations", - "slug": "parachains-runtime-maintenance-storage-migrations", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/", - "preview": "Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Storage Migration Scenarios", - "anchor": "storage-migration-scenarios" - }, - { - "depth": 2, - "title": "Implement Storage Migrations", - "anchor": "implement-storage-migrations" - }, - { - "depth": 3, - "title": "Core Migration Function", - "anchor": "core-migration-function" - }, - { - "depth": 3, - "title": "Migration Testing Hooks", - "anchor": "migration-testing-hooks" - }, - { - "depth": 3, - "title": "Migration Structure", - "anchor": "migration-structure" - }, - { - "depth": 3, - "title": "Migration Organization", - "anchor": "migration-organization" - }, - { - "depth": 3, - "title": "Scheduling Migrations", - "anchor": "scheduling-migrations" - }, - { - "depth": 2, - "title": "Single-Block Migrations", - "anchor": "single-block-migrations" - }, - { - "depth": 2, - "title": "Multi Block Migrations", - "anchor": "multi-block-migrations" - } - ], - "stats": { - "chars": 18500, - "words": 2363, - "headings": 10, - "estimated_token_count_total": 4014 - }, - "hash": "sha256:55dc252fdecf1590048ce8d009b822e90231442abe81e9593cf1635944a31336", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-runtime-maintenance-unlock-parachains", - "title": "Unlock a Parachain", - "slug": "parachains-runtime-maintenance-unlock-parachains", - "categories": [ - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-unlock-parachains.md", - "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/unlock-parachains/", - "preview": "Parachain locks are a critical security mechanism in the Polkadot ecosystem designed to maintain decentralization during the parachain lifecycle. These locks prevent potential centralization risks that could emerge during the early stages of parachain operation.", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Check If the Parachain Is Locked", - "anchor": "check-if-the-parachain-is-locked" - }, - { - "depth": 2, - "title": "How to Unlock a Parachain", - "anchor": "how-to-unlock-a-parachain" - }, - { - "depth": 3, - "title": "Prepare the Unlock Call", - "anchor": "prepare-the-unlock-call" - }, - { - "depth": 3, - "title": "Fund the Sovereign Account", - "anchor": "fund-the-sovereign-account" - }, - { - "depth": 3, - "title": "Craft and Submit the XCM", - "anchor": "craft-and-submit-the-xcm" - } - ], - "stats": { - "chars": 9232, - "words": 1276, - "headings": 6, - "estimated_token_count_total": 2028 - }, - "hash": "sha256:e408d05199cc184fc6fe8bb212efb3c9aa6cb79258977e07566692176c912def", - "token_estimator": "heuristic-v1" - }, - { - "id": "parachains-testing-fork-a-parachain", - "title": "Get Started", - "slug": "parachains-testing-fork-a-parachain", - "categories": [ - "Parachains", - "Tooling" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md", - "html_url": "https://docs.polkadot.com/parachains/testing/fork-a-parachain/", - "preview": "[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.", + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-bootnode.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/bootnode/", + "preview": "Bootnodes are essential for helping blockchain nodes discover peers and join the network. When a node starts, it needs to find other nodes, and bootnodes provide an initial point of contact. Once connected, a node can expand its peer connections and play its role in the network, like participating as a validator.", "outline": [ { "depth": 2, @@ -3506,65 +221,59 @@ }, { "depth": 2, - "title": "Install Chopsticks", - "anchor": "install-chopsticks" + "title": "Accessing the Bootnode", + "anchor": "accessing-the-bootnode" }, { - "depth": 3, - "title": "Global Installation", - "anchor": "global-installation" + "depth": 2, + "title": "Node Key", + "anchor": "node-key" }, { - "depth": 3, - "title": "Local Installation", - "anchor": "local-installation" + "depth": 2, + "title": "Running the Bootnode", + "anchor": "running-the-bootnode" }, { "depth": 2, - "title": "Configure Chopsticks", - "anchor": "configure-chopsticks" + "title": "Testing Bootnode Connection", + "anchor": "testing-bootnode-connection" }, { "depth": 3, - "title": "Configuration File", - "anchor": "configuration-file" + "title": "P2P", + "anchor": "p2p" }, { "depth": 3, - "title": "CLI Flags", - "anchor": "cli-flags" - }, - { - "depth": 2, - "title": "WebSocket Commands", - "anchor": "websocket-commands" + "title": "P2P/WS", + "anchor": "p2pws" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "P2P/WSS", + "anchor": "p2pwss" } ], "stats": { - "chars": 10894, - "words": 1330, - "headings": 10, - "estimated_token_count_total": 2614 + "chars": 4538, + "words": 647, + "headings": 9, + "estimated_token_count_total": 1044 }, - "hash": "sha256:4325cdd697814b8043db808da3dee86d3d9c6fc7dd523aae7fe8914d59d1b39c", + "hash": "sha256:d84a5af1a0237a911d25a68c077f508ebbce608f673ef4f9055e8e434daa96b9", "token_estimator": "heuristic-v1" }, { - "id": "parachains-testing-run-a-parachain-network", - "title": "Get Started", - "slug": "parachains-testing-run-a-parachain-network", + "id": "nodes-and-validators-run-a-node-full-node", + "title": "Set Up a Node", + "slug": "nodes-and-validators-run-a-node-full-node", "categories": [ - "Parachains", - "Tooling" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md", - "html_url": "https://docs.polkadot.com/parachains/testing/run-a-parachain-network/", - "preview": "Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-full-node.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/full-node/", + "preview": "Running a node on Polkadot provides direct interaction with the network, enhanced privacy, and full control over RPC requests, transactions, and data queries. As the backbone of the network, nodes ensure decentralized data propagation, transaction validation, and seamless communication across the ecosystem.", "outline": [ { "depth": 2, @@ -3573,425 +282,556 @@ }, { "depth": 2, - "title": "Install Zombienet", - "anchor": "install-zombienet" + "title": "Set Up a Node", + "anchor": "set-up-a-node" }, { - "depth": 2, - "title": "Providers", - "anchor": "providers" + "depth": 3, + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 3, - "title": "Kubernetes", - "anchor": "kubernetes" + "title": "Install and Build the Polkadot Binary", + "anchor": "install-and-build-the-polkadot-binary" }, { "depth": 3, - "title": "Podman", - "anchor": "podman" + "title": "Use Docker", + "anchor": "use-docker" + }, + { + "depth": 2, + "title": "Configure and Run Your Node", + "anchor": "configure-and-run-your-node" }, { "depth": 3, - "title": "Local Provider", - "anchor": "local-provider" + "title": "RPC Configurations", + "anchor": "rpc-configurations" }, { "depth": 2, - "title": "Configure Zombienet", - "anchor": "configure-zombienet" + "title": "Sync Your Node", + "anchor": "sync-your-node" }, { "depth": 3, - "title": "Configuration Files", - "anchor": "configuration-files" + "title": "Connect to Your Node", + "anchor": "connect-to-your-node" + } + ], + "stats": { + "chars": 15944, + "words": 2481, + "headings": 9, + "estimated_token_count_total": 4196 + }, + "hash": "sha256:924fab837818610c825be5cefde0a7bacd46985b4fa05cfa0376a941105b9869", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-node-secure-wss", + "title": "Set Up Secure WebSocket", + "slug": "nodes-and-validators-run-a-node-secure-wss", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-node-secure-wss.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-node/secure-wss/", + "preview": "Ensuring secure WebSocket communication is crucial for maintaining the integrity and security of a Polkadot or Kusama node when interacting with remote clients. This guide walks you through setting up a secure WebSocket (WSS) connection for your node by leveraging SSL encryption with popular web server proxies like nginx or Apache.", + "outline": [ + { + "depth": 2, + "title": "Introduction", + "anchor": "introduction" }, { - "depth": 3, - "title": "CLI Usage", - "anchor": "cli-usage" + "depth": 2, + "title": "Secure a WebSocket Port", + "anchor": "secure-a-websocket-port" }, { "depth": 3, - "title": "Settings", - "anchor": "settings" + "title": "Obtain an SSL Certificate", + "anchor": "obtain-an-ssl-certificate" }, { - "depth": 3, - "title": "Relay Chain Configuration", - "anchor": "relay-chain-configuration" + "depth": 2, + "title": "Install a Proxy Server", + "anchor": "install-a-proxy-server" }, { "depth": 3, - "title": "Parachain Configuration", - "anchor": "parachain-configuration" + "title": "Use nginx", + "anchor": "use-nginx" }, { "depth": 3, - "title": "XCM Configuration", - "anchor": "xcm-configuration" + "title": "Use Apache2", + "anchor": "use-apache2" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Connect to the Node", + "anchor": "connect-to-the-node" } ], "stats": { - "chars": 41636, - "words": 4599, - "headings": 14, - "estimated_token_count_total": 9871 + "chars": 5568, + "words": 774, + "headings": 7, + "estimated_token_count_total": 1280 }, - "hash": "sha256:0d7e04fd952cc9d5bd8cdbfd87cc4004c5f95e896a16bc7f89dfc4caeac8f371", + "hash": "sha256:992082e4ad87348b283f6c37ea886ae0e7bf016852b6470000876f3d169c65a4", "token_estimator": "heuristic-v1" }, { - "id": "reference-glossary", - "title": "Glossary", - "slug": "reference-glossary", + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", + "title": "Validator Key Management", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management", "categories": [ - "Reference" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md", - "html_url": "https://docs.polkadot.com/reference/glossary/", - "preview": "Key definitions, concepts, and terminology specific to the Polkadot ecosystem are included here.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-key-management.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/", + "preview": "After setting up your node environment as shown in the [Setup](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/){target=\\_blank} section, you'll need to configure multiple keys for your validator to operate properly. This includes setting up session keys, which are essential for participating in the consensus process, and configuring a node key that maintains a stable network identity. This guide walks you through the key management process, showing you how to g", "outline": [ { "depth": 2, - "title": "Authority", - "anchor": "authority" - }, - { - "depth": 2, - "title": "Authority Round (Aura)", - "anchor": "authority-round-aura" - }, - { - "depth": 2, - "title": "Blind Assignment of Blockchain Extension (BABE)", - "anchor": "blind-assignment-of-blockchain-extension-babe" - }, - { - "depth": 2, - "title": "Block Author", - "anchor": "block-author" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Byzantine Fault Tolerance (BFT)", - "anchor": "byzantine-fault-tolerance-bft" + "title": "Set Session Keys", + "anchor": "set-session-keys" }, { "depth": 3, - "title": "Byzantine Failure", - "anchor": "byzantine-failure" + "title": "Generate Session Keys", + "anchor": "generate-session-keys" }, { "depth": 3, - "title": "Practical Byzantine Fault Tolerance (pBFT)", - "anchor": "practical-byzantine-fault-tolerance-pbft" + "title": "Submit Transaction to Set Keys", + "anchor": "submit-transaction-to-set-keys" }, { "depth": 3, - "title": "Preimage", - "anchor": "preimage" + "title": "Verify Session Key Setup", + "anchor": "verify-session-key-setup" }, { "depth": 2, - "title": "Call", - "anchor": "call" + "title": "Set the Node Key", + "anchor": "set-the-node-key" }, { - "depth": 2, - "title": "Chain Specification", - "anchor": "chain-specification" + "depth": 3, + "title": "Generate the Node Key", + "anchor": "generate-the-node-key" }, + { + "depth": 3, + "title": "Set Node Key", + "anchor": "set-node-key" + } + ], + "stats": { + "chars": 8227, + "words": 1183, + "headings": 8, + "estimated_token_count_total": 1840 + }, + "hash": "sha256:0fb5a83835aab263c0b9aa886028c8aa8a2d6d0897d7b9fff4b5258835d30dfe", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", + "title": "Set Up a Validator", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-set-up-validator.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/set-up-validator/", + "preview": "Setting up a Polkadot validator node is essential for securing the network and earning staking rewards. This guide walks you through the technical steps to set up a validator, from installing the necessary software to managing keys and synchronizing your node with the chain.", + "outline": [ { "depth": 2, - "title": "Collator", - "anchor": "collator" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Collective", - "anchor": "collective" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Consensus", - "anchor": "consensus" + "title": "Initial Setup", + "anchor": "initial-setup" }, { - "depth": 2, - "title": "Consensus Algorithm", - "anchor": "consensus-algorithm" + "depth": 3, + "title": "Install Network Time Protocol Client", + "anchor": "install-network-time-protocol-client" }, { - "depth": 2, - "title": "Consensus Engine", - "anchor": "consensus-engine" + "depth": 3, + "title": "Verify Landlock is Activated", + "anchor": "verify-landlock-is-activated" }, { "depth": 2, - "title": "Coretime", - "anchor": "coretime" + "title": "Install the Polkadot Binaries", + "anchor": "install-the-polkadot-binaries" }, { - "depth": 2, - "title": "Development Phrase", - "anchor": "development-phrase" + "depth": 3, + "title": "Install from Official Releases", + "anchor": "install-from-official-releases" }, { - "depth": 2, - "title": "Digest", - "anchor": "digest" + "depth": 3, + "title": "Install with Package Managers", + "anchor": "install-with-package-managers" }, { - "depth": 2, - "title": "Dispatchable", - "anchor": "dispatchable" + "depth": 3, + "title": "Install with Ansible", + "anchor": "install-with-ansible" }, { - "depth": 2, - "title": "Events", - "anchor": "events" + "depth": 3, + "title": "Install with Docker", + "anchor": "install-with-docker" }, { - "depth": 2, - "title": "Executor", - "anchor": "executor" + "depth": 3, + "title": "Build from Sources", + "anchor": "build-from-sources" }, { "depth": 2, - "title": "Existential Deposit", - "anchor": "existential-deposit" - }, + "title": "Verify Installation", + "anchor": "verify-installation" + } + ], + "stats": { + "chars": 11921, + "words": 1678, + "headings": 12, + "estimated_token_count_total": 2592 + }, + "hash": "sha256:d2c1c91734bc8185057d8eeec6829ea91e0316f7ba884c5dc3922a5e5778815e", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", + "title": "Start Validating", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-start-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/start-validating/", + "preview": "After configuring your node keys as shown in the [Key Management](/nodes-and-validators/run-a-validator/onboarding-and-offboarding/key-management/){target=\\_blank} section and ensuring your system is set up, you're ready to begin the validator setup process. This guide will walk you through choosing a network, synchronizing your node with the blockchain, bonding your DOT tokens, and starting your validator.", + "outline": [ { "depth": 2, - "title": "Extrinsic", - "anchor": "extrinsic" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Fork Choice Rule/Strategy", - "anchor": "fork-choice-rulestrategy" + "title": "Choose a Network", + "anchor": "choose-a-network" }, { "depth": 2, - "title": "FRAME (Framework for Runtime Aggregation of Modularized Entities)", - "anchor": "frame-framework-for-runtime-aggregation-of-modularized-entities" + "title": "Synchronize Chain Data", + "anchor": "synchronize-chain-data" }, { - "depth": 2, - "title": "Full Node", - "anchor": "full-node" + "depth": 3, + "title": "Database Snapshot Services", + "anchor": "database-snapshot-services" }, { "depth": 2, - "title": "Genesis Configuration", - "anchor": "genesis-configuration" + "title": "Bond DOT", + "anchor": "bond-dot" }, { - "depth": 2, - "title": "GRANDPA", - "anchor": "grandpa" + "depth": 3, + "title": "Bonding DOT on Polkadot.js Apps", + "anchor": "bonding-dot-on-polkadotjs-apps" }, { "depth": 2, - "title": "Header", - "anchor": "header" + "title": "Validate", + "anchor": "validate" }, { - "depth": 2, - "title": "Hybrid Consensus", - "anchor": "hybrid-consensus" + "depth": 3, + "title": "Verify Sync via Telemetry", + "anchor": "verify-sync-via-telemetry" }, { - "depth": 2, - "title": "Inherent Transactions", - "anchor": "inherent-transactions" + "depth": 3, + "title": "Activate using Polkadot.js Apps", + "anchor": "activate-using-polkadotjs-apps" }, { - "depth": 2, - "title": "JSON-RPC", - "anchor": "json-rpc" + "depth": 3, + "title": "Monitor Validation Status and Slots", + "anchor": "monitor-validation-status-and-slots" }, { "depth": 2, - "title": "Keystore", - "anchor": "keystore" + "title": "Run a Validator Using Systemd", + "anchor": "run-a-validator-using-systemd" }, { - "depth": 2, - "title": "Kusama", - "anchor": "kusama" + "depth": 3, + "title": "Create the Systemd Service File", + "anchor": "create-the-systemd-service-file" }, + { + "depth": 3, + "title": "Run the Service", + "anchor": "run-the-service" + } + ], + "stats": { + "chars": 15820, + "words": 2446, + "headings": 13, + "estimated_token_count_total": 3861 + }, + "hash": "sha256:67a43e787805244196e1e9cb962069292c69ed5fdb1110df57c942019892b953", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", + "title": "Stop Validating", + "slug": "nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-onboarding-and-offboarding-stop-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/onboarding-and-offboarding/stop-validating/", + "preview": "If you're ready to stop validating on Polkadot, there are essential steps to ensure a smooth transition while protecting your funds and account integrity. Whether you're taking a break for maintenance or unbonding entirely, you'll need to chill your validator, purge session keys, and unbond your tokens. This guide explains how to use Polkadot's tools and extrinsics to safely withdraw from validation activities, safeguarding your account's future usability.", + "outline": [ { "depth": 2, - "title": "libp2p", - "anchor": "libp2p" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Light Client", - "anchor": "light-client" + "title": "Pause Versus Stop", + "anchor": "pause-versus-stop" }, { "depth": 2, - "title": "Metadata", - "anchor": "metadata" + "title": "Chill Validator", + "anchor": "chill-validator" }, { "depth": 2, - "title": "Nominated Proof of Stake (NPoS)", - "anchor": "nominated-proof-of-stake-npos" + "title": "Purge Validator Session Keys", + "anchor": "purge-validator-session-keys" }, { "depth": 2, - "title": "Oracle", - "anchor": "oracle" - }, + "title": "Unbond Your Tokens", + "anchor": "unbond-your-tokens" + } + ], + "stats": { + "chars": 3230, + "words": 500, + "headings": 5, + "estimated_token_count_total": 629 + }, + "hash": "sha256:0d6db361bfa7a3022849bbe39989bfdac0429537498d7f534adadec131afca98", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-validator-operational-tasks-general-management", + "title": "General Management", + "slug": "nodes-and-validators-run-a-validator-operational-tasks-general-management", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-general-management.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/general-management/", + "preview": "Validator performance is pivotal in maintaining the security and stability of the Polkadot network. As a validator, optimizing your setup ensures efficient transaction processing, minimizes latency, and maintains system reliability during high-demand periods. Proper configuration and proactive monitoring also help mitigate risks like slashing and service interruptions.", + "outline": [ { "depth": 2, - "title": "Origin", - "anchor": "origin" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Pallet", - "anchor": "pallet" + "title": "Configuration Optimization", + "anchor": "configuration-optimization" }, { - "depth": 2, - "title": "Parachain", - "anchor": "parachain" + "depth": 3, + "title": "Deactivate Simultaneous Multithreading", + "anchor": "deactivate-simultaneous-multithreading" }, { - "depth": 2, - "title": "Paseo", - "anchor": "paseo" + "depth": 3, + "title": "Deactivate Automatic NUMA Balancing", + "anchor": "deactivate-automatic-numa-balancing" }, { - "depth": 2, - "title": "Polkadot", - "anchor": "polkadot" + "depth": 3, + "title": "Spectre and Meltdown Mitigations", + "anchor": "spectre-and-meltdown-mitigations" }, { "depth": 2, - "title": "Polkadot Cloud", - "anchor": "polkadot-cloud" + "title": "Monitor Your Node", + "anchor": "monitor-your-node" }, { - "depth": 2, - "title": "Polkadot Hub", - "anchor": "polkadot-hub" + "depth": 3, + "title": "Environment Setup", + "anchor": "environment-setup" }, { - "depth": 2, - "title": "PolkaVM", - "anchor": "polkavm" + "depth": 3, + "title": "Install and Configure Prometheus", + "anchor": "install-and-configure-prometheus" }, { - "depth": 2, - "title": "Relay Chain", - "anchor": "relay-chain" + "depth": 3, + "title": "Start Prometheus", + "anchor": "start-prometheus" }, { - "depth": 2, - "title": "Rococo", - "anchor": "rococo" + "depth": 3, + "title": "Install and Configure Grafana", + "anchor": "install-and-configure-grafana" }, { - "depth": 2, - "title": "Runtime", - "anchor": "runtime" + "depth": 3, + "title": "Install and Configure Alertmanager", + "anchor": "install-and-configure-alertmanager" }, { "depth": 2, - "title": "Slot", - "anchor": "slot" + "title": "Secure Your Validator", + "anchor": "secure-your-validator" }, { - "depth": 2, - "title": "Sovereign Account", - "anchor": "sovereign-account" + "depth": 3, + "title": "Key Management", + "anchor": "key-management" }, { - "depth": 2, - "title": "SS58 Address Format", - "anchor": "ss58-address-format" + "depth": 3, + "title": "Signing Outside the Client", + "anchor": "signing-outside-the-client" }, { - "depth": 2, - "title": "State Transition Function (STF)", - "anchor": "state-transition-function-stf" + "depth": 3, + "title": "Secure-Validator Mode", + "anchor": "secure-validator-mode" }, { - "depth": 2, - "title": "Storage Item", - "anchor": "storage-item" + "depth": 3, + "title": "Linux Best Practices", + "anchor": "linux-best-practices" }, { - "depth": 2, - "title": "Substrate", - "anchor": "substrate" + "depth": 3, + "title": "Validator Best Practices", + "anchor": "validator-best-practices" }, { "depth": 2, - "title": "Transaction", - "anchor": "transaction" - }, + "title": "Additional Resources", + "anchor": "additional-resources" + } + ], + "stats": { + "chars": 26673, + "words": 3357, + "headings": 18, + "estimated_token_count_total": 5866 + }, + "hash": "sha256:81eb0fe77f05155f1ec0511cd066120fc9994961e9d91e21b6666377e65b4586", + "token_estimator": "heuristic-v1" + }, + { + "id": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", + "title": "Pause Validating", + "slug": "nodes-and-validators-run-a-validator-operational-tasks-pause-validating", + "categories": [ + "Infrastructure" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-pause-validating.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/pause-validating/", + "preview": "If you need to temporarily stop participating in Polkadot staking activities without fully unbonding your funds, chilling your account allows you to do so efficiently. Chilling removes your node from active validation or nomination in the next era while keeping your funds bonded, making it ideal for planned downtimes or temporary pauses.", + "outline": [ { "depth": 2, - "title": "Transaction Era", - "anchor": "transaction-era" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "Trie (Patricia Merkle Tree)", - "anchor": "trie-patricia-merkle-tree" + "title": "Chilling Your Node", + "anchor": "chilling-your-node" }, { "depth": 2, - "title": "Validator", - "anchor": "validator" + "title": "Staking Election Timing Considerations", + "anchor": "staking-election-timing-considerations" }, { "depth": 2, - "title": "WebAssembly (Wasm)", - "anchor": "webassembly-wasm" + "title": "Chilling as a Nominator", + "anchor": "chilling-as-a-nominator" }, { "depth": 2, - "title": "Weight", - "anchor": "weight" + "title": "Chilling as a Validator", + "anchor": "chilling-as-a-validator" }, { "depth": 2, - "title": "Westend", - "anchor": "westend" + "title": "Chill Other", + "anchor": "chill-other" } ], "stats": { - "chars": 24739, - "words": 3626, - "headings": 63, - "estimated_token_count_total": 5273 + "chars": 4439, + "words": 679, + "headings": 6, + "estimated_token_count_total": 861 }, - "hash": "sha256:40bd67811e7eabc79ca5d105eae388b19380d9f035022da17fc0d6bb173c817c", + "hash": "sha256:1af153570ce57bd5b52d08493a300996765686f2a6d04519a2e0aa91191612c1", "token_estimator": "heuristic-v1" }, { - "id": "reference-governance-origins-tracks", - "title": "Origins and Tracks", - "slug": "reference-governance-origins-tracks", + "id": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", + "title": "Upgrade a Validator Node", + "slug": "nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node", "categories": [ - "Polkadot Protocol" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance-origins-tracks.md", - "html_url": "https://docs.polkadot.com/reference/governance/origins-tracks/", - "preview": "Polkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-operational-tasks-upgrade-your-node.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/operational-tasks/upgrade-your-node/", + "preview": "Upgrading a Polkadot validator node is essential for staying current with network updates and maintaining optimal performance. This guide covers routine and extended maintenance scenarios, including software upgrades and major server changes. Following these steps, you can manage session keys and transition smoothly between servers without risking downtime, slashing, or network disruptions. The process requires strategic planning, especially if you need to perform long-lead maintenance, ensuring", "outline": [ { "depth": 2, @@ -4000,40 +840,54 @@ }, { "depth": 2, - "title": "Origins", - "anchor": "origins" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Tracks", - "anchor": "tracks" + "title": "Session Keys", + "anchor": "session-keys" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Keystore", + "anchor": "keystore" + }, + { + "depth": 2, + "title": "Upgrade Using Backup Validator", + "anchor": "upgrade-using-backup-validator" + }, + { + "depth": 3, + "title": "Session `N`", + "anchor": "session-n" + }, + { + "depth": 3, + "title": "Session `N+3`", + "anchor": "session-n3" } ], "stats": { - "chars": 3333, - "words": 469, - "headings": 4, - "estimated_token_count_total": 631 + "chars": 5650, + "words": 851, + "headings": 7, + "estimated_token_count_total": 1185 }, - "hash": "sha256:baba9dd41091b792d09005d55d3df0bf65b35f42b40ebe63caf425a0978a22b0", + "hash": "sha256:888230b128d8c648c4f06a18d3b1d1b06dd1bf22a0de4add1f28210ffccb2549", "token_estimator": "heuristic-v1" }, { - "id": "reference-governance", - "title": "On-Chain Governance Overview", - "slug": "reference-governance", + "id": "nodes-and-validators-run-a-validator-requirements", + "title": "Validator Requirements", + "slug": "nodes-and-validators-run-a-validator-requirements", "categories": [ - "Basics", - "Polkadot Protocol" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md", - "html_url": "https://docs.polkadot.com/reference/governance/", - "preview": "Polkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-requirements.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/requirements/", + "preview": "Running a validator in the Polkadot ecosystem is essential for maintaining network security and decentralization. Validators are responsible for validating transactions and adding new blocks to the chain, ensuring the system operates smoothly. In return for their services, validators earn rewards. However, the role comes with inherent risks, such as slashing penalties for misbehavior or technical failures. If you’re new to validation, starting on Kusama provides a lower-stakes environment to gai", "outline": [ { "depth": 2, @@ -4042,65 +896,44 @@ }, { "depth": 2, - "title": "Governance Evolution", - "anchor": "governance-evolution" - }, - { - "depth": 2, - "title": "OpenGov Key Features", - "anchor": "opengov-key-features" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Origins and Tracks", - "anchor": "origins-and-tracks" + "title": "Minimum Hardware Requirements", + "anchor": "minimum-hardware-requirements" }, { "depth": 2, - "title": "Referendums", - "anchor": "referendums" - }, - { - "depth": 3, - "title": "Vote on Referendums", - "anchor": "vote-on-referendums" - }, - { - "depth": 3, - "title": "Delegate Voting Power", - "anchor": "delegate-voting-power" - }, - { - "depth": 3, - "title": "Cancel a Referendum", - "anchor": "cancel-a-referendum" + "title": "VPS Provider List", + "anchor": "vps-provider-list" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Minimum Bond Requirement", + "anchor": "minimum-bond-requirement" } ], "stats": { - "chars": 7493, - "words": 1019, - "headings": 9, - "estimated_token_count_total": 1611 + "chars": 6842, + "words": 944, + "headings": 5, + "estimated_token_count_total": 1485 }, - "hash": "sha256:62beec261e72529f70e07a641177d489d2c8872f9c9d618cbadf1ac0fd881986", + "hash": "sha256:46435b97c37ef6798d2c75c69df31c5e5f07e04b218c370ec5af6b1838d43aac", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-accounts", - "title": "Polkadot SDK Accounts", - "slug": "reference-parachains-accounts", + "id": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", + "title": "Offenses and Slashes", + "slug": "nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes", "categories": [ - "Basics", - "Polkadot Protocol" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md", - "html_url": "https://docs.polkadot.com/reference/parachains/accounts/", - "preview": "Accounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-offenses-and-slashes.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/offenses-and-slashes/", + "preview": "In Polkadot's Nominated Proof of Stake (NPoS) system, validator misconduct is deterred through a combination of slashing, disabling, and reputation penalties. Validators and nominators who stake tokens face consequences for validator misbehavior, which range from token slashes to restrictions on network participation.", "outline": [ { "depth": 2, @@ -4109,95 +942,64 @@ }, { "depth": 2, - "title": "Account Data Structure", - "anchor": "account-data-structure" - }, - { - "depth": 3, - "title": "Account", - "anchor": "account" - }, - { - "depth": 3, - "title": "Account Info", - "anchor": "account-info" - }, - { - "depth": 3, - "title": "Account Reference Counters", - "anchor": "account-reference-counters" - }, - { - "depth": 2, - "title": "Account Balance Types", - "anchor": "account-balance-types" - }, - { - "depth": 3, - "title": "Balance Types", - "anchor": "balance-types" + "title": "Offenses", + "anchor": "offenses" }, { "depth": 3, - "title": "Locks", - "anchor": "locks" + "title": "Invalid Votes", + "anchor": "invalid-votes" }, { "depth": 3, - "title": "Balance Types on Polkadot.js", - "anchor": "balance-types-on-polkadotjs" + "title": "Equivocations", + "anchor": "equivocations" }, { "depth": 2, - "title": "Address Formats", - "anchor": "address-formats" - }, - { - "depth": 3, - "title": "Basic Format", - "anchor": "basic-format" + "title": "Penalties", + "anchor": "penalties" }, { "depth": 3, - "title": "Address Type", - "anchor": "address-type" + "title": "Slashing", + "anchor": "slashing" }, { "depth": 3, - "title": "Address Length", - "anchor": "address-length" + "title": "Disabling", + "anchor": "disabling" }, { "depth": 3, - "title": "Checksum Types", - "anchor": "checksum-types" + "title": "Reputation Changes", + "anchor": "reputation-changes" }, { "depth": 3, - "title": "Validating Addresses", - "anchor": "validating-addresses" + "title": "Penalties by Offense", + "anchor": "penalties-by-offense" } ], "stats": { - "chars": 29604, - "words": 4194, - "headings": 15, - "estimated_token_count_total": 6507 + "chars": 15427, + "words": 2103, + "headings": 9, + "estimated_token_count_total": 3409 }, - "hash": "sha256:0104a9132a69345a2faac37fca0e2853a2ded1efb009511a83a98d44509ab887", + "hash": "sha256:abe6bedab04f463ec07f554977b8d6355a5d2fad9bcda01cbe58568152295daa", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-blocks", - "title": "Blocks", - "slug": "reference-parachains-blocks-transactions-fees-blocks", + "id": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", + "title": "Rewards Payout", + "slug": "nodes-and-validators-run-a-validator-staking-mechanics-rewards", "categories": [ - "Basics", - "Polkadot Protocol" + "Infrastructure" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/blocks/", - "preview": "In the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/nodes-and-validators-run-a-validator-staking-mechanics-rewards.md", + "html_url": "https://docs.polkadot.com/nodes-and-validators/run-a-validator/staking-mechanics/rewards/", + "preview": "Understanding how rewards are distributed to validators and nominators is essential for network participants. In Polkadot and Kusama, validators earn rewards based on their era points, which are accrued through actions like block production and parachain validation.", "outline": [ { "depth": 2, @@ -4206,157 +1008,140 @@ }, { "depth": 2, - "title": "What is a Block?", - "anchor": "what-is-a-block" + "title": "Era Points", + "anchor": "era-points" }, { "depth": 2, - "title": "Block Production", - "anchor": "block-production" - }, - { - "depth": 3, - "title": "Initialize Block", - "anchor": "initialize-block" - }, - { - "depth": 3, - "title": "Finalize Block", - "anchor": "finalize-block" + "title": "Reward Variance", + "anchor": "reward-variance" }, { "depth": 2, - "title": "Block Authoring and Import", - "anchor": "block-authoring-and-import" + "title": "Payout Scheme", + "anchor": "payout-scheme" }, { - "depth": 3, - "title": "Block Import Queue", - "anchor": "block-import-queue" + "depth": 2, + "title": "Running Multiple Validators", + "anchor": "running-multiple-validators" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Nominators and Validator Payments", + "anchor": "nominators-and-validator-payments" } ], "stats": { - "chars": 6252, - "words": 910, - "headings": 8, - "estimated_token_count_total": 1395 + "chars": 10976, + "words": 1753, + "headings": 6, + "estimated_token_count_total": 2588 }, - "hash": "sha256:424783c102bea5dae5b8749635858c6c59055563442a98f57521f0027dafa8d3", + "hash": "sha256:d5d6d72eb2cf10f624d84c65f2274f7df90acb5d071bf170bc8eae8d98a810a5", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-fees", - "title": "Transactions Weights and Fees", - "slug": "reference-parachains-blocks-transactions-fees-fees", + "id": "parachains-customize-runtime-add-existing-pallets", + "title": "Add an Existing Pallet to the Runtime", + "slug": "parachains-customize-runtime-add-existing-pallets", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/fees/", - "preview": "When transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop th", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-existing-pallets.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-existing-pallets/", + "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a functional runtime that includes default [FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} development modules ([pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}) to help you get started building a custo", "outline": [ { "depth": 2, - "title": "Introductions", - "anchor": "introductions" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, - "title": "How Fees are Calculated", - "anchor": "how-fees-are-calculated" + "title": "Check Prerequisites", + "anchor": "check-prerequisites" }, { "depth": 2, - "title": "Using the Transaction Payment Pallet", - "anchor": "using-the-transaction-payment-pallet" + "title": "Add an Existing Polkadot SDK Pallet to Your Runtime", + "anchor": "add-an-existing-polkadot-sdk-pallet-to-your-runtime" }, { "depth": 3, - "title": "Understanding the Inclusion Fee", - "anchor": "understanding-the-inclusion-fee" + "title": "Add an Existing Pallet as a Dependency", + "anchor": "add-an-existing-pallet-as-a-dependency" }, { "depth": 3, - "title": "Accounts with an Insufficient Balance", - "anchor": "accounts-with-an-insufficient-balance" + "title": "Enable Standard Library Features", + "anchor": "enable-standard-library-features" }, { "depth": 3, - "title": "Fee Multipliers", - "anchor": "fee-multipliers" - }, - { - "depth": 2, - "title": "Transactions with Special Requirements", - "anchor": "transactions-with-special-requirements" - }, - { - "depth": 2, - "title": "Default Weight Annotations", - "anchor": "default-weight-annotations" + "title": "Review the Config Trait", + "anchor": "review-the-config-trait" }, { "depth": 3, - "title": "Weights and Database Read/Write Operations", - "anchor": "weights-and-database-readwrite-operations" + "title": "Implement the Config Trait", + "anchor": "implement-the-config-trait" }, { "depth": 3, - "title": "Dispatch Classes", - "anchor": "dispatch-classes" + "title": "Add to Runtime Construct", + "anchor": "add-to-runtime-construct" }, { "depth": 3, - "title": "Dynamic Weights", - "anchor": "dynamic-weights" + "title": "Verify the Runtime Compiles", + "anchor": "verify-the-runtime-compiles" }, { "depth": 2, - "title": "Post Dispatch Weight Correction", - "anchor": "post-dispatch-weight-correction" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { - "depth": 2, - "title": "Custom Fees", - "anchor": "custom-fees" + "depth": 3, + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" + }, + { + "depth": 3, + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" }, { "depth": 3, - "title": "Custom Weights", - "anchor": "custom-weights" + "title": "Interact with the Pallet", + "anchor": "interact-with-the-pallet" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 20800, - "words": 2917, - "headings": 15, - "estimated_token_count_total": 4464 + "chars": 11924, + "words": 1585, + "headings": 14, + "estimated_token_count_total": 2724 }, - "hash": "sha256:7d0c3fa7982b3e1843adb8f27422456397580b3a3eba5047b381da8517742536", + "hash": "sha256:93d123cbaaccc2515b4a70be8e1327b4f75b1051d16c5e3daf5a2035af7b7ca3", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-blocks-transactions-fees-transactions", - "title": "Transactions", - "slug": "reference-parachains-blocks-transactions-fees-transactions", + "id": "parachains-customize-runtime-add-pallet-instances", + "title": "Add Multiple Pallet Instances", + "slug": "parachains-customize-runtime-add-pallet-instances", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md", - "html_url": "https://docs.polkadot.com/reference/parachains/blocks-transactions-fees/transactions/", - "preview": "Transactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-pallet-instances.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-pallet-instances/", + "preview": "The [Polkadot SDK Parachain Template](https://github.com/paritytech/polkadot-sdk-parachain-template){target=\\_blank} provides a solid foundation for building custom parachains. While most pallets are typically included as single instances within a runtime, some scenarios benefit from running multiple instances of the same pallet with different configurations. This approach lets you reuse pallet logic without reimplementing it, enabling diverse functionality from a single codebase.", "outline": [ { "depth": 2, @@ -4365,130 +1150,124 @@ }, { "depth": 2, - "title": "What Is a Transaction?", - "anchor": "what-is-a-transaction" + "title": "Check Prerequisites", + "anchor": "check-prerequisites" }, { - "depth": 3, - "title": "Signed Transactions", - "anchor": "signed-transactions" + "depth": 2, + "title": "Understanding Instantiable Pallets", + "anchor": "understanding-instantiable-pallets" }, { "depth": 3, - "title": "Unsigned Transactions", - "anchor": "unsigned-transactions" + "title": "Identifying an Instantiable Pallet", + "anchor": "identifying-an-instantiable-pallet" }, { "depth": 3, - "title": "Inherent Transactions", - "anchor": "inherent-transactions" + "title": "How Instance Generics Work", + "anchor": "how-instance-generics-work" }, { "depth": 2, - "title": "Transaction Formats", - "anchor": "transaction-formats" + "title": "Add Multiple Instances of a Pallet to Your Runtime", + "anchor": "add-multiple-instances-of-a-pallet-to-your-runtime" }, { "depth": 3, - "title": "Types of Transaction Formats", - "anchor": "types-of-transaction-formats" + "title": "Add the Pallet as a Dependency", + "anchor": "add-the-pallet-as-a-dependency" }, { "depth": 3, - "title": "Signed Transaction Data Structure", - "anchor": "signed-transaction-data-structure" + "title": "Enable Standard Library Features", + "anchor": "enable-standard-library-features" }, { "depth": 3, - "title": "Signed Extensions", - "anchor": "signed-extensions" - }, - { - "depth": 2, - "title": "Transaction Construction", - "anchor": "transaction-construction" + "title": "Review the Config Trait", + "anchor": "review-the-config-trait" }, { "depth": 3, - "title": "Construct a Signed Transaction", - "anchor": "construct-a-signed-transaction" + "title": "Define Pallet Parameters", + "anchor": "define-pallet-parameters" }, { "depth": 3, - "title": "Transaction Encoding", - "anchor": "transaction-encoding" + "title": "Create Instance Type Definitions", + "anchor": "create-instance-type-definitions" }, { "depth": 3, - "title": "Customize Transaction Construction", - "anchor": "customize-transaction-construction" + "title": "Implement Config Trait for First Instance", + "anchor": "implement-config-trait-for-first-instance" }, { - "depth": 2, - "title": "Lifecycle of a Transaction", - "anchor": "lifecycle-of-a-transaction" + "depth": 3, + "title": "Implement Config Trait for Second Instance", + "anchor": "implement-config-trait-for-second-instance" }, { "depth": 3, - "title": "Define Transaction Properties", - "anchor": "define-transaction-properties" + "title": "Add Instances to Runtime Construct", + "anchor": "add-instances-to-runtime-construct" }, { "depth": 3, - "title": "Process on a Block Authoring Node", - "anchor": "process-on-a-block-authoring-node" + "title": "Verify the Runtime Compiles", + "anchor": "verify-the-runtime-compiles" }, { - "depth": 3, - "title": "Validate and Queue", - "anchor": "validate-and-queue" + "depth": 2, + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { "depth": 3, - "title": "Transaction Ordering and Priority", - "anchor": "transaction-ordering-and-priority" + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" }, { "depth": 3, - "title": "Transaction Execution", - "anchor": "transaction-execution" + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" }, { - "depth": 2, - "title": "Transaction Mortality", - "anchor": "transaction-mortality" + "depth": 3, + "title": "Interact with Both Pallet Instances", + "anchor": "interact-with-both-pallet-instances" }, { - "depth": 2, - "title": "Unique Identifiers for Extrinsics", - "anchor": "unique-identifiers-for-extrinsics" + "depth": 3, + "title": "Test Instance Independence", + "anchor": "test-instance-independence" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 23610, - "words": 3333, - "headings": 22, - "estimated_token_count_total": 4708 + "chars": 17923, + "words": 2203, + "headings": 21, + "estimated_token_count_total": 3811 }, - "hash": "sha256:66726634d3a51cd9c471621054a6e5f09c8061dca6144b64c8bcf45626359617", + "hash": "sha256:d83e574726c524fa017236eb5e3b8a0676d598be4da1ce4fe25a60141baeee49", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-chain-data", - "title": "Chain Data", - "slug": "reference-parachains-chain-data", - "categories": [ - "Basics", - "Polkadot Protocol" + "id": "parachains-customize-runtime-add-smart-contract-functionality", + "title": "Add Smart Contract Functionality", + "slug": "parachains-customize-runtime-add-smart-contract-functionality", + "categories": [ + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md", - "html_url": "https://docs.polkadot.com/reference/parachains/chain-data/", - "preview": "Understanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-add-smart-contract-functionality.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/add-smart-contract-functionality/", + "preview": "When building your custom blockchain with the Polkadot SDK, you can add smart contract capabilities through specialized pallets. These pallets enable users to deploy and execute smart contracts, enhancing your chain's programmability and allowing developers to build decentralized applications on your network.", "outline": [ { "depth": 2, @@ -4497,114 +1276,100 @@ }, { "depth": 2, - "title": "Application Development", - "anchor": "application-development" + "title": "pallet-revive", + "anchor": "pallet-revive" }, { - "depth": 2, - "title": "Understand Metadata", - "anchor": "understand-metadata" + "depth": 3, + "title": "Core Components", + "anchor": "core-components" }, { - "depth": 2, - "title": "Expose Runtime Information as Metadata", - "anchor": "expose-runtime-information-as-metadata" + "depth": 3, + "title": "Supported Languages and Compilers", + "anchor": "supported-languages-and-compilers" }, { - "depth": 2, - "title": "Generate Metadata", - "anchor": "generate-metadata" + "depth": 3, + "title": "How It Works", + "anchor": "how-it-works" }, { - "depth": 2, - "title": "Retrieve Runtime Metadata", - "anchor": "retrieve-runtime-metadata" + "depth": 3, + "title": "Key Benefits", + "anchor": "key-benefits" }, { "depth": 3, - "title": "Use Polkadot.js", - "anchor": "use-polkadotjs" + "title": "Implementation Examples", + "anchor": "implementation-examples" }, { - "depth": 3, - "title": "Use Curl", - "anchor": "use-curl" + "depth": 2, + "title": "Frontier", + "anchor": "frontier" }, { "depth": 3, - "title": "Use Subxt", - "anchor": "use-subxt" + "title": "Integration Options", + "anchor": "integration-options" }, { - "depth": 2, - "title": "Client Applications and Metadata", - "anchor": "client-applications-and-metadata" + "depth": 3, + "title": "EVM Execution Only", + "anchor": "evm-execution-only" }, { - "depth": 2, - "title": "Metadata Format", - "anchor": "metadata-format" + "depth": 3, + "title": "Full Ethereum Compatibility", + "anchor": "full-ethereum-compatibility" }, { "depth": 3, - "title": "Pallets", - "anchor": "pallets" + "title": "Key Benefits", + "anchor": "key-benefits-2" }, { "depth": 3, - "title": "Extrinsic", - "anchor": "extrinsic" + "title": "Implementation Examples", + "anchor": "implementation-examples-2" }, { "depth": 2, - "title": "Included RPC APIs", - "anchor": "included-rpc-apis" + "title": "pallet-contracts (Legacy)", + "anchor": "pallet-contracts-legacy" + }, + { + "depth": 3, + "title": "Implementation Example", + "anchor": "implementation-example" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 18650, - "words": 2216, - "headings": 15, - "estimated_token_count_total": 3774 - }, - "hash": "sha256:49238d1e9e2c33e0fcd3a84b5e30f0d3840d7d23a783b538875e0a23f38efc1d", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-consensus-async-backing", - "title": "reference-parachains-consensus-async-backing", - "slug": "reference-parachains-consensus-async-backing", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-async-backing.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/async-backing/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 6655, + "words": 833, + "headings": 16, + "estimated_token_count_total": 1631 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:6297bb5e0809fdd0585d6170054599f7ab4a3ce7c687ad03ae43092057c493b7", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-consensus-elastic-scaling", - "title": "Elastic Scaling", - "slug": "reference-parachains-consensus-elastic-scaling", + "id": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", + "title": "Add Pallets to the Runtime", + "slug": "parachains-customize-runtime-pallet-development-add-pallet-to-runtime", "categories": [ - "Polkadot Protocol" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-elastic-scaling.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/elastic-scaling/", - "preview": "Polkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-add-pallet-to-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/add-pallet-to-runtime/", + "preview": "In previous tutorials, you learned how to [create a custom pallet](/tutorials/polkadot-sdk/parachains/zero-to-hero/build-custom-pallet/){target=\\_blank} and [test it](/tutorials/polkadot-sdk/parachains/zero-to-hero/pallet-unit-testing/){target=\\_blank}. The next step is to include this pallet in your runtime, integrating it into the core logic of your blockchain.", "outline": [ { "depth": 2, @@ -4613,80 +1378,49 @@ }, { "depth": 2, - "title": "How Elastic Scaling Works", - "anchor": "how-elastic-scaling-works" - }, - { - "depth": 2, - "title": "Benefits of Elastic Scaling", - "anchor": "benefits-of-elastic-scaling" - }, - { - "depth": 2, - "title": "Use Cases", - "anchor": "use-cases" + "title": "Add the Pallets as Dependencies", + "anchor": "add-the-pallets-as-dependencies" }, { "depth": 3, - "title": "Handling Sudden Traffic Spikes", - "anchor": "handling-sudden-traffic-spikes" + "title": "Update the Runtime Configuration", + "anchor": "update-the-runtime-configuration" }, { - "depth": 3, - "title": "Supporting Early-Stage Growth", - "anchor": "supporting-early-stage-growth" + "depth": 2, + "title": "Recompile the Runtime", + "anchor": "recompile-the-runtime" }, { - "depth": 3, - "title": "Scaling Massive IoT Networks", - "anchor": "scaling-massive-iot-networks" + "depth": 2, + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { - "depth": 3, - "title": "Powering Real-Time, Low-Latency Systems", - "anchor": "powering-real-time-low-latency-systems" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 7871, - "words": 1047, - "headings": 8, - "estimated_token_count_total": 1440 - }, - "hash": "sha256:2d228c52844df8952520fafdd3e6f0e26bfd2f32b5ee60c6241cf7d38603643c", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-consensus", - "title": "reference-parachains-consensus", - "slug": "reference-parachains-consensus", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus.md", - "html_url": "https://docs.polkadot.com/reference/parachains/consensus/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 13091, + "words": 1522, + "headings": 6, + "estimated_token_count_total": 3091 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:87add0ae178e4970601a27efccadb58eff1375d19819201034ba2829914f1cd5", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-cryptography", - "title": "Cryptography", - "slug": "reference-parachains-cryptography", + "id": "parachains-customize-runtime-pallet-development-benchmark-pallet", + "title": "Benchmark Your Pallet", + "slug": "parachains-customize-runtime-pallet-development-benchmark-pallet", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md", - "html_url": "https://docs.polkadot.com/reference/parachains/cryptography/", - "preview": "Cryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-benchmark-pallet.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/benchmark-pallet/", + "preview": "Benchmarking is the process of measuring the computational resources (execution time and storage) required by your pallet's extrinsics. Accurate [weight](https://paritytech.github.io/polkadot-sdk/master/frame_support/weights/index.html){target=\\_blank} calculations are essential for ensuring your blockchain can process transactions efficiently while protecting against denial-of-service attacks.", "outline": [ { "depth": 2, @@ -4695,152 +1429,109 @@ }, { "depth": 2, - "title": "Hash Functions", - "anchor": "hash-functions" - }, - { - "depth": 3, - "title": "Key Properties of Hash Functions", - "anchor": "key-properties-of-hash-functions" - }, - { - "depth": 3, - "title": "Blake2", - "anchor": "blake2" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Types of Cryptography", - "anchor": "types-of-cryptography" - }, - { - "depth": 3, - "title": "Symmetric Cryptography", - "anchor": "symmetric-cryptography" + "title": "Create the Benchmarking Module", + "anchor": "create-the-benchmarking-module" }, { - "depth": 3, - "title": "Asymmetric Cryptography", - "anchor": "asymmetric-cryptography" + "depth": 2, + "title": "Define the Weight Trait", + "anchor": "define-the-weight-trait" }, { - "depth": 3, - "title": "Trade-offs and Compromises", - "anchor": "trade-offs-and-compromises" + "depth": 2, + "title": "Add WeightInfo to Config", + "anchor": "add-weightinfo-to-config" }, { "depth": 2, - "title": "Digital Signatures", - "anchor": "digital-signatures" + "title": "Update Extrinsic Weight Annotations", + "anchor": "update-extrinsic-weight-annotations" }, { - "depth": 3, - "title": "Example of Creating a Digital Signature", - "anchor": "example-of-creating-a-digital-signature" + "depth": 2, + "title": "Include the Benchmarking Module", + "anchor": "include-the-benchmarking-module" }, { "depth": 2, - "title": "Elliptic Curve", - "anchor": "elliptic-curve" + "title": "Configure Pallet Dependencies", + "anchor": "configure-pallet-dependencies" }, - { - "depth": 3, - "title": "Various Implementations", - "anchor": "various-implementations" - } - ], - "stats": { - "chars": 8860, - "words": 1293, - "headings": 12, - "estimated_token_count_total": 1797 - }, - "hash": "sha256:259dcef86aadc513675258b665cc3940db65af6eb32a5db85da6ac339966fa60", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-data-encoding", - "title": "Data Encoding", - "slug": "reference-parachains-data-encoding", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md", - "html_url": "https://docs.polkadot.com/reference/parachains/data-encoding/", - "preview": "The Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data.", - "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Update Mock Runtime", + "anchor": "update-mock-runtime" }, { "depth": 2, - "title": "SCALE Codec", - "anchor": "scale-codec" + "title": "Configure Runtime Benchmarking", + "anchor": "configure-runtime-benchmarking" }, { - "depth": 3, - "title": "Encode", - "anchor": "encode" + "depth": 2, + "title": "Test Benchmark Compilation", + "anchor": "test-benchmark-compilation" }, { - "depth": 3, - "title": "Decode", - "anchor": "decode" + "depth": 2, + "title": "Build the Runtime with Benchmarks", + "anchor": "build-the-runtime-with-benchmarks" }, { - "depth": 3, - "title": "CompactAs", - "anchor": "compactas" + "depth": 2, + "title": "Install the Benchmarking Tool", + "anchor": "install-the-benchmarking-tool" }, { - "depth": 3, - "title": "HasCompact", - "anchor": "hascompact" + "depth": 2, + "title": "Download the Weight Template", + "anchor": "download-the-weight-template" }, { - "depth": 3, - "title": "EncodeLike", - "anchor": "encodelike" + "depth": 2, + "title": "Execute Benchmarks", + "anchor": "execute-benchmarks" }, { - "depth": 3, - "title": "Data Types", - "anchor": "data-types" + "depth": 2, + "title": "Use Generated Weights", + "anchor": "use-generated-weights" }, { "depth": 2, - "title": "Encode and Decode Rust Trait Implementations", - "anchor": "encode-and-decode-rust-trait-implementations" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { "depth": 2, - "title": "SCALE Codec Libraries", - "anchor": "scale-codec-libraries" + "title": "Related Resources", + "anchor": "related-resources" } ], "stats": { - "chars": 13629, - "words": 1314, - "headings": 10, - "estimated_token_count_total": 3213 + "chars": 22752, + "words": 2813, + "headings": 18, + "estimated_token_count_total": 5191 }, - "hash": "sha256:e448294b6e52291ac0add5fa6533572814e6cd27af42bdaccc2000b86f52d775", + "hash": "sha256:c1b53ecbfc3dea02097104c7a4c652e61ccc42ad56325a9c80684850a198fbdd", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-interoperability", - "title": "Interoperability", - "slug": "reference-parachains-interoperability", + "id": "parachains-customize-runtime-pallet-development-create-a-pallet", + "title": "Create a Custom Pallet", + "slug": "parachains-customize-runtime-pallet-development-create-a-pallet", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md", - "html_url": "https://docs.polkadot.com/reference/parachains/interoperability/", - "preview": "Interoperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-create-a-pallet.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/create-a-pallet/", + "preview": "[Framework for Runtime Aggregation of Modular Entities (FRAME)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank} provides a powerful set of tools for blockchain development through modular components called [pallets](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/pallet/index.html){target=\\_blank}. These Rust-based runtime modules allow you to build custom blockchain functional", "outline": [ { "depth": 2, @@ -4849,200 +1540,149 @@ }, { "depth": 2, - "title": "Why Interoperability Matters", - "anchor": "why-interoperability-matters" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Key Mechanisms for Interoperability", - "anchor": "key-mechanisms-for-interoperability" - }, - { - "depth": 3, - "title": "Cross-Consensus Messaging (XCM): The Backbone of Communication", - "anchor": "cross-consensus-messaging-xcm-the-backbone-of-communication" + "title": "Core Pallet Components", + "anchor": "core-pallet-components" }, { - "depth": 3, - "title": "Bridges: Connecting External Networks", - "anchor": "bridges-connecting-external-networks" + "depth": 2, + "title": "Create the Pallet Project", + "anchor": "create-the-pallet-project" }, { "depth": 2, - "title": "The Polkadot Advantage", - "anchor": "the-polkadot-advantage" + "title": "Configure Dependencies", + "anchor": "configure-dependencies" }, { - "depth": 2, - "title": "Looking Ahead", - "anchor": "looking-ahead" - } - ], - "stats": { - "chars": 4635, - "words": 584, - "headings": 7, - "estimated_token_count_total": 772 - }, - "hash": "sha256:11bb4f113bdda5852a3115e64d5ba47f8eccd4e3619a05ad960ab3a541f31346", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-networks", - "title": "Networks", - "slug": "reference-parachains-networks", - "categories": [ - "Basics", - "Polkadot Protocol", - "Networks" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md", - "html_url": "https://docs.polkadot.com/reference/parachains/networks/", - "preview": "The Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's va", - "outline": [ + "depth": 2, + "title": "Initialize the Pallet Structure", + "anchor": "initialize-the-pallet-structure" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Configure the Pallet", + "anchor": "configure-the-pallet" }, { "depth": 2, - "title": "Network Overview", - "anchor": "network-overview" + "title": "Define Events", + "anchor": "define-events" }, { "depth": 2, - "title": "Polkadot Development Networks", - "anchor": "polkadot-development-networks" + "title": "Define Errors", + "anchor": "define-errors" }, { "depth": 2, - "title": "Kusama Network", - "anchor": "kusama-network" + "title": "Add Storage Items", + "anchor": "add-storage-items" }, { "depth": 2, - "title": "Test Networks", - "anchor": "test-networks" + "title": "Configure Genesis State", + "anchor": "configure-genesis-state" }, { - "depth": 3, - "title": "Westend", - "anchor": "westend" + "depth": 2, + "title": "Implement Dispatchable Functions", + "anchor": "implement-dispatchable-functions" }, { "depth": 3, - "title": "Paseo", - "anchor": "paseo" + "title": "Dispatchable Function Details", + "anchor": "dispatchable-function-details" }, { "depth": 2, - "title": "Local Test Networks", - "anchor": "local-test-networks" + "title": "Verify Pallet Compilation", + "anchor": "verify-pallet-compilation" }, { - "depth": 3, - "title": "Zombienet", - "anchor": "zombienet" + "depth": 2, + "title": "Add the Pallet to Your Runtime", + "anchor": "add-the-pallet-to-your-runtime" }, { "depth": 3, - "title": "Chopsticks", - "anchor": "chopsticks" - } - ], - "stats": { - "chars": 7834, - "words": 1111, - "headings": 10, - "estimated_token_count_total": 1473 - }, - "hash": "sha256:e49e063a2cc0fb5a48c6cdc3de266bb6e025a006940fea8e90cc4d5f9884900f", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains-node-and-runtime", - "title": "Node and Runtime", - "slug": "reference-parachains-node-and-runtime", - "categories": [ - "Basics", - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md", - "html_url": "https://docs.polkadot.com/reference/parachains/node-and-runtime/", - "preview": "Every blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network.", - "outline": [ + "title": "Add Runtime Dependency", + "anchor": "add-runtime-dependency" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Implement the Config Trait", + "anchor": "implement-the-config-trait" }, { - "depth": 2, - "title": "Architectural Principles", - "anchor": "architectural-principles" + "depth": 3, + "title": "Add to Runtime Construct", + "anchor": "add-to-runtime-construct" }, { "depth": 3, - "title": "Advantages of this Architecture", - "anchor": "advantages-of-this-architecture" + "title": "Configure Genesis for Your Runtime", + "anchor": "configure-genesis-for-your-runtime" }, { - "depth": 2, - "title": "Node (Client)", - "anchor": "node-client" + "depth": 3, + "title": "Verify Runtime Compilation", + "anchor": "verify-runtime-compilation" }, { "depth": 2, - "title": "Runtime", - "anchor": "runtime" + "title": "Run Your Chain Locally", + "anchor": "run-your-chain-locally" }, { "depth": 3, - "title": "Characteristics", - "anchor": "characteristics" + "title": "Generate a Chain Specification", + "anchor": "generate-a-chain-specification" }, { "depth": 3, - "title": "Key Functions", - "anchor": "key-functions" + "title": "Start the Parachain Node", + "anchor": "start-the-parachain-node" }, { "depth": 2, - "title": "Communication Between Node and Runtime", - "anchor": "communication-between-node-and-runtime" + "title": "Interact with Your Pallet", + "anchor": "interact-with-your-pallet" }, { - "depth": 3, - "title": "Runtime APIs", - "anchor": "runtime-apis" + "depth": 2, + "title": "Key Takeaways", + "anchor": "key-takeaways" }, { - "depth": 3, - "title": "Host Functions", - "anchor": "host-functions" + "depth": 2, + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 4937, - "words": 628, - "headings": 10, - "estimated_token_count_total": 914 + "chars": 26958, + "words": 3085, + "headings": 26, + "estimated_token_count_total": 6194 }, - "hash": "sha256:8122e21c149d0863cfe3b37fc5606bcdb91668e9d265f0f05451a61ff70e4e93", + "hash": "sha256:dad68ea59fd05fd60dc8890c4cf5615243c7ea879830b0dcf3a5e5e53c3ccec7", "token_estimator": "heuristic-v1" }, { - "id": "reference-parachains-randomness", - "title": "Randomness", - "slug": "reference-parachains-randomness", + "id": "parachains-customize-runtime-pallet-development-mock-runtime", + "title": "Mock Your Runtime", + "slug": "parachains-customize-runtime-pallet-development-mock-runtime", "categories": [ - "Basics", - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md", - "html_url": "https://docs.polkadot.com/reference/parachains/randomness/", - "preview": "Randomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as \"random\" numbers on a computer are actually pseudo-random. These numbers rely on an initial \"seed,\" which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\\_blank}, [heart rates](https://m", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-mock-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/mock-runtime/", + "preview": "Testing is a critical part of pallet development. Before integrating your pallet into a full runtime, you need a way to test its functionality in isolation. A mock runtime provides a minimal, simulated blockchain environment where you can verify your pallet's logic without the overhead of running a full node.", "outline": [ { "depth": 2, @@ -5051,75 +1691,58 @@ }, { "depth": 2, - "title": "VRF", - "anchor": "vrf" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "How VRF Works", - "anchor": "how-vrf-works" + "depth": 2, + "title": "Understand Mock Runtimes", + "anchor": "understand-mock-runtimes" }, { "depth": 2, - "title": "RANDAO", - "anchor": "randao" + "title": "Create the Mock Runtime Module", + "anchor": "create-the-mock-runtime-module" }, { "depth": 2, - "title": "VDFs", - "anchor": "vdfs" + "title": "Set Up Basic Mock", + "anchor": "set-up-basic-mock" }, { "depth": 2, - "title": "Additional Resources", - "anchor": "additional-resources" - } - ], - "stats": { - "chars": 6503, - "words": 1005, - "headings": 6, - "estimated_token_count_total": 1388 - }, - "hash": "sha256:c7d8a5a4263fd21af458ab0bd102377104affdf2431b4fe74eeff4ebe62a4a81", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-parachains", - "title": "Parachains Overview", - "slug": "reference-parachains", - "categories": [ - "Basics", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md", - "html_url": "https://docs.polkadot.com/reference/parachains/", - "preview": "A parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network.", - "outline": [ + "title": "Implement Essential Configuration", + "anchor": "implement-essential-configuration" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Implement Your Pallet's Configuration", + "anchor": "implement-your-pallets-configuration" }, { "depth": 2, - "title": "Polkadot SDK: Parachain Architecture", - "anchor": "polkadot-sdk-parachain-architecture" + "title": "Configure Genesis Storage", + "anchor": "configure-genesis-storage" }, { "depth": 3, - "title": "Substrate: The Foundation", - "anchor": "substrate-the-foundation" + "title": "Basic Test Environment", + "anchor": "basic-test-environment" }, { "depth": 3, - "title": "FRAME: Building Blocks for Your Runtime", - "anchor": "frame-building-blocks-for-your-runtime" + "title": "Custom Genesis Configurations", + "anchor": "custom-genesis-configurations" }, { - "depth": 3, - "title": "Cumulus: Parachain-Specific Functionality", - "anchor": "cumulus-parachain-specific-functionality" + "depth": 2, + "title": "Verify Mock Compilation", + "anchor": "verify-mock-compilation" + }, + { + "depth": 2, + "title": "Key Takeaways", + "anchor": "key-takeaways" }, { "depth": 2, @@ -5128,24 +1751,24 @@ } ], "stats": { - "chars": 8495, - "words": 1029, - "headings": 6, - "estimated_token_count_total": 1759 + "chars": 11766, + "words": 1369, + "headings": 13, + "estimated_token_count_total": 2514 }, - "hash": "sha256:ecb0d9459e08920db7d2d59dc7c01aba7a91ce8c9e39256bd0c3efa473dbaa17", + "hash": "sha256:dd784a5d2daebb9a885fe09f6a967e6c84958d96ddb38d8366eabe9d860fa539", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-assets-and-smart-contracts", - "title": "Asset Hub", - "slug": "reference-polkadot-hub-assets-and-smart-contracts", + "id": "parachains-customize-runtime-pallet-development-pallet-testing", + "title": "Unit Test Pallets", + "slug": "parachains-customize-runtime-pallet-development-pallet-testing", "categories": [ - "Polkadot Protocol" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/assets-and-smart-contracts/", - "preview": "The Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integra", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-pallet-testing.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/pallet-development/pallet-testing/", + "preview": "Unit testing in the Polkadot SDK helps ensure that the functions provided by a pallet behave as expected. It also confirms that data and events associated with a pallet are processed correctly during interactions. The Polkadot SDK offers a set of APIs to create a test environment to simulate runtime and mock transaction execution for extrinsics and queries.", "outline": [ { "depth": 2, @@ -5154,98 +1777,28 @@ }, { "depth": 2, - "title": "Assets Basics", - "anchor": "assets-basics" - }, - { - "depth": 2, - "title": "Assets Pallet", - "anchor": "assets-pallet" - }, - { - "depth": 3, - "title": "Key Features", - "anchor": "key-features" - }, - { - "depth": 3, - "title": "Main Functions", - "anchor": "main-functions" - }, - { - "depth": 3, - "title": "Querying Functions", - "anchor": "querying-functions" - }, - { - "depth": 3, - "title": "Permission Models and Roles", - "anchor": "permission-models-and-roles" - }, - { - "depth": 3, - "title": "Asset Freezing", - "anchor": "asset-freezing" - }, - { - "depth": 3, - "title": "Non-Custodial Transfers (Approval API)", - "anchor": "non-custodial-transfers-approval-api" - }, - { - "depth": 2, - "title": "Foreign Assets", - "anchor": "foreign-assets" - }, - { - "depth": 3, - "title": "Handling Foreign Assets", - "anchor": "handling-foreign-assets" - }, - { - "depth": 2, - "title": "Integration", - "anchor": "integration" - }, - { - "depth": 3, - "title": "API Sidecar", - "anchor": "api-sidecar" - }, - { - "depth": 3, - "title": "TxWrapper", - "anchor": "txwrapper" - }, - { - "depth": 3, - "title": "Parachain Node", - "anchor": "parachain-node" - }, - { - "depth": 2, - "title": "XCM Transfer Monitoring", - "anchor": "xcm-transfer-monitoring" + "title": "Writing Unit Tests", + "anchor": "writing-unit-tests" }, { "depth": 3, - "title": "Monitor XCM Deposits", - "anchor": "monitor-xcm-deposits" + "title": "Test Initialization", + "anchor": "test-initialization" }, { "depth": 3, - "title": "Track XCM Information Back to the Source", - "anchor": "track-xcm-information-back-to-the-source" + "title": "Function Call Testing", + "anchor": "function-call-testing" }, { "depth": 3, - "title": "Practical Monitoring Examples", - "anchor": "practical-monitoring-examples" + "title": "Storage Testing", + "anchor": "storage-testing" }, { "depth": 3, - "title": "Monitor for Failed XCM Transfers", - "anchor": "monitor-for-failed-xcm-transfers" + "title": "Event Testing", + "anchor": "event-testing" }, { "depth": 2, @@ -5254,24 +1807,25 @@ } ], "stats": { - "chars": 18211, - "words": 2649, - "headings": 21, - "estimated_token_count_total": 3678 + "chars": 6895, + "words": 912, + "headings": 7, + "estimated_token_count_total": 1563 }, - "hash": "sha256:3d10c04cffc5f737ff75b079d661c2c1904629d23ae1e415e64fd6ae4e98759e", + "hash": "sha256:041ccd82f0c1ddfb93be05feb6cf9d7d4a7e37af6caa8fa8fdab5d5538017122", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-bridging", - "title": "Bridge Hub", - "slug": "reference-polkadot-hub-bridging", + "id": "parachains-customize-runtime", + "title": "Overview of FRAME", + "slug": "parachains-customize-runtime", "categories": [ - "Polkadot Protocol" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-bridging.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/bridging/", - "preview": "The Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interope", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md", + "html_url": "https://docs.polkadot.com/parachains/customize-runtime/", + "preview": "A blockchain runtime is more than just a fixed set of rules—it's a dynamic foundation that you can shape to match your specific needs. With Polkadot SDK's [FRAME (Framework for Runtime Aggregation of Modularized Entities)](/reference/glossary/#frame-framework-for-runtime-aggregation-of-modularized-entities){target=\\_blank}, customizing your runtime is straightforward and modular. Instead of building everything from scratch, you combine pre-built pallets with your own custom logic to create a run", "outline": [ { "depth": 2, @@ -5280,392 +1834,364 @@ }, { "depth": 2, - "title": "Trustless Bridging", - "anchor": "trustless-bridging" + "title": "Understanding Your Runtime", + "anchor": "understanding-your-runtime" + }, + { + "depth": 2, + "title": "Runtime Architecture", + "anchor": "runtime-architecture" }, { "depth": 2, - "title": "Bridging Components", - "anchor": "bridging-components" + "title": "Building Blocks: Pallets", + "anchor": "building-blocks-pallets" }, { "depth": 3, - "title": "Ethereum-Specific Support", - "anchor": "ethereum-specific-support" + "title": "Pre-Built Pallets vs. Custom Pallets", + "anchor": "pre-built-pallets-vs-custom-pallets" }, { - "depth": 2, - "title": "Deployed Bridges", - "anchor": "deployed-bridges" + "depth": 3, + "title": "Pallet Structure", + "anchor": "pallet-structure" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 5467, - "words": 776, - "headings": 6, - "estimated_token_count_total": 1220 - }, - "hash": "sha256:86734ba8bcdea7913f488edf666a6104bed0a18649d57abde82c149c41c2b871", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-collectives-and-daos", - "title": "Collectives Chain", - "slug": "reference-polkadot-hub-collectives-and-daos", - "categories": [ - "Polkadot Protocol" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-collectives-and-daos.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/collectives-and-daos/", - "preview": "Established through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem.", - "outline": [ + "title": "How Runtime Customization Works", + "anchor": "how-runtime-customization-works" + }, { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Starting Templates", + "anchor": "starting-templates" }, { "depth": 2, - "title": "Key Collectives", - "anchor": "key-collectives" + "title": "Key Customization Scenarios", + "anchor": "key-customization-scenarios" } ], "stats": { - "chars": 2288, - "words": 293, - "headings": 2, - "estimated_token_count_total": 424 + "chars": 8237, + "words": 1101, + "headings": 9, + "estimated_token_count_total": 1828 }, - "hash": "sha256:59ec351fbb8d3a392e90f4f5bf6b62f58b21d6d7a900c5e367e5d2e09ecb3aca", + "hash": "sha256:28501589d5290f932b55cd3319f6a3fd78d7297ba42810da5ad2784a297224fd", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-consensus-and-security-agile-coretime", - "title": "Agile Coretime", - "slug": "reference-polkadot-hub-consensus-and-security-agile-coretime", + "id": "parachains-get-started", + "title": "Get Started with Parachain Development", + "slug": "parachains-get-started", "categories": [ - "Polkadot Protocol" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/agile-coretime/", - "preview": "Agile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md", + "html_url": "https://docs.polkadot.com/parachains/get-started/", + "preview": "The following sections provide practical recipes for building parachains on Polkadot—each focused on specific development scenarios with step-by-step, hands-on examples.", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Quick Start Guides", + "anchor": "quick-start-guides" }, { "depth": 2, - "title": "Bulk Coretime", - "anchor": "bulk-coretime" + "title": "Launch a Simple Parachain", + "anchor": "launch-a-simple-parachain" }, { - "depth": 3, - "title": "Coretime Interlacing", - "anchor": "coretime-interlacing" + "depth": 2, + "title": "Customize Your Runtime", + "anchor": "customize-your-runtime" }, { "depth": 3, - "title": "Coretime Splitting", - "anchor": "coretime-splitting" + "title": "Pallet Development", + "anchor": "pallet-development" + }, + { + "depth": 2, + "title": "Testing", + "anchor": "testing" + }, + { + "depth": 2, + "title": "Runtime Upgrades and Maintenance", + "anchor": "runtime-upgrades-and-maintenance" + }, + { + "depth": 2, + "title": "Interoperability", + "anchor": "interoperability" + }, + { + "depth": 2, + "title": "Integrations", + "anchor": "integrations" }, { "depth": 2, - "title": "On-Demand Coretime", - "anchor": "on-demand-coretime" + "title": "Additional Resources", + "anchor": "additional-resources" } ], "stats": { - "chars": 3028, - "words": 452, - "headings": 5, - "estimated_token_count_total": 619 + "chars": 7941, + "words": 631, + "headings": 9, + "estimated_token_count_total": 2292 }, - "hash": "sha256:00be43ac8d666bbe15c5c2fa5a5085697d0bb5a6f341ebbb943a209f0be355df", + "hash": "sha256:759ed27cf3d473445e33141089b652082c42a2c59eb822d6b506146fd9555e13", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-consensus-and-security-pos-consensus", - "title": "Proof of Stake Consensus", - "slug": "reference-polkadot-hub-consensus-and-security-pos-consensus", + "id": "parachains-install-polkadot-sdk", + "title": "Install Polkadot SDK", + "slug": "parachains-install-polkadot-sdk", "categories": [ - "Polkadot Protocol" + "Basics", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/pos-consensus/", - "preview": "Polkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank} model and a com", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md", + "html_url": "https://docs.polkadot.com/parachains/install-polkadot-sdk/", + "preview": "This guide provides step-by-step instructions for installing the Polkadot SDK on macOS, Linux, and Windows. The installation process consists of two main parts:", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Nominated Proof of Stake", - "anchor": "nominated-proof-of-stake" + "title": "Install Dependencies: macOS", + "anchor": "install-dependencies-macos" }, { - "depth": 2, - "title": "Hybrid Consensus", - "anchor": "hybrid-consensus" + "depth": 3, + "title": "Before You Begin {: #before-you-begin-mac-os }", + "anchor": "before-you-begin-before-you-begin-mac-os" }, { - "depth": 2, - "title": "Block Production - BABE", - "anchor": "block-production-babe" + "depth": 3, + "title": "Install Homebrew", + "anchor": "install-homebrew" }, { "depth": 3, - "title": "Validator Participation", - "anchor": "validator-participation" + "title": "Support for Apple Silicon", + "anchor": "support-for-apple-silicon" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources" + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-mac-os }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-mac-os" }, { "depth": 2, - "title": "Finality Gadget - GRANDPA", - "anchor": "finality-gadget-grandpa" + "title": "Install Dependencies: Linux", + "anchor": "install-dependencies-linux" }, { "depth": 3, - "title": "Probabilistic vs. Provable Finality", - "anchor": "probabilistic-vs-provable-finality" + "title": "Before You Begin {: #before-you-begin-linux }", + "anchor": "before-you-begin-before-you-begin-linux" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-2" + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-linux }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-linux" }, { "depth": 2, - "title": "Fork Choice", - "anchor": "fork-choice" + "title": "Install Dependencies: Windows (WSL)", + "anchor": "install-dependencies-windows-wsl" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-3" + "title": "Before You Begin {: #before-you-begin-windows-wls }", + "anchor": "before-you-begin-before-you-begin-windows-wls" }, { - "depth": 2, - "title": "Bridging - BEEFY", - "anchor": "bridging-beefy" + "depth": 3, + "title": "Set Up Windows Subsystem for Linux", + "anchor": "set-up-windows-subsystem-for-linux" }, { "depth": 3, - "title": "Additional Resources", - "anchor": "additional-resources-4" - } - ], - "stats": { - "chars": 12753, - "words": 1834, - "headings": 13, - "estimated_token_count_total": 2526 - }, - "hash": "sha256:231fc555eefe5f910fb36e0c03945147d0fb235272850797391751f4444b0a9c", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-polkadot-hub-consensus-and-security-relay-chain", - "title": "Overview of the Polkadot Relay Chain", - "slug": "reference-polkadot-hub-consensus-and-security-relay-chain", - "categories": [ - "Basics", - "Polkadot Protocol", - "Parachains" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/consensus-and-security/relay-chain/", - "preview": "Polkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank}, and cross-chain int", - "outline": [ - { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Install Required Packages and Rust {: #install-required-packages-and-rust-windows-wls }", + "anchor": "install-required-packages-and-rust-install-required-packages-and-rust-windows-wls" }, { "depth": 2, - "title": "Polkadot 1.0", - "anchor": "polkadot-10" - }, - { - "depth": 3, - "title": "High-Level Architecture", - "anchor": "high-level-architecture" + "title": "Build the Polkadot SDK", + "anchor": "build-the-polkadot-sdk" }, { "depth": 3, - "title": "Polkadot's Additional Functionalities", - "anchor": "polkadots-additional-functionalities" + "title": "Clone the Polkadot SDK", + "anchor": "clone-the-polkadot-sdk" }, { "depth": 3, - "title": "Polkadot's Resilience", - "anchor": "polkadots-resilience" + "title": "Compile the Polkadot SDK", + "anchor": "compile-the-polkadot-sdk" }, { "depth": 3, - "title": "Polkadot's Blockspace", - "anchor": "polkadots-blockspace" + "title": "Verify the Build", + "anchor": "verify-the-build" }, { "depth": 2, - "title": "DOT Token", - "anchor": "dot-token" - }, - { - "depth": 3, - "title": "Redenomination of DOT", - "anchor": "redenomination-of-dot" + "title": "Optional: Run the Kitchensink Node", + "anchor": "optional-run-the-kitchensink-node" }, { "depth": 3, - "title": "The Planck Unit", - "anchor": "the-planck-unit" + "title": "Run the Kitchensink Node in Development Mode", + "anchor": "run-the-kitchensink-node-in-development-mode" }, { "depth": 3, - "title": "Uses for DOT", - "anchor": "uses-for-dot" + "title": "Interact with the Kitchensink Node", + "anchor": "interact-with-the-kitchensink-node" }, { "depth": 2, - "title": "JAM and the Road Ahead", - "anchor": "jam-and-the-road-ahead" + "title": "Where to Go Next", + "anchor": "where-to-go-next" } ], "stats": { - "chars": 12458, - "words": 1774, - "headings": 11, - "estimated_token_count_total": 2580 + "chars": 16051, + "words": 2312, + "headings": 20, + "estimated_token_count_total": 3345 }, - "hash": "sha256:60f5ac9f67fb9f2188121219830538d334028b3b9e85d42bd1e7279043654e39", + "hash": "sha256:a52c05b623f3780f14be3a5f36b3d79a6c1965c2fbfd6864b512a9a70c47cd60", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub-people-and-identity", - "title": "People Chain", - "slug": "reference-polkadot-hub-people-and-identity", + "id": "parachains-integrations-indexers", + "title": "Indexers", + "slug": "parachains-integrations-indexers", "categories": [ - "Polkadot Protocol" + "Tooling", + "Dapps" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-people-and-identity.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/people-and-identity/", - "preview": "People chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/indexers/", + "preview": "Blockchain data is inherently sequential and distributed, with information stored chronologically across numerous blocks. While retrieving data from a single block through JSON-RPC API calls is straightforward, more complex queries that span multiple blocks present significant challenges:", "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" - }, - { - "depth": 2, - "title": "Identity Management System", - "anchor": "identity-management-system" - }, - { - "depth": 3, - "title": "Sub-Identities", - "anchor": "sub-identities" + "title": "The Challenge of Blockchain Data Access", + "anchor": "the-challenge-of-blockchain-data-access" }, { "depth": 2, - "title": "Verification Process", - "anchor": "verification-process" - }, - { - "depth": 3, - "title": "Judgment Requests", - "anchor": "judgment-requests" - }, - { - "depth": 3, - "title": "Judgment Classifications", - "anchor": "judgment-classifications" - }, - { - "depth": 3, - "title": "Registrars", - "anchor": "registrars" + "title": "What is a Blockchain Indexer?", + "anchor": "what-is-a-blockchain-indexer" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Indexer Implementations", + "anchor": "indexer-implementations" } ], "stats": { - "chars": 4750, - "words": 606, - "headings": 8, - "estimated_token_count_total": 876 + "chars": 2230, + "words": 302, + "headings": 3, + "estimated_token_count_total": 428 }, - "hash": "sha256:8239d1e8d8642cb7c10e9e5f971c99b999e9e4a87373b50bf4a691225c1e4702", + "hash": "sha256:cfcc76bb24779c9b613f2c046b6f99a0f2529c25fd82287d804f6b945b936227", "token_estimator": "heuristic-v1" }, { - "id": "reference-polkadot-hub", - "title": "reference-polkadot-hub", - "slug": "reference-polkadot-hub", + "id": "parachains-integrations-oracles", + "title": "Oracles", + "slug": "parachains-integrations-oracles", "categories": [ - "Uncategorized" + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/oracles/", + "preview": "Oracles enable blockchains to access external data sources. Since blockchains operate as isolated networks, they cannot natively interact with external systems - this limitation is known as the \"blockchain oracle problem.\" Oracles solves this by extracting data from external sources (like APIs, IoT devices, or other blockchains), validating it, and submitting it on-chain.", + "outline": [ + { + "depth": 2, + "title": "What is a Blockchain Oracle?", + "anchor": "what-is-a-blockchain-oracle" + }, + { + "depth": 2, + "title": "Oracle Implementations", + "anchor": "oracle-implementations" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub.md", - "html_url": "https://docs.polkadot.com/reference/polkadot-hub/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 1343, + "words": 181, + "headings": 2, + "estimated_token_count_total": 245 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:6d8e01281a5895fd2bc4438b24c170c72a496de0b838626a53e87685aea4aa25", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-chopsticks", - "title": "reference-tools-chopsticks", - "slug": "reference-tools-chopsticks", + "id": "parachains-integrations-wallets", + "title": "Wallets", + "slug": "parachains-integrations-wallets", "categories": [ - "Uncategorized" + "Tooling", + "Dapps" + ], + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md", + "html_url": "https://docs.polkadot.com/parachains/integrations/wallets/", + "preview": "A wallet serves as your gateway to interacting with blockchain networks. Rather than storing funds, wallets secure your private keys, controlling access to your blockchain assets. Your private key provides complete control over all permitted transactions on your blockchain account, making it essential to keep it secure.", + "outline": [ + { + "depth": 2, + "title": "What is a Blockchain Wallet?", + "anchor": "what-is-a-blockchain-wallet" + }, + { + "depth": 2, + "title": "Hot Wallets", + "anchor": "hot-wallets" + }, + { + "depth": 2, + "title": "Cold Wallets", + "anchor": "cold-wallets" + }, + { + "depth": 2, + "title": "Wallet Tools", + "anchor": "wallet-tools" + } ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md", - "html_url": "https://docs.polkadot.com/reference/tools/chopsticks/", - "preview": "TODO", - "outline": [], "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 + "chars": 3588, + "words": 489, + "headings": 4, + "estimated_token_count_total": 786 }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", + "hash": "sha256:1c65342056983806d639fb8393fdfbdf2ef644ffd41ed749947a16fb3839753d", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-dedot", - "title": "Dedot", - "slug": "reference-tools-dedot", + "id": "parachains-interoperability-channels-between-parachains", + "title": "Opening HRMP Channels Between Parachains", + "slug": "parachains-interoperability-channels-between-parachains", "categories": [ - "Tooling", - "Dapps" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md", - "html_url": "https://docs.polkadot.com/reference/tools/dedot/", - "preview": "[Dedot](https://github.com/dedotdev/dedot){target=\\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\\_blank}.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-between-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-between-parachains/", + "preview": "For establishing communication channels between parachains on the Polkadot network using the Horizontal Relay-routed Message Passing (HRMP) protocol, the following steps are required:", "outline": [ { "depth": 2, @@ -5673,66 +2199,70 @@ "anchor": "introduction" }, { - "depth": 3, - "title": "Key Features", - "anchor": "key-features" + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Procedure to Initiate an HRMP Channel", + "anchor": "procedure-to-initiate-an-hrmp-channel" }, { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "depth": 3, + "title": "Fund Sender Sovereign Account", + "anchor": "fund-sender-sovereign-account" }, { "depth": 3, - "title": "Initialize a Client Instance", - "anchor": "initialize-a-client-instance" + "title": "Create Channel Opening Extrinsic", + "anchor": "create-channel-opening-extrinsic" }, { "depth": 3, - "title": "Enable Type and API Suggestions", - "anchor": "enable-type-and-api-suggestions" + "title": "Craft and Submit the XCM Message from the Sender", + "anchor": "craft-and-submit-the-xcm-message-from-the-sender" + }, + { + "depth": 2, + "title": "Procedure to Accept an HRMP Channel", + "anchor": "procedure-to-accept-an-hrmp-channel" }, { "depth": 3, - "title": "Read On-Chain Data", - "anchor": "read-on-chain-data" + "title": "Fund Receiver Sovereign Account", + "anchor": "fund-receiver-sovereign-account" }, { "depth": 3, - "title": "Sign and Send Transactions", - "anchor": "sign-and-send-transactions" + "title": "Create Channel Accepting Extrinsic", + "anchor": "create-channel-accepting-extrinsic" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Craft and Submit the XCM Message from the Receiver", + "anchor": "craft-and-submit-the-xcm-message-from-the-receiver" } ], "stats": { - "chars": 8855, - "words": 1100, - "headings": 9, - "estimated_token_count_total": 2300 + "chars": 10934, + "words": 1549, + "headings": 10, + "estimated_token_count_total": 2285 }, - "hash": "sha256:ba24e31e2ad94fbf1d73f1878da92dd2e1476db00170780bbdf0e65ab18bc961", + "hash": "sha256:b8de1228b9976765accd18ff724038bed6f2449367f500bc3177ab2a053abe63", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-light-clients", - "title": "Light Clients", - "slug": "reference-tools-light-clients", + "id": "parachains-interoperability-channels-with-system-parachains", + "title": "Opening HRMP Channels with System Parachains", + "slug": "parachains-interoperability-channels-with-system-parachains", "categories": [ - "Parachains", - "Tooling" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md", - "html_url": "https://docs.polkadot.com/reference/tools/light-clients/", - "preview": "Light clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-channels-with-system-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/channels-with-system-parachains/", + "preview": "While establishing Horizontal Relay-routed Message Passing (HRMP) channels between regular parachains involves a two-step request and acceptance procedure, opening channels with system parachains follows a more straightforward approach.", "outline": [ { "depth": 2, @@ -5741,55 +2271,50 @@ }, { "depth": 2, - "title": "Light Clients Workflow", - "anchor": "light-clients-workflow" - }, - { - "depth": 2, - "title": "JSON-RPC and Light Client Comparison", - "anchor": "json-rpc-and-light-client-comparison" + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Using Light Clients", - "anchor": "using-light-clients" + "title": "Procedure to Establish an HRMP Channel", + "anchor": "procedure-to-establish-an-hrmp-channel" }, { "depth": 3, - "title": "PAPI Light Client Support", - "anchor": "papi-light-client-support" + "title": "Fund Parachain Sovereign Account", + "anchor": "fund-parachain-sovereign-account" }, { "depth": 3, - "title": "Substrate Connect - Browser Extension", - "anchor": "substrate-connect-browser-extension" + "title": "Create Establish Channel with System Extrinsic", + "anchor": "create-establish-channel-with-system-extrinsic" }, { - "depth": 2, - "title": "Resources", - "anchor": "resources" + "depth": 3, + "title": "Craft and Submit the XCM Message", + "anchor": "craft-and-submit-the-xcm-message" } ], "stats": { - "chars": 6490, - "words": 870, - "headings": 7, - "estimated_token_count_total": 1430 + "chars": 7203, + "words": 889, + "headings": 6, + "estimated_token_count_total": 1427 }, - "hash": "sha256:1284c42be692167e01bcc44e2e134ec20615402675fac26df246c00aa1588d80", + "hash": "sha256:b501d99c464fb049d46676827b6a325a195c90617becc4a7db305441c115350a", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-moonwall", - "title": "E2E Testing with Moonwall", - "slug": "reference-tools-moonwall", + "id": "parachains-interoperability-get-started", + "title": "Get Started with XCM", + "slug": "parachains-interoperability-get-started", "categories": [ - "Parachains", - "Tooling" + "Basics", + "Polkadot Protocol" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md", - "html_url": "https://docs.polkadot.com/reference/tools/moonwall/", - "preview": "Moonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md", + "html_url": "https://docs.polkadot.com/parachains/interoperability/get-started/", + "preview": "Polkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.", "outline": [ { "depth": 2, @@ -5798,65 +2323,54 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Messaging Format", + "anchor": "messaging-format" }, { "depth": 2, - "title": "Install Moonwall", - "anchor": "install-moonwall" - }, - { - "depth": 3, - "title": "Global Installation", - "anchor": "global-installation" - }, - { - "depth": 3, - "title": "Local Installation", - "anchor": "local-installation" + "title": "The Four Principles of XCM", + "anchor": "the-four-principles-of-xcm" }, { "depth": 2, - "title": "Initialize Moonwall", - "anchor": "initialize-moonwall" + "title": "The XCM Tech Stack", + "anchor": "the-xcm-tech-stack" }, { "depth": 2, - "title": "Writing Tests", - "anchor": "writing-tests" + "title": "Core Functionalities of XCM", + "anchor": "core-functionalities-of-xcm" }, { "depth": 2, - "title": "Running the Tests", - "anchor": "running-the-tests" + "title": "XCM Example", + "anchor": "xcm-example" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Overview", + "anchor": "overview" } ], "stats": { - "chars": 10240, - "words": 1295, - "headings": 9, - "estimated_token_count_total": 2453 + "chars": 7451, + "words": 975, + "headings": 7, + "estimated_token_count_total": 1501 }, - "hash": "sha256:2c77cfb38bb2e466a8f56dabbb706fcd2e90cf1634fc9beb7f0ee95a75735653", + "hash": "sha256:71ec75e18ea13b80d5955f96c10edd86ba679379d508a16c77e638f57a19361d", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-omninode", - "title": "Polkadot Omni Node", - "slug": "reference-tools-omninode", + "id": "parachains-launch-a-parachain-deploy-to-polkadot", + "title": "Deploy on Polkadot", + "slug": "parachains-launch-a-parachain-deploy-to-polkadot", "categories": [ - "Parachains", - "Tooling" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md", - "html_url": "https://docs.polkadot.com/reference/tools/omninode/", - "preview": "The [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\\_blank} file, allowing it to adapt dynamically to different parachains.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-deploy-to-polkadot.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/deploy-to-polkadot/", + "preview": "Previously, you learned how to [choose and set up a parachain template](/parachains/launch-a-parachain/choose-a-template/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to the Polkadot TestNet. Deploying to a TestNet is a crucial step for validating your parachain's functionality and preparing it for eventual MainNet deployment.", "outline": [ { "depth": 2, @@ -5865,65 +2379,64 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Get Started with an Account and Tokens", + "anchor": "get-started-with-an-account-and-tokens" }, { "depth": 2, - "title": "Install Polkadot Omni Node", - "anchor": "install-polkadot-omni-node" + "title": "Reserve a Parachain Identifier", + "anchor": "reserve-a-parachain-identifier" }, { "depth": 2, - "title": "Obtain Chain Specifications", - "anchor": "obtain-chain-specifications" + "title": "Generate Custom Keys for Your Collators", + "anchor": "generate-custom-keys-for-your-collators" }, { "depth": 2, - "title": "Run a Parachain Full Node", - "anchor": "run-a-parachain-full-node" + "title": "Generate the Chain Specification", + "anchor": "generate-the-chain-specification" }, { "depth": 2, - "title": "Interact with the Node", - "anchor": "interact-with-the-node" + "title": "Export Required Files", + "anchor": "export-required-files" }, { "depth": 2, - "title": "Parachain Compatibility", - "anchor": "parachain-compatibility" + "title": "Register a Parathread", + "anchor": "register-a-parathread" }, { - "depth": 3, - "title": "Required Runtime APIs", - "anchor": "required-runtime-apis" + "depth": 2, + "title": "Start the Collator Node", + "anchor": "start-the-collator-node" }, { - "depth": 3, - "title": "Required Pallets", - "anchor": "required-pallets" + "depth": 2, + "title": "Producing Blocks", + "anchor": "producing-blocks" } ], "stats": { - "chars": 8913, - "words": 1164, + "chars": 20252, + "words": 2357, "headings": 9, - "estimated_token_count_total": 2017 + "estimated_token_count_total": 4129 }, - "hash": "sha256:7db2d31ba37abad20b026c875f632b89739b45707e58809e2e8b32a09715c6f9", + "hash": "sha256:7309d3487c653951bf264013eb3402a72a1cbb5e0b6f89ae4e678f239cd63b80", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-papi", - "title": "Polkadot-API", - "slug": "reference-tools-papi", + "id": "parachains-launch-a-parachain-obtain-coretime", + "title": "Obtain Coretime", + "slug": "parachains-launch-a-parachain-obtain-coretime", "categories": [ - "Tooling", - "Dapps" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md", - "html_url": "https://docs.polkadot.com/reference/tools/papi/", - "preview": "[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-obtain-coretime.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/obtain-coretime/", + "preview": "After deploying a parachain to Paseo in the [Deploy on Polkadot](/parachains/launch-a-parachain/deploy-to-polkadot/){target=\\_blank} tutorial, the next critical step is obtaining coretime. Coretime is the mechanism through which validation resources are allocated from the relay chain to your parachain. Your parachain can only produce and finalize blocks on the relay chain by obtaining coretime.", "outline": [ { "depth": 2, @@ -5932,136 +2445,130 @@ }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Prerequisites", + "anchor": "prerequisites" }, { - "depth": 3, - "title": "API Instantiation", - "anchor": "api-instantiation" + "depth": 2, + "title": "Order On-Demand Coretime", + "anchor": "order-on-demand-coretime" }, { "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "title": "On-Demand Extrinsics", + "anchor": "on-demand-extrinsics" }, { "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" + "title": "Place an On-Demand Order", + "anchor": "place-an-on-demand-order" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" - } - ], - "stats": { - "chars": 8957, - "words": 1156, - "headings": 6, - "estimated_token_count_total": 1987 - }, - "hash": "sha256:2ca93b09d3bb9159bbf53816886a9b242bb3c13b996c51fd52962e049e2d5477", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-paraspell", - "title": "ParaSpell XCM SDK", - "slug": "reference-tools-paraspell", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md", - "html_url": "https://docs.polkadot.com/reference/tools/paraspell/", - "preview": "[ParaSpell](https://paraspell.github.io/docs/){target=\\_blank} is a comprehensive suite of open-source tools designed to simplify cross-chain interactions within the Polkadot ecosystem. At its core, ParaSpell is dedicated to enhancing the functionality of the [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} protocol by providing developers with a unified and streamlined experience for building interoperable decentralized applications (dApps).", - "outline": [ + "title": "Purchase Bulk Coretime", + "anchor": "purchase-bulk-coretime" + }, { - "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "depth": 3, + "title": "Connect Your Wallet to RegionX", + "anchor": "connect-your-wallet-to-regionx" }, { "depth": 3, - "title": "ParaSpell XCM SDK", - "anchor": "paraspell-xcm-sdk" + "title": "Obtain Coretime Chain Funds", + "anchor": "obtain-coretime-chain-funds" }, { - "depth": 2, - "title": "Install ParaSpell", - "anchor": "install-paraspell" + "depth": 3, + "title": "Purchase a Core", + "anchor": "purchase-a-core" + }, + { + "depth": 3, + "title": "Verify Your Purchase", + "anchor": "verify-your-purchase" + }, + { + "depth": 3, + "title": "Assign Your Parachain to the Core", + "anchor": "assign-your-parachain-to-the-core" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Next Steps", + "anchor": "next-steps" } ], "stats": { - "chars": 4043, - "words": 562, - "headings": 4, - "estimated_token_count_total": 888 + "chars": 9049, + "words": 1345, + "headings": 12, + "estimated_token_count_total": 2103 }, - "hash": "sha256:c8741954ea656680aa3322c825e3f6acbaac369baaa42232b06af9e5e482f74f", + "hash": "sha256:15154f211753665d9af70dc81d15ceb3f0954e3febf9282c68c0074881d620c6", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-polkadart", - "title": "Polkadart", - "slug": "reference-tools-polkadart", + "id": "parachains-launch-a-parachain-set-up-the-parachain-template", + "title": "Set Up the Polkadot SDK Parachain Template", + "slug": "parachains-launch-a-parachain-set-up-the-parachain-template", "categories": [ - "Tooling", - "Dapps" + "Basics", + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md", - "html_url": "https://docs.polkadot.com/reference/tools/polkadart/", - "preview": "Polkadart is the most comprehensive Dart/Flutter SDK for interacting with Polkadot, Substrate, and other compatible blockchain networks. Designed with a Dart-first approach and type-safe APIs, it provides everything developers need to build powerful decentralized applications.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md", + "html_url": "https://docs.polkadot.com/parachains/launch-a-parachain/set-up-the-parachain-template/", + "preview": "The [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank} includes several [templates](/parachains/customize-runtime/#starting-templates){target=\\_blank} designed to help you quickly start building your own blockchain. Each template offers a different level of configuration, from minimal setups to feature-rich environments, allowing you to choose the foundation that best fits your project's needs.", "outline": [ { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Introduction", + "anchor": "introduction" + }, + { + "depth": 2, + "title": "Prerequisites", + "anchor": "prerequisites" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Polkadot SDK Utility Tools", + "anchor": "polkadot-sdk-utility-tools" }, { - "depth": 3, - "title": "Type Generation", - "anchor": "type-generation" + "depth": 2, + "title": "Clone the Template", + "anchor": "clone-the-template" }, { - "depth": 3, - "title": "Run Generator", - "anchor": "run-generator" + "depth": 2, + "title": "Explore the Project Structure", + "anchor": "explore-the-project-structure" }, { - "depth": 3, - "title": "Use Generated Types", - "anchor": "use-generated-types" + "depth": 2, + "title": "Compile the Runtime", + "anchor": "compile-the-runtime" }, { - "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" + "depth": 2, + "title": "Verify the Build", + "anchor": "verify-the-build" }, { - "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "depth": 2, + "title": "Run the Node Locally", + "anchor": "run-the-node-locally" }, { - "depth": 3, - "title": "Subscribe to New Blocks", - "anchor": "subscribe-to-new-blocks" + "depth": 2, + "title": "Interact with the Node", + "anchor": "interact-with-the-node" }, { - "depth": 3, - "title": "Send a Transaction", - "anchor": "send-a-transaction" + "depth": 2, + "title": "Stop the Node", + "anchor": "stop-the-node" }, { "depth": 2, @@ -6070,92 +2577,70 @@ } ], "stats": { - "chars": 5178, - "words": 624, - "headings": 10, - "estimated_token_count_total": 1084 + "chars": 10588, + "words": 1510, + "headings": 11, + "estimated_token_count_total": 2375 }, - "hash": "sha256:7f533abe61586af8438e350c41b741d74a8edb839f9dc4139bc4619ba3748258", + "hash": "sha256:380063fe7c00ae8bde05fa76688b8ae4902e6566147f1cfe0e0260ad1aa05aa6", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-polkadot-js-api", - "title": "Polkadot.js API", - "slug": "reference-tools-polkadot-js-api", + "id": "parachains-runtime-maintenance-runtime-upgrades", + "title": "Runtime Upgrades", + "slug": "parachains-runtime-maintenance-runtime-upgrades", "categories": [ - "Tooling", - "Dapps" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md", - "html_url": "https://docs.polkadot.com/reference/tools/polkadot-js-api/", - "preview": "!!! warning \"Maintenance Mode Only\" The Polkadot.js API is now in maintenance mode and is no longer actively developed. New projects should use [Dedot](/develop/toolkit/api-libraries/dedot){target=\\_blank} (TypeScript-first API) or [Polkadot API](/develop/toolkit/api-libraries/papi){target=\\_blank} (modern, type-safe API) as actively maintained alternatives.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/runtime-upgrades/", + "preview": "One of the defining features of Polkadot SDK-based blockchains is the ability to perform forkless runtime upgrades. Unlike traditional blockchains, which require hard forks and node coordination for upgrades, Polkadot networks enable seamless updates without network disruption.", "outline": [ { "depth": 2, "title": "Introduction", "anchor": "introduction" }, - { - "depth": 3, - "title": "Dynamic API Generation", - "anchor": "dynamic-api-generation" - }, - { - "depth": 3, - "title": "Available API Categories", - "anchor": "available-api-categories" - }, - { - "depth": 2, - "title": "Installation", - "anchor": "installation" - }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" - }, - { - "depth": 3, - "title": "Creating an API Instance", - "anchor": "creating-an-api-instance" + "title": "How Runtime Upgrades Work", + "anchor": "how-runtime-upgrades-work" }, { "depth": 3, - "title": "Reading Chain Data", - "anchor": "reading-chain-data" + "title": "Runtime Versioning", + "anchor": "runtime-versioning" }, { "depth": 3, - "title": "Sending Transactions", - "anchor": "sending-transactions" + "title": "Accessing the Runtime Version", + "anchor": "accessing-the-runtime-version" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Storage Migrations", + "anchor": "storage-migrations" } ], "stats": { - "chars": 5042, - "words": 684, - "headings": 9, - "estimated_token_count_total": 1166 + "chars": 5837, + "words": 811, + "headings": 5, + "estimated_token_count_total": 1161 }, - "hash": "sha256:ed3986f30880fefca5975fcdc847c68b4aca65862c63e3002b25391b0521781d", + "hash": "sha256:ec31270001a6cd9d0a8ecb7974ad161d5c1ef4d3023d5a6af9fbc5a6ca46cbca", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-py-substrate-interface", - "title": "Python Substrate Interface", - "slug": "reference-tools-py-substrate-interface", + "id": "parachains-runtime-maintenance-storage-migrations", + "title": "Storage Migrations", + "slug": "parachains-runtime-maintenance-storage-migrations", "categories": [ - "Tooling", - "Dapps" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md", - "html_url": "https://docs.polkadot.com/reference/tools/py-substrate-interface/", - "preview": "The [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for:", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/storage-migrations/", + "preview": "Storage migrations are a crucial part of the runtime upgrade process. They allow you to update the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\\_blank} of your blockchain, adapting to changes in the runtime. Whenever you change the encoding or data types used to represent data in storage, you'll need to provide a storage migration to ensure the runtime can correctly interpret the existing stored values in the new runtime", "outline": [ { "depth": 2, @@ -6164,55 +2649,69 @@ }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Storage Migration Scenarios", + "anchor": "storage-migration-scenarios" }, { "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "title": "Implement Storage Migrations", + "anchor": "implement-storage-migrations" + }, + { + "depth": 3, + "title": "Core Migration Function", + "anchor": "core-migration-function" + }, + { + "depth": 3, + "title": "Migration Testing Hooks", + "anchor": "migration-testing-hooks" }, { "depth": 3, - "title": "Establishing Connection", - "anchor": "establishing-connection" + "title": "Migration Structure", + "anchor": "migration-structure" }, { "depth": 3, - "title": "Reading Chain State", - "anchor": "reading-chain-state" + "title": "Migration Organization", + "anchor": "migration-organization" }, { "depth": 3, - "title": "Submitting Transactions", - "anchor": "submitting-transactions" + "title": "Scheduling Migrations", + "anchor": "scheduling-migrations" }, { "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "title": "Single-Block Migrations", + "anchor": "single-block-migrations" + }, + { + "depth": 2, + "title": "Multi Block Migrations", + "anchor": "multi-block-migrations" } ], "stats": { - "chars": 4302, - "words": 541, - "headings": 7, - "estimated_token_count_total": 942 + "chars": 18500, + "words": 2363, + "headings": 10, + "estimated_token_count_total": 4014 }, - "hash": "sha256:8987fc35cd28602054ee018031f773e2e3837425107c51d0e2ac68a94b86e9c0", + "hash": "sha256:55dc252fdecf1590048ce8d009b822e90231442abe81e9593cf1635944a31336", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-sidecar", - "title": "Sidecar REST API", - "slug": "reference-tools-sidecar", + "id": "parachains-runtime-maintenance-unlock-parachains", + "title": "Unlock a Parachain", + "slug": "parachains-runtime-maintenance-unlock-parachains", "categories": [ - "Tooling", - "Dapps" + "Parachains" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md", - "html_url": "https://docs.polkadot.com/reference/tools/sidecar/", - "preview": "The [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-unlock-parachains.md", + "html_url": "https://docs.polkadot.com/parachains/runtime-maintenance/unlock-parachains/", + "preview": "Parachain locks are a critical security mechanism in the Polkadot ecosystem designed to maintain decentralization during the parachain lifecycle. These locks prevent potential centralization risks that could emerge during the early stages of parachain operation.", "outline": [ { "depth": 2, @@ -6221,50 +2720,50 @@ }, { "depth": 2, - "title": "Prerequisites", - "anchor": "prerequisites" + "title": "Check If the Parachain Is Locked", + "anchor": "check-if-the-parachain-is-locked" }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "How to Unlock a Parachain", + "anchor": "how-to-unlock-a-parachain" }, { - "depth": 2, - "title": "Usage", - "anchor": "usage" + "depth": 3, + "title": "Prepare the Unlock Call", + "anchor": "prepare-the-unlock-call" }, { "depth": 3, - "title": "Endpoints", - "anchor": "endpoints" + "title": "Fund the Sovereign Account", + "anchor": "fund-the-sovereign-account" }, { - "depth": 2, - "title": "Where to Go Next", - "anchor": "where-to-go-next" + "depth": 3, + "title": "Craft and Submit the XCM", + "anchor": "craft-and-submit-the-xcm" } ], "stats": { - "chars": 7309, - "words": 1033, + "chars": 9232, + "words": 1276, "headings": 6, - "estimated_token_count_total": 1945 + "estimated_token_count_total": 2028 }, - "hash": "sha256:0795462182cb97256bb5c2acb035855fe0d6557185de8ac99482725ecb4f94c1", + "hash": "sha256:e408d05199cc184fc6fe8bb212efb3c9aa6cb79258977e07566692176c912def", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-subxt", - "title": "Subxt Rust API", - "slug": "reference-tools-subxt", + "id": "parachains-testing-fork-a-parachain", + "title": "Fork a Parachain Using Chopsticks", + "slug": "parachains-testing-fork-a-parachain", "categories": [ - "Tooling", - "Dapps" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md", - "html_url": "https://docs.polkadot.com/reference/tools/subxt/", - "preview": "Subxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md", + "html_url": "https://docs.polkadot.com/parachains/testing/fork-a-parachain/", + "preview": "[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.", "outline": [ { "depth": 2, @@ -6278,38 +2777,38 @@ }, { "depth": 2, - "title": "Installation", - "anchor": "installation" + "title": "Install Chopsticks", + "anchor": "install-chopsticks" }, { - "depth": 2, - "title": "Get Started", - "anchor": "get-started" + "depth": 3, + "title": "Global Installation", + "anchor": "global-installation" }, { "depth": 3, - "title": "Download Chain Metadata", - "anchor": "download-chain-metadata" + "title": "Local Installation", + "anchor": "local-installation" }, { - "depth": 3, - "title": "Generate Type-Safe Interfaces", - "anchor": "generate-type-safe-interfaces" + "depth": 2, + "title": "Configure Chopsticks", + "anchor": "configure-chopsticks" }, { "depth": 3, - "title": "Initialize the Subxt Client", - "anchor": "initialize-the-subxt-client" + "title": "Configuration File", + "anchor": "configuration-file" }, { "depth": 3, - "title": "Read Chain Data", - "anchor": "read-chain-data" + "title": "CLI Flags", + "anchor": "cli-flags" }, { - "depth": 3, - "title": "Submit Transactions", - "anchor": "submit-transactions" + "depth": 2, + "title": "WebSocket Commands", + "anchor": "websocket-commands" }, { "depth": 2, @@ -6318,26 +2817,25 @@ } ], "stats": { - "chars": 9174, - "words": 1175, + "chars": 10916, + "words": 1333, "headings": 10, - "estimated_token_count_total": 2187 + "estimated_token_count_total": 2614 }, - "hash": "sha256:56269d9ea47f5b4e92cd7d5a1e65ab06d181a9c380f90bb3ef285529b12299f7", + "hash": "sha256:2079ef331bde286e281ca1b4bffc6c7c86844bad08c728131d1787dbe977d56e", "token_estimator": "heuristic-v1" }, { - "id": "reference-tools-xcm-tools", - "title": "XCM Tools", - "slug": "reference-tools-xcm-tools", + "id": "parachains-testing-run-a-parachain-network", + "title": "Run a Parachain Network", + "slug": "parachains-testing-run-a-parachain-network", "categories": [ - "Basics", - "Tooling", - "Dapps" + "Parachains", + "Tooling" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md", - "html_url": "https://docs.polkadot.com/reference/tools/xcm-tools/", - "preview": "As described in the [Interoperability](/develop/interoperability){target=\\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem.", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md", + "html_url": "https://docs.polkadot.com/parachains/testing/run-a-parachain-network/", + "preview": "Zombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.", "outline": [ { "depth": 2, @@ -6346,106 +2844,63 @@ }, { "depth": 2, - "title": "Popular XCM Tools", - "anchor": "popular-xcm-tools" + "title": "Install Zombienet", + "anchor": "install-zombienet" }, { - "depth": 3, - "title": "Moonsong Labs XCM Tools", - "anchor": "moonsong-labs-xcm-tools" + "depth": 2, + "title": "Providers", + "anchor": "providers" }, { "depth": 3, - "title": "ParaSpell", - "anchor": "paraspell" + "title": "Kubernetes", + "anchor": "kubernetes" }, { "depth": 3, - "title": "Astar XCM Tools", - "anchor": "astar-xcm-tools" + "title": "Podman", + "anchor": "podman" }, { "depth": 3, - "title": "Chopsticks", - "anchor": "chopsticks" + "title": "Local Provider", + "anchor": "local-provider" }, - { - "depth": 3, - "title": "Moonbeam XCM SDK", - "anchor": "moonbeam-xcm-sdk" - } - ], - "stats": { - "chars": 6146, - "words": 852, - "headings": 7, - "estimated_token_count_total": 1377 - }, - "hash": "sha256:674e4f60c82fc7544c7af8e09f1e0f677c9907cdff88b107f6c8489e97a43487", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference-tools-zombienet", - "title": "reference-tools-zombienet", - "slug": "reference-tools-zombienet", - "categories": [ - "Uncategorized" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md", - "html_url": "https://docs.polkadot.com/reference/tools/zombienet/", - "preview": "TODO", - "outline": [], - "stats": { - "chars": 5, - "words": 1, - "headings": 0, - "estimated_token_count_total": 0 - }, - "hash": "sha256:56ba36249ea8216ad513b13df3de6c0e490ba214897674d30331f1c7e7edbef3", - "token_estimator": "heuristic-v1" - }, - { - "id": "reference", - "title": "Technical Reference Overview", - "slug": "reference", - "categories": [ - "Basics", - "Polkadot Protocol", - "Reference" - ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md", - "html_url": "https://docs.polkadot.com/reference/", - "preview": "The Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need.", - "outline": [ { "depth": 2, - "title": "Introduction", - "anchor": "introduction" + "title": "Configure Zombienet", + "anchor": "configure-zombienet" }, { - "depth": 2, - "title": "Polkadot Hub", - "anchor": "polkadot-hub" + "depth": 3, + "title": "Configuration Files", + "anchor": "configuration-files" }, { - "depth": 2, - "title": "Parachains", - "anchor": "parachains" + "depth": 3, + "title": "CLI Usage", + "anchor": "cli-usage" }, { - "depth": 2, - "title": "On-Chain Governance", - "anchor": "on-chain-governance" + "depth": 3, + "title": "Settings", + "anchor": "settings" }, { - "depth": 2, - "title": "Glossary", - "anchor": "glossary" + "depth": 3, + "title": "Relay Chain Configuration", + "anchor": "relay-chain-configuration" }, { - "depth": 2, - "title": "Tools", - "anchor": "tools" + "depth": 3, + "title": "Parachain Configuration", + "anchor": "parachain-configuration" + }, + { + "depth": 3, + "title": "XCM Configuration", + "anchor": "xcm-configuration" }, { "depth": 2, @@ -6454,12 +2909,12 @@ } ], "stats": { - "chars": 7648, - "words": 937, - "headings": 7, - "estimated_token_count_total": 1682 + "chars": 41664, + "words": 4603, + "headings": 14, + "estimated_token_count_total": 9871 }, - "hash": "sha256:9f71f3b4018f7a9e127cff51fab7cfe1168adcde2553cd1fc5dc8c25fb97a30d", + "hash": "sha256:2007d6d01c9b915f613eba0aae53c80e61898bc61b5033c82a5c20324065b81f", "token_estimator": "heuristic-v1" }, { @@ -6557,7 +3012,7 @@ }, { "depth": 2, - "title": "Set Up the dApp Project", + "title": "Set Up the DApp Project", "anchor": "set-up-the-dapp-project" }, { @@ -6627,7 +3082,7 @@ "headings": 22, "estimated_token_count_total": 6967 }, - "hash": "sha256:b200f93a9179f0b2588ba722dd4c118536136faf3c39eabccf4abf5c346f78a8", + "hash": "sha256:59084ceaad3ff22227c58d4fe3af81ee968ca33fb5bffd256bdc92a1ffe7a0c4", "token_estimator": "heuristic-v1" }, { @@ -7762,7 +4217,7 @@ }, { "id": "smart-contracts-faucet", - "title": "Faucet", + "title": "Get Tokens from the Official Faucet", "slug": "smart-contracts-faucet", "categories": [ "Smart Contracts" @@ -8077,8 +4532,8 @@ "outline": [ { "depth": 2, - "title": "Overview", - "anchor": "overview" + "title": "Introduction", + "anchor": "introduction" }, { "depth": 2, @@ -8112,12 +4567,12 @@ } ], "stats": { - "chars": 5234, + "chars": 5238, "words": 751, "headings": 7, "estimated_token_count_total": 1046 }, - "hash": "sha256:dd29fab6e3c00d720b10effa4e50373a6fe9ab4b7bfd3aea892c7fa9c84318a2", + "hash": "sha256:e7ec7e9746d9314405d09c78db4da888054871eb48cd4881a0bade00e9b05edc", "token_estimator": "heuristic-v1" }, { @@ -8455,14 +4910,14 @@ "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-integrations-indexers", - "title": "smart-contracts-integrations-indexers", - "slug": "smart-contracts-integrations-indexers", + "id": "smart-contracts-integrations-.indexers", + "title": "smart-contracts-integrations-.indexers", + "slug": "smart-contracts-integrations-.indexers", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-indexers.md", - "html_url": "https://docs.polkadot.com/smart-contracts/integrations/indexers/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-.indexers.md", + "html_url": "https://docs.polkadot.com/smart-contracts/integrations/.indexers/", "preview": "TODO", "outline": [], "stats": { @@ -8475,14 +4930,14 @@ "token_estimator": "heuristic-v1" }, { - "id": "smart-contracts-integrations-oracles", - "title": "smart-contracts-integrations-oracles", - "slug": "smart-contracts-integrations-oracles", + "id": "smart-contracts-integrations-.oracles", + "title": "smart-contracts-integrations-.oracles", + "slug": "smart-contracts-integrations-.oracles", "categories": [ "Uncategorized" ], - "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-oracles.md", - "html_url": "https://docs.polkadot.com/smart-contracts/integrations/oracles/", + "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-.oracles.md", + "html_url": "https://docs.polkadot.com/smart-contracts/integrations/.oracles/", "preview": "TODO", "outline": [], "stats": { diff --git a/chain-interactions/.nav.yml b/.chain-interactions/.nav.yml similarity index 100% rename from chain-interactions/.nav.yml rename to .chain-interactions/.nav.yml diff --git a/chain-interactions/accounts/.nav.yml b/.chain-interactions/accounts/.nav.yml similarity index 100% rename from chain-interactions/accounts/.nav.yml rename to .chain-interactions/accounts/.nav.yml diff --git a/chain-interactions/accounts/create-account.md b/.chain-interactions/accounts/create-account.md similarity index 100% rename from chain-interactions/accounts/create-account.md rename to .chain-interactions/accounts/create-account.md diff --git a/chain-interactions/accounts/query-accounts.md b/.chain-interactions/accounts/query-accounts.md similarity index 100% rename from chain-interactions/accounts/query-accounts.md rename to .chain-interactions/accounts/query-accounts.md diff --git a/chain-interactions/index.md b/.chain-interactions/index.md similarity index 100% rename from chain-interactions/index.md rename to .chain-interactions/index.md diff --git a/chain-interactions/query-data/.nav.yml b/.chain-interactions/query-data/.nav.yml similarity index 100% rename from chain-interactions/query-data/.nav.yml rename to .chain-interactions/query-data/.nav.yml diff --git a/chain-interactions/query-data/query-rest.md b/.chain-interactions/query-data/query-rest.md similarity index 100% rename from chain-interactions/query-data/query-rest.md rename to .chain-interactions/query-data/query-rest.md diff --git a/chain-interactions/query-data/query-sdks.md b/.chain-interactions/query-data/query-sdks.md similarity index 100% rename from chain-interactions/query-data/query-sdks.md rename to .chain-interactions/query-data/query-sdks.md diff --git a/chain-interactions/query-data/runtime-api-calls.md b/.chain-interactions/query-data/runtime-api-calls.md similarity index 100% rename from chain-interactions/query-data/runtime-api-calls.md rename to .chain-interactions/query-data/runtime-api-calls.md diff --git a/chain-interactions/send-transactions/.nav.yml b/.chain-interactions/send-transactions/.nav.yml similarity index 100% rename from chain-interactions/send-transactions/.nav.yml rename to .chain-interactions/send-transactions/.nav.yml diff --git a/chain-interactions/send-transactions/calculate-transaction-fees.md b/.chain-interactions/send-transactions/calculate-transaction-fees.md similarity index 100% rename from chain-interactions/send-transactions/calculate-transaction-fees.md rename to .chain-interactions/send-transactions/calculate-transaction-fees.md diff --git a/chain-interactions/send-transactions/interoperability/.nav.yml b/.chain-interactions/send-transactions/interoperability/.nav.yml similarity index 100% rename from chain-interactions/send-transactions/interoperability/.nav.yml rename to .chain-interactions/send-transactions/interoperability/.nav.yml diff --git a/chain-interactions/send-transactions/interoperability/debug-and-preview-xcms.md b/.chain-interactions/send-transactions/interoperability/debug-and-preview-xcms.md similarity index 100% rename from chain-interactions/send-transactions/interoperability/debug-and-preview-xcms.md rename to .chain-interactions/send-transactions/interoperability/debug-and-preview-xcms.md diff --git a/chain-interactions/send-transactions/interoperability/estimate-xcm-fees.md b/.chain-interactions/send-transactions/interoperability/estimate-xcm-fees.md similarity index 100% rename from chain-interactions/send-transactions/interoperability/estimate-xcm-fees.md rename to .chain-interactions/send-transactions/interoperability/estimate-xcm-fees.md diff --git a/chain-interactions/send-transactions/interoperability/transfer-assets-out-of-polkadot.md b/.chain-interactions/send-transactions/interoperability/transfer-assets-out-of-polkadot.md similarity index 100% rename from chain-interactions/send-transactions/interoperability/transfer-assets-out-of-polkadot.md rename to .chain-interactions/send-transactions/interoperability/transfer-assets-out-of-polkadot.md diff --git a/chain-interactions/send-transactions/interoperability/transfer-assets-parachains.md b/.chain-interactions/send-transactions/interoperability/transfer-assets-parachains.md similarity index 96% rename from chain-interactions/send-transactions/interoperability/transfer-assets-parachains.md rename to .chain-interactions/send-transactions/interoperability/transfer-assets-parachains.md index e0113ee03..9d6f20176 100644 --- a/chain-interactions/send-transactions/interoperability/transfer-assets-parachains.md +++ b/.chain-interactions/send-transactions/interoperability/transfer-assets-parachains.md @@ -184,6 +184,6 @@ You have now successfully created and sent a cross-chain transfer using the Para ## Next Steps -- Read the Docs: Dive deeper into the features of the [ParaSpell XCM SDK](https://paraspell.github.io/docs/sdk/getting-started.html){target=\_blank} documentation. +- **Read the docs**: Dive deeper into the features of the [ParaSpell XCM SDK](https://paraspell.github.io/docs/sdk/getting-started.html){target=\_blank} documentation. -- Learn about XCM: Understand the underlying protocol by visiting the [Introduction to XCM page](/parachains/interoperability/get-started/) in the Polkadot Docs. \ No newline at end of file +- **Learn about XCM**: Understand the underlying protocol by visiting the [Get Started with XCM](/parachains/interoperability/get-started/) guide. \ No newline at end of file diff --git a/chain-interactions/send-transactions/pay-fees-with-different-tokens.md b/.chain-interactions/send-transactions/pay-fees-with-different-tokens.md similarity index 100% rename from chain-interactions/send-transactions/pay-fees-with-different-tokens.md rename to .chain-interactions/send-transactions/pay-fees-with-different-tokens.md diff --git a/chain-interactions/send-transactions/with-sdks.md b/.chain-interactions/send-transactions/with-sdks.md similarity index 100% rename from chain-interactions/send-transactions/with-sdks.md rename to .chain-interactions/send-transactions/with-sdks.md diff --git a/chain-interactions/token-operations/.nav.yml b/.chain-interactions/token-operations/.nav.yml similarity index 100% rename from chain-interactions/token-operations/.nav.yml rename to .chain-interactions/token-operations/.nav.yml diff --git a/chain-interactions/token-operations/convert-assets.md b/.chain-interactions/token-operations/convert-assets.md similarity index 100% rename from chain-interactions/token-operations/convert-assets.md rename to .chain-interactions/token-operations/convert-assets.md diff --git a/chain-interactions/token-operations/register-foreign-asset.md b/.chain-interactions/token-operations/register-foreign-asset.md similarity index 100% rename from chain-interactions/token-operations/register-foreign-asset.md rename to .chain-interactions/token-operations/register-foreign-asset.md diff --git a/chain-interactions/token-operations/register-local-asset.md b/.chain-interactions/token-operations/register-local-asset.md similarity index 100% rename from chain-interactions/token-operations/register-local-asset.md rename to .chain-interactions/token-operations/register-local-asset.md diff --git a/.nav.yml b/.nav.yml index ce7cd8449..17e5ccd0e 100644 --- a/.nav.yml +++ b/.nav.yml @@ -2,7 +2,7 @@ nav: - 'Home': index.md - 'Smart Contracts': smart-contracts - 'Parachains': parachains - - 'Chain Interactions': chain-interactions + # - 'Chain Interactions': chain-interactions # 'Get Support': get-support - 'Nodes and Validators': nodes-and-validators - - 'Technical Reference': reference + # - 'Technical Reference': reference diff --git a/reference/.nav.yml b/.reference/.nav.yml similarity index 100% rename from reference/.nav.yml rename to .reference/.nav.yml diff --git a/reference/glossary.md b/.reference/glossary.md similarity index 100% rename from reference/glossary.md rename to .reference/glossary.md diff --git a/reference/governance/index.md b/.reference/governance/index.md similarity index 100% rename from reference/governance/index.md rename to .reference/governance/index.md diff --git a/reference/governance/origins-tracks.md b/.reference/governance/origins-tracks.md similarity index 100% rename from reference/governance/origins-tracks.md rename to .reference/governance/origins-tracks.md diff --git a/reference/index.md b/.reference/index.md similarity index 100% rename from reference/index.md rename to .reference/index.md diff --git a/reference/parachains/.nav.yml b/.reference/parachains/.nav.yml similarity index 100% rename from reference/parachains/.nav.yml rename to .reference/parachains/.nav.yml diff --git a/reference/parachains/accounts.md b/.reference/parachains/accounts.md similarity index 100% rename from reference/parachains/accounts.md rename to .reference/parachains/accounts.md diff --git a/reference/parachains/blocks-transactions-fees/.nav.yml b/.reference/parachains/blocks-transactions-fees/.nav.yml similarity index 100% rename from reference/parachains/blocks-transactions-fees/.nav.yml rename to .reference/parachains/blocks-transactions-fees/.nav.yml diff --git a/reference/parachains/blocks-transactions-fees/blocks.md b/.reference/parachains/blocks-transactions-fees/blocks.md similarity index 100% rename from reference/parachains/blocks-transactions-fees/blocks.md rename to .reference/parachains/blocks-transactions-fees/blocks.md diff --git a/reference/parachains/blocks-transactions-fees/fees.md b/.reference/parachains/blocks-transactions-fees/fees.md similarity index 100% rename from reference/parachains/blocks-transactions-fees/fees.md rename to .reference/parachains/blocks-transactions-fees/fees.md diff --git a/reference/parachains/blocks-transactions-fees/transactions.md b/.reference/parachains/blocks-transactions-fees/transactions.md similarity index 100% rename from reference/parachains/blocks-transactions-fees/transactions.md rename to .reference/parachains/blocks-transactions-fees/transactions.md diff --git a/reference/parachains/chain-data.md b/.reference/parachains/chain-data.md similarity index 100% rename from reference/parachains/chain-data.md rename to .reference/parachains/chain-data.md diff --git a/reference/parachains/consensus/.nav.yml b/.reference/parachains/consensus/.nav.yml similarity index 100% rename from reference/parachains/consensus/.nav.yml rename to .reference/parachains/consensus/.nav.yml diff --git a/reference/parachains/consensus/async-backing.md b/.reference/parachains/consensus/async-backing.md similarity index 100% rename from reference/parachains/consensus/async-backing.md rename to .reference/parachains/consensus/async-backing.md diff --git a/reference/parachains/consensus/elastic-scaling.md b/.reference/parachains/consensus/elastic-scaling.md similarity index 100% rename from reference/parachains/consensus/elastic-scaling.md rename to .reference/parachains/consensus/elastic-scaling.md diff --git a/reference/parachains/consensus/index.md b/.reference/parachains/consensus/index.md similarity index 100% rename from reference/parachains/consensus/index.md rename to .reference/parachains/consensus/index.md diff --git a/reference/parachains/cryptography.md b/.reference/parachains/cryptography.md similarity index 100% rename from reference/parachains/cryptography.md rename to .reference/parachains/cryptography.md diff --git a/reference/parachains/data-encoding.md b/.reference/parachains/data-encoding.md similarity index 100% rename from reference/parachains/data-encoding.md rename to .reference/parachains/data-encoding.md diff --git a/reference/parachains/index.md b/.reference/parachains/index.md similarity index 100% rename from reference/parachains/index.md rename to .reference/parachains/index.md diff --git a/reference/parachains/interoperability.md b/.reference/parachains/interoperability.md similarity index 97% rename from reference/parachains/interoperability.md rename to .reference/parachains/interoperability.md index 3901c6928..3e071734b 100644 --- a/reference/parachains/interoperability.md +++ b/.reference/parachains/interoperability.md @@ -39,7 +39,7 @@ Through XCM, decentralized applications can: - Enable seamless user experiences where underlying blockchain differences are invisible. - XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem. -For further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\_blank} article. +For further information about XCM, check the [Get Started with XCM](/parachains/interoperability/get-started/){target=\_blank} article. ### Bridges: Connecting External Networks diff --git a/reference/parachains/networks.md b/.reference/parachains/networks.md similarity index 100% rename from reference/parachains/networks.md rename to .reference/parachains/networks.md diff --git a/reference/parachains/node-and-runtime.md b/.reference/parachains/node-and-runtime.md similarity index 100% rename from reference/parachains/node-and-runtime.md rename to .reference/parachains/node-and-runtime.md diff --git a/reference/parachains/randomness.md b/.reference/parachains/randomness.md similarity index 100% rename from reference/parachains/randomness.md rename to .reference/parachains/randomness.md diff --git a/reference/polkadot-hub/.nav.yml b/.reference/polkadot-hub/.nav.yml similarity index 100% rename from reference/polkadot-hub/.nav.yml rename to .reference/polkadot-hub/.nav.yml diff --git a/reference/polkadot-hub/assets-and-smart-contracts.md b/.reference/polkadot-hub/assets-and-smart-contracts.md similarity index 100% rename from reference/polkadot-hub/assets-and-smart-contracts.md rename to .reference/polkadot-hub/assets-and-smart-contracts.md diff --git a/reference/polkadot-hub/bridging.md b/.reference/polkadot-hub/bridging.md similarity index 100% rename from reference/polkadot-hub/bridging.md rename to .reference/polkadot-hub/bridging.md diff --git a/reference/polkadot-hub/collectives-and-daos.md b/.reference/polkadot-hub/collectives-and-daos.md similarity index 100% rename from reference/polkadot-hub/collectives-and-daos.md rename to .reference/polkadot-hub/collectives-and-daos.md diff --git a/reference/polkadot-hub/consensus-and-security/.nav.yml b/.reference/polkadot-hub/consensus-and-security/.nav.yml similarity index 100% rename from reference/polkadot-hub/consensus-and-security/.nav.yml rename to .reference/polkadot-hub/consensus-and-security/.nav.yml diff --git a/reference/polkadot-hub/consensus-and-security/agile-coretime.md b/.reference/polkadot-hub/consensus-and-security/agile-coretime.md similarity index 100% rename from reference/polkadot-hub/consensus-and-security/agile-coretime.md rename to .reference/polkadot-hub/consensus-and-security/agile-coretime.md diff --git a/reference/polkadot-hub/consensus-and-security/pos-consensus.md b/.reference/polkadot-hub/consensus-and-security/pos-consensus.md similarity index 100% rename from reference/polkadot-hub/consensus-and-security/pos-consensus.md rename to .reference/polkadot-hub/consensus-and-security/pos-consensus.md diff --git a/reference/polkadot-hub/consensus-and-security/relay-chain.md b/.reference/polkadot-hub/consensus-and-security/relay-chain.md similarity index 100% rename from reference/polkadot-hub/consensus-and-security/relay-chain.md rename to .reference/polkadot-hub/consensus-and-security/relay-chain.md diff --git a/reference/polkadot-hub/index.md b/.reference/polkadot-hub/index.md similarity index 100% rename from reference/polkadot-hub/index.md rename to .reference/polkadot-hub/index.md diff --git a/reference/polkadot-hub/people-and-identity.md b/.reference/polkadot-hub/people-and-identity.md similarity index 100% rename from reference/polkadot-hub/people-and-identity.md rename to .reference/polkadot-hub/people-and-identity.md diff --git a/reference/tools/.nav.yml b/.reference/tools/.nav.yml similarity index 100% rename from reference/tools/.nav.yml rename to .reference/tools/.nav.yml diff --git a/reference/tools/chopsticks.md b/.reference/tools/chopsticks.md similarity index 100% rename from reference/tools/chopsticks.md rename to .reference/tools/chopsticks.md diff --git a/reference/tools/dedot.md b/.reference/tools/dedot.md similarity index 100% rename from reference/tools/dedot.md rename to .reference/tools/dedot.md diff --git a/reference/tools/light-clients.md b/.reference/tools/light-clients.md similarity index 100% rename from reference/tools/light-clients.md rename to .reference/tools/light-clients.md diff --git a/reference/tools/moonwall.md b/.reference/tools/moonwall.md similarity index 100% rename from reference/tools/moonwall.md rename to .reference/tools/moonwall.md diff --git a/reference/tools/omninode.md b/.reference/tools/omninode.md similarity index 100% rename from reference/tools/omninode.md rename to .reference/tools/omninode.md diff --git a/reference/tools/papi.md b/.reference/tools/papi.md similarity index 100% rename from reference/tools/papi.md rename to .reference/tools/papi.md diff --git a/reference/tools/paraspell.md b/.reference/tools/paraspell.md similarity index 100% rename from reference/tools/paraspell.md rename to .reference/tools/paraspell.md diff --git a/reference/tools/polkadart.md b/.reference/tools/polkadart.md similarity index 100% rename from reference/tools/polkadart.md rename to .reference/tools/polkadart.md diff --git a/reference/tools/polkadot-js-api.md b/.reference/tools/polkadot-js-api.md similarity index 100% rename from reference/tools/polkadot-js-api.md rename to .reference/tools/polkadot-js-api.md diff --git a/reference/tools/py-substrate-interface.md b/.reference/tools/py-substrate-interface.md similarity index 100% rename from reference/tools/py-substrate-interface.md rename to .reference/tools/py-substrate-interface.md diff --git a/reference/tools/sidecar.md b/.reference/tools/sidecar.md similarity index 100% rename from reference/tools/sidecar.md rename to .reference/tools/sidecar.md diff --git a/reference/tools/subxt.md b/.reference/tools/subxt.md similarity index 100% rename from reference/tools/subxt.md rename to .reference/tools/subxt.md diff --git a/reference/tools/xcm-tools.md b/.reference/tools/xcm-tools.md similarity index 100% rename from reference/tools/xcm-tools.md rename to .reference/tools/xcm-tools.md diff --git a/reference/tools/zombienet.md b/.reference/tools/zombienet.md similarity index 100% rename from reference/tools/zombienet.md rename to .reference/tools/zombienet.md diff --git a/llms-full.jsonl b/llms-full.jsonl index d902f5751..b27c492bd 100644 --- a/llms-full.jsonl +++ b/llms-full.jsonl @@ -1,83 +1,3 @@ -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 44, "end_char": 709, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nIn this tutorial, you'll learn how to replay and dry-run XCMs using [Chopsticks](/parachains/testing/fork-a-parachain/){target=\\_blank}, a powerful tool for forking live Polkadot SDK-based chains in your local environment. These techniques are essential for:\n\n- Debugging cross-chain message failures.\n- Tracing execution across relay chains and parachains.\n- Analyzing weight usage, error types, and message flow.\n- Safely simulating XCMs without committing state changes.\n\nBy the end of this guide, you'll be able to set up a local fork, capture and replay real XCMs, and use dry-run features to diagnose and resolve complex cross-chain issues."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 709, "end_char": 1426, "estimated_token_count": 193, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, make sure you have:\n\n- [Chopsticks](/parachains/testing/fork-a-parachain/){target=\\_blank} installed (`npm i -g @acala-network/chopsticks`).\n- Access to the endpoint or genesis file of the parachain you want to fork.\n- The block number or hash where the XCM was sent.\n- (Optional) A Chopsticks config file for repeated setups.\n\nIf you haven't forked a chain before, see the [Fork a Chain with Chopsticks guide](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\\_blank} or [Fork a Network Locally using Chopsticks](https://wiki.polkadot.com/learn/learn-guides-test-opengov-proposals/#fork-a-network-locally-using-chopsticks){target=\\_blank} for step-by-step instructions."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 2, "depth": 2, "title": "Set Up Your Project", "anchor": "set-up-your-project", "start_char": 1426, "end_char": 2258, "estimated_token_count": 194, "token_estimator": "heuristic-v1", "text": "## Set Up Your Project\n\nLet's start by creating a dedicated workspace for your XCM replay and dry-run experiments.\n\n1. Create a new directory and navigate into it:\n\n ```bash\n mkdir -p replay-xcm-tests\n cd replay-xcm-tests\n ```\n\n2. Initialize a new Node project:\n\n ```bash\n npm init -y\n ```\n\n3. Install Chopsticks globally (recommended to avoid conflicts with local installs):\n\n ```bash\n npm install -g @acala-network/chopsticks@latest\n ```\n\n4. Install TypeScript and related tooling for local development:\n\n ```bash\n npm install --save-dev typescript @types/node tsx\n ```\n\n5. Install the required Polkadot packages:\n\n ```bash\n npm install polkadot-api @polkadot-labs/hdkd @polkadot-labs/hdkd-helpers\n ```\n\n6. Initialize the TypeScript config:\n\n ```bash\n npx tsc --init\n ```"} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 3, "depth": 2, "title": "Capture the XCM to Replay", "anchor": "capture-the-xcm-to-replay", "start_char": 2258, "end_char": 2834, "estimated_token_count": 151, "token_estimator": "heuristic-v1", "text": "## Capture the XCM to Replay\n\nTo replay a specific XCM, identify:\n\n- The source and destination chains involved.\n- The block number or height where the XCM was sent.\n- Optionally, the call payload (if you plan to simulate it manually via development commands).\n\nYou can use [Polkadot.js Apps](/tutorials/polkadot-sdk/testing/fork-live-chains/#use-polkadotjs-apps){target=\\_blank}, [papi console](https://dev.papi.how/){target=\\_blank}, or indexers such as [Subscan](https://polkadot.subscan.io/xcm_dashboard){target=\\_blank} to locate and inspect the original XCM execution."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 4, "depth": 2, "title": "Fork the Relevant Chains", "anchor": "fork-the-relevant-chains", "start_char": 2834, "end_char": 3022, "estimated_token_count": 48, "token_estimator": "heuristic-v1", "text": "## Fork the Relevant Chains\n\nUse Chopsticks to [fork the required chains](/tutorials/polkadot-sdk/testing/fork-live-chains/#xcm-testing){target=\\_blank} at the appropriate block heights."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 5, "depth": 3, "title": "Set the Block Numbers", "anchor": "set-the-block-numbers", "start_char": 3022, "end_char": 3307, "estimated_token_count": 61, "token_estimator": "heuristic-v1", "text": "### Set the Block Numbers\n\nCreate/edit a `.env` file with the block heights for each chain. These should be just before the XCM is sent to allow a full replay:\n\n```text title=\".env\"\nPOLKADOT_BLOCK_NUMBER=26481107\nPOLKADOT_ASSET_HUB_BLOCK_NUMBER=9079591\nACALA_BLOCK_NUMBER=8826385\n```"} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 6, "depth": 3, "title": "Enable Logging and Wasm Override", "anchor": "enable-logging-and-wasm-override", "start_char": 3307, "end_char": 7168, "estimated_token_count": 1021, "token_estimator": "heuristic-v1", "text": "### Enable Logging and Wasm Override\n\nFull execution logs only work if the runtime was compiled with logging enabled. Most live chains are built using the `production` profile, which disables logs. To enable logging, you'll need to override the Wasm with a locally built `release` or `debug` version. The `release` profile is faster to load in Chopsticks. \n\n1. Clone the `polkadot-fellows/runtimes` repository:\n\n ```bash\n git clone git@github.com:polkadot-fellows/runtimes.git\n ```\n\n2. Build the Polkadot Asset Hub runtime:\n\n ```bash\n cd runtimes\n # Build with the `debug` profile (default): \n # cargo build -p asset-hub-polkadot-runtime\n\n # Build with the `release` profile (faster to load in Chopsticks)\n cargo build --release -p asset-hub-polkadot-runtime\n ```\n\n3. Copy the compiled Wasm to your working directory:\n\n ```bash\n # Assuming you're still in the `runtimes` directory\n mkdir -p ../wasms # or your /wasms path\n\n # Copy the compiled Wasm to your working directory:\n\n # If built with the `debug` profile:\n # cp target/debug/wbuild/asset-hub-polkadot-runtime/asset_hub_polkadot_runtime.wasm ../wasms\n\n # If built with the `release` profile:\n cp target/release/wbuild/asset-hub-polkadot-runtime/asset_hub_polkadot_runtime.compact.compressed.wasm ../wasms\n ```\n\n4. Download and modify a config file:\n\n ```bash\n # Still in the `runtimes` directory\n cd .. # Return to your replay-xcm-tests root\n mkdir -p configs\n wget https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml -O configs/polkadot-asset-hub-override.yaml\n ```\n\n5. Edit `configs/polkadot-asset-hub-override.yaml` to include:\n\n {% raw %}\n ```yaml title=\"configs/polkadot-asset-hub-override.yaml\"\n ...\n runtime-log-level: 5\n # wasm-override: wasms/asset_hub_polkadot_runtime.wasm # Uncomment if using the `debug` build\n wasm-override: wasms/asset_hub_polkadot_runtime.compact.compressed.wasm # Use this if you built with `release`\n ...\n ```\n {% endraw %}\n\n6. Start the forked chains using your custom config:\n\n ```bash\n npx @acala-network/chopsticks xcm \\\n -r polkadot \\\n -p configs/polkadot-asset-hub-override.yaml \\\n -p acala\n ```\n\n This command starts the relay chain and parachains locally, with full runtime execution logs enabled. Once the chains are running, you should see output indicating that the following RPC endpoints are available:\n\n - Polkadot Asset Hub RPC on `http://localhost:8000`\n - Acala RPC on `http://localhost:8001`\n - Polkadot RPC on `http://localhost:8002`\n\n You'll also see runtime logs such as:\n\n
    \n npx @acala-network/chopsticks xcm \\ -r polkadot \\ -p configs/polkadot-asset-hub-override.yaml \\ -p acala\n [09:29:14.988] INFO: Polkadot Asset Hub RPC listening on http://[::]:8000 and ws://[::]:8000\n [09:29:14.988] INFO: Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/acala.yml\n [09:29:15.984] INFO: Acala RPC listening on http://[::]:8001 and ws://[::]:8001\n [09:29:15.990] INFO (xcm): Connected parachains [1000,2000]\n [09:29:15.990] INFO: Loading config file https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot.yml\n [09:29:16.927] INFO: Polkadot RPC listening on http://[::]:8002 and ws://[::]:8002\n [09:29:16.984] INFO (xcm): Connected relaychain 'Polkadot' with parachain 'Polkadot Asset Hub'\n [09:29:17.028] INFO (xcm): Connected relaychain 'Polkadot' with parachain 'Acala'\n
    "} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 7, "depth": 2, "title": "Identify and Extract the XCM", "anchor": "identify-and-extract-the-xcm", "start_char": 7168, "end_char": 8791, "estimated_token_count": 333, "token_estimator": "heuristic-v1", "text": "## Identify and Extract the XCM\n\nTo replay an XCM, you'll first need to identify the exact extrinsic that triggered it. In this example, we'll use block 9079592 on the Polkadot Asset Hub.\n\n1. Find and open the block on Subscan to inspect its extrinsics and events. In this case, the block is [9079592](https://assethub-polkadot.subscan.io/block/9079592){target=\\_blank}.\n\n2. Copy the black hash. Look for the block hash at the top of the page. For block 9079592, the hash is:\n\n ```bash title=\"Block Hash\"\n 0xeb5a5737d47367dc1c02b978232283cdb096eb7e51d2eb22366a106a011347f6\n ```\n\n3. Explore and view the block in [Polkadot.Js Apps](https://polkadot.js.org/apps){target=\\_blank} using this direct link: [Block Hash Explorer](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot-asset-hub-rpc.polkadot.io#/explorer/query/0xeb5a5737d47367dc1c02b978232283cdb096eb7e51d2eb22366a106a011347f6){target=\\_blank}.\n\n4. Locate and decode the XCM extrinsic. Once you've found the extrinsic (e.g., 9079592-2), extract and decode its call data. For example, the call data is:\n \n ```bash title=\"Call Data\"\n 0xad028400fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c820016a30461702adc48213e5c9ee4d15c5a481c578cb5cbc935f0bd11fe8aee489082a745ffbbe94282f91b67daa6cb44920d77c30849c1d25f5f6c3e59015a3e383440055040000011f0803010100411f0300010100fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c8200304000002043205011f0092e81d790000000000\n ```\n\n5. From the decoded view, copy the **hex-encoded call** (e.g. `0x1f08...0000`). You'll pass this into `api.txFromCallData(...)` to replay the XCM locally."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 8, "depth": 2, "title": "Replay the XCM", "anchor": "replay-the-xcm", "start_char": 8791, "end_char": 9045, "estimated_token_count": 50, "token_estimator": "heuristic-v1", "text": "## Replay the XCM\n\nOnce your project is set up, you're ready to replay the XCM locally.\n\nThis is useful for:\n\n- Diagnosing execution failures or weight limits.\n- Inspecting all emitted events.\n- Verifying behaviour before submitting a real transaction."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 9, "depth": 3, "title": "Add the Asset Hub Descriptor", "anchor": "add-the-asset-hub-descriptor", "start_char": 9045, "end_char": 9478, "estimated_token_count": 105, "token_estimator": "heuristic-v1", "text": "### Add the Asset Hub Descriptor\n\nThis will let you use type-safe APIs with PAPI:\n\n```bash\nnpx papi add assetHub -w ws://localhost:8000\n```\n\nThe script assumes the Polkadot Asset Hub is served on `ws://localhost:8000`. If you're using a different port or config, update the WebSocket endpoint in the script or descriptor. You can confirm the port by checking your terminal logs or by seeing [Launch Chopsticks](#launch-chopsticks)."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 10, "depth": 3, "title": "Create a Replay Script", "anchor": "create-a-replay-script", "start_char": 9478, "end_char": 12356, "estimated_token_count": 667, "token_estimator": "heuristic-v1", "text": "### Create a Replay Script\n\nCreate a file named `replay-xcm.ts` and copy the following code into it:\n\n```ts\nimport { Binary, createClient, Transaction } from 'polkadot-api';\nimport { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat';\nimport { getPolkadotSigner } from 'polkadot-api/signer';\nimport { getWsProvider } from 'polkadot-api/ws-provider/web';\nimport { assetHub } from '@polkadot-api/descriptors';\nimport { sr25519CreateDerive } from '@polkadot-labs/hdkd';\nimport {\n DEV_PHRASE,\n entropyToMiniSecret,\n mnemonicToEntropy,\n} from '@polkadot-labs/hdkd-helpers';\n\nconst toHuman = (_key: any, value: any) => {\n if (typeof value === 'bigint') {\n return Number(value);\n }\n\n if (value && typeof value === 'object' && typeof value.asHex === 'function') {\n return value.asHex();\n }\n\n return value;\n};\n\nfunction getSigner() {\n const entropy = mnemonicToEntropy(DEV_PHRASE);\n const miniSecret = entropyToMiniSecret(entropy);\n const derive = sr25519CreateDerive(miniSecret);\n const alice = derive('//Alice');\n\n return getPolkadotSigner(alice.publicKey, 'Sr25519', alice.sign);\n}\n\nasync function main() {\n const provider = withPolkadotSdkCompat(getWsProvider('ws://localhost:8000'));\n const client = createClient(provider);\n const api = client.getTypedApi(assetHub);\n const aliceSigner = getSigner();\n\n const callData = Binary.fromHex(\n '0x1f0803010100411f0300010100fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c8200304000002043205011f0092e81d790000000000',\n );\n const tx: Transaction =\n await api.txFromCallData(callData);\n console.log('👀 Executing XCM:', JSON.stringify(tx.decodedCall, toHuman, 2));\n\n await new Promise((resolve) => {\n const subscription = tx.signSubmitAndWatch(aliceSigner).subscribe((ev) => {\n if (\n ev.type === 'finalized' ||\n (ev.type === 'txBestBlocksState' && ev.found)\n ) {\n console.log(\n `📦 Included in block #${ev.block.number}: ${ev.block.hash}`,\n );\n\n if (!ev.ok) {\n const dispatchError = ev.dispatchError;\n if (dispatchError.type === 'Module') {\n const modErr: any = dispatchError.value;\n console.error(\n `❌ Dispatch error in module: ${modErr.type} → ${modErr.value?.type}`,\n );\n } else {\n console.error(\n '❌ Dispatch error:',\n JSON.stringify(dispatchError, toHuman, 2),\n );\n }\n }\n\n for (const event of ev.events) {\n console.log(\n '📣 Event:',\n event.type,\n JSON.stringify(event.value, toHuman, 2),\n );\n }\n\n console.log('✅ Process completed, exiting...');\n subscription.unsubscribe();\n resolve();\n }\n });\n });\n\n client.destroy();\n}\n\nmain().catch(console.error);\n\n```"} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 11, "depth": 3, "title": "Execute the Replay Script", "anchor": "execute-the-replay-script", "start_char": 12356, "end_char": 12545, "estimated_token_count": 48, "token_estimator": "heuristic-v1", "text": "### Execute the Replay Script\n\nEnsure Chopsticks is running and serving a chain that includes `pallet-xcm`, such as a Polkadot Asset Hub fork. Then run:\n\n```bash\nnpx tsx replay-xcm.ts\n```"} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 12, "depth": 3, "title": "Expected Output", "anchor": "expected-output", "start_char": 12545, "end_char": 14451, "estimated_token_count": 674, "token_estimator": "heuristic-v1", "text": "### Expected Output\n\nIf everything is working, you'll see logs like:\n\n
    \n npx tsx replay-xcm.ts\n
    \nexecuting xcm: {\n  \"type\": \"polkadotxcm\",\n  \"value\": {\n    \"type\": \"limited_reserve_transfer_assets\",\n    \"value\": {\n      \"dest\": { \"parents\": 0, \"interior\": { \"X1\": [{ \"Parachain\": 2006 }] } },\n      \"beneficiary\": { \"parents\": 0, \"interior\": { \"X1\": [{ \"AccountId32\": { \"network\": null, \"id\": \"0x...\" } }] } },\n      \"assets\": [{ \"id\": { \"Concrete\": { \"parents\": 0, \"interior\": \"Here\" } }, \"fun\": { \"Fungible\": 120000000000 } }],\n      \"fee_asset_item\": 0,\n      \"weight_limit\": { \"type\": \"Unlimited\" }\n    }\n  }\n}\n  
    \n 📦 Included in block #9079592: 0x227a11c64f6051ba2e090a13abd17e5f7581640a80f6c03fc2d43fac66ab7949\n 📣 Event: Balances { \"type\": \"Upgraded\", \"value\": { ... } }\n 📣 Event: Balances { \"type\": \"Withdraw\", \"value\": { ... } }\n 📣 Event: Assets { \"type\": \"Transferred\", \"value\": { ... } }\n 📣 Event: PolkadotXcm { \"type\": \"Attempted\", \"value\": { ... } }\n 📣 Event: Balances { \"type\": \"Burned\", \"value\": { ... } }\n 📣 Event: Balances { \"type\": \"Minted\", \"value\": { ... } }\n 📣 Event: PolkadotXcm { \"type\": \"FeesPaid\", \"value\": { ... } }\n 📣 Event: XcmpQueue { \"type\": \"XcmpMessageSent\", \"value\": { ... } }\n 📣 Event: PolkadotXcm { \"type\": \"Sent\", \"value\": { ... } }\n 📣 Event: Balances { \"type\": \"Deposit\", \"value\": { ... } }\n 📣 Event: TransactionPayment { \"type\": \"TransactionFeePaid\", \"value\": { ... } }\n 📣 Event: System { \"type\": \"ExtrinsicSuccess\", \"value\": { ... } }\n ✅ Process completed, exiting...\n
    "} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 13, "depth": 2, "title": "Dry Run the XCM", "anchor": "dry-run-the-xcm", "start_char": 14451, "end_char": 14639, "estimated_token_count": 38, "token_estimator": "heuristic-v1", "text": "## Dry Run the XCM\n\nTo simulate the XCM without actually sending it, you can use the `dry_run_call` method. This lets you check whether the XCM would succeed without modifying any state."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 14, "depth": 3, "title": "Create a Dry Run Script", "anchor": "create-a-dry-run-script", "start_char": 14639, "end_char": 16321, "estimated_token_count": 366, "token_estimator": "heuristic-v1", "text": "### Create a Dry Run Script\n\nAssuming you've the `tx` transaction from the previous step, you can create a new script, `dry-run-call.ts`, then paste in the following code:\n\n```ts\nimport { Binary, createClient, Enum } from 'polkadot-api';\nimport { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat';\nimport { getWsProvider } from 'polkadot-api/ws-provider/web';\nimport { assetHub } from '@polkadot-api/descriptors';\nimport { sr25519CreateDerive } from '@polkadot-labs/hdkd';\nimport {\n DEV_PHRASE,\n entropyToMiniSecret,\n mnemonicToEntropy,\n ss58Address,\n} from '@polkadot-labs/hdkd-helpers';\n\nconst XCM_VERSION = 5;\n\nasync function main() {\n const provider = withPolkadotSdkCompat(getWsProvider('ws://localhost:8000'));\n const client = createClient(provider);\n const api = client.getTypedApi(assetHub);\n\n const entropy = mnemonicToEntropy(DEV_PHRASE);\n const miniSecret = entropyToMiniSecret(entropy);\n const derive = sr25519CreateDerive(miniSecret);\n const alice = derive('//Alice');\n const aliceAddress = ss58Address(alice.publicKey);\n\n const callData = Binary.fromHex(\n '0x1f0803010100411f0300010100fc39fcf04a8071b7409823b7c82427ce67910c6ed80aa0e5093aff234624c8200304000002043205011f0092e81d790000000000',\n );\n const tx: any = await api.txFromCallData(callData);\n const origin = Enum('system', Enum('Signed', aliceAddress));\n const dryRunResult: any = await api.apis.DryRunApi.dry_run_call(\n origin,\n tx.decodedCall,\n XCM_VERSION,\n );\n console.dir(dryRunResult.value, { depth: null });\n\n client.destroy();\n}\n\nmain().catch(console.error);\n\n```\n\nEnsure your local Chopsticks fork is running and the ports match those used in the script."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 15, "depth": 3, "title": "Execute the Dry Run Script", "anchor": "execute-the-dry-run-script", "start_char": 16321, "end_char": 17894, "estimated_token_count": 496, "token_estimator": "heuristic-v1", "text": "### Execute the Dry Run Script\n\n```bash\nnpx tsx dry-run-call.ts\n```\n\nIf successful, the dry run confirms that the XCM would execute correctly:\n\n
    \n npx tsx dry-run-call.ts\n
    \nexecution_result: {\n  \"success\": true,\n  \"value\": {\n    \"post_info\": { \"actual_weight\": 123456, \"pays_fee\": \"Yes\" },\n    \"result\": \"Ok\"\n  }\n}\nemitted_events: [ { \"section\": \"Balances\", \"method\": \"Transfer\", \"data\": { \"from\": \"0x...\", \"to\": \"0x...\", \"amount\": 1000000000 } } ]\nlocal_xcm: { \"type\": \"SomeType\", \"value\": { ... } }\nforwarded_xcms: []\n  
    \n ✅ Dry run succeeded\n ✅ Process completed, exiting...\n
    \n\nIf it fails, you'll receive detailed error information:\n\n
    \n npx tsx dry-run-call.ts\n
    \nexecution_result: {\n  \"success\": false,\n  \"value\": {\n    \"post_info\": { \"actual_weight\": 123456, \"pays_fee\": \"Yes\" },\n    \"error\": {\n      \"type\": \"Module\",\n      \"value\": {\n        \"type\": \"PolkadotXcm\",\n        \"value\": { \"type\": \"LocalExecutionIncomplete\", \"value\": null }\n      }\n    }\n  }\n}\n  
    \n ❌ Dry run failed: LocalExecutionIncomplete\n ✅ Process completed, exiting...\n
    \n\nFor more information, see:\n\n- [Dry Run Call](/develop/interoperability/xcm-runtime-apis/#dry-run-call){target=\\_blank} to simulate a full extrinsic\n- [Dry Run XCM](/develop/interoperability/xcm-runtime-apis/#dry-run-xcm){target=\\_blank} to simulate a raw XCM"} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 16, "depth": 2, "title": "Review and Debug", "anchor": "review-and-debug", "start_char": 17894, "end_char": 18239, "estimated_token_count": 60, "token_estimator": "heuristic-v1", "text": "## Review and Debug\n\nReplaying XCMs with full logging provides fine-grained control and visibility into cross-chain message behaviour. Chopsticks makes this possible in a safe, local environment – empowering developers to:\n\n- Debug complex message flows.\n- Identify root causes of XCM failures.\n- Improve observability for future integrations."} -{"page_id": "chain-interactions-send-transactions-interoperability-debug-and-preview-xcms", "page_title": "Replay and Dry Run XCMs", "index": 17, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 18239, "end_char": 18942, "estimated_token_count": 181, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
    \n\n- External __Chopsticks Repository__\n\n ---\n\n View the official Chopsticks GitHub repository.\n\n [:octicons-arrow-right-24: Get Started](https://github.com/AcalaNetwork/chopsticks/)\n\n- Guide __Polkadot XCM Docs__\n\n ---\n\n Learn how to use XCM effectively.\n\n [:octicons-arrow-right-24: Get Started](/parachains/interoperability/get-started/)\n\n- Tutorial __XCM Runtime APIs__\n\n ---\n\n Learn how to use XCM Runtime APIs.\n\n [:octicons-arrow-right-24: Get Started](/develop/interoperability/xcm-runtime-apis/)\n\n
    "} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 22, "end_char": 450, "estimated_token_count": 76, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nWhen sending cross-chain messages, ensure that the transaction will be successful not only in the local chain but also in the destination chain and any intermediate chains.\n\nSending cross-chain messages requires estimating the fees for the operation. \n\nThis tutorial will demonstrate how to dry-run and estimate the fees for teleporting assets from the Paseo Asset Hub parachain to the Paseo Bridge Hub chain."} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 1, "depth": 2, "title": "Fee Mechanism", "anchor": "fee-mechanism", "start_char": 450, "end_char": 1437, "estimated_token_count": 222, "token_estimator": "heuristic-v1", "text": "## Fee Mechanism\n\nThere are three types of fees that can be charged when sending a cross-chain message:\n\n- **Local execution fees**: Fees charged in the local chain for executing the message.\n- **Delivery fees**: Fees charged for delivering the message to the destination chain.\n- **Remote execution fees**: Fees charged in the destination chain for executing the message.\n\nIf there are multiple intermediate chains, delivery fees and remote execution fees will be charged for each one.\n\nIn this example, you will estimate the fees for teleporting assets from the Paseo Asset Hub parachain to the Paseo Bridge Hub chain. The fee structure will be as follows:\n\n```mermaid\nflowchart LR\n AssetHub[Paseo Asset Hub] -->|Delivery Fees| BridgeHub[Paseo Bridge Hub]\n AssetHub -->|
    Local
    Execution
    Fees| AssetHub\n BridgeHub -->|
    Remote
    Execution
    Fees| BridgeHub\n```\n\nThe overall fees are `local_execution_fees` + `delivery_fees` + `remote_execution_fees`."} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 2, "depth": 2, "title": "Environment Setup", "anchor": "environment-setup", "start_char": 1437, "end_char": 3989, "estimated_token_count": 588, "token_estimator": "heuristic-v1", "text": "## Environment Setup\n\nFirst, you need to set up your environment:\n\n1. Create a new directory and initialize the project:\n\n ```bash\n mkdir xcm-fee-estimation && \\\n cd xcm-fee-estimation\n ```\n\n2. Initialize the project:\n\n ```bash\n npm init -y\n ```\n\n3. Install dev dependencies:\n\n ```bash\n npm install --save-dev @types/node@^22.12.0 ts-node@^10.9.2 typescript@^5.7.3\n ```\n\n4. Install dependencies:\n\n ```bash\n npm install --save @polkadot-labs/hdkd@^0.0.13 @polkadot-labs/hdkd-helpers@^0.0.13 polkadot-api@1.9.5\n ```\n\n5. Create TypeScript configuration:\n\n ```bash\n npx tsc --init\n ```\n\n6. Generate the types for the Polkadot API for Paseo Bridge Hub and Paseo Asset Hub:\n\n ```bash\n npx papi add paseoAssetHub -n paseo_asset_hub && \\\n npx papi add paseoBridgeHub -w wss://bridge-hub-paseo.dotters.network\n ```\n\n7. Create a new file called `teleport-ah-to-bridge-hub.ts`:\n\n ```bash\n touch teleport-ah-to-bridge-hub.ts\n ```\n\n8. Import the necessary modules. Add the following code to the `teleport-ah-to-bridge-hub.ts` file:\n\n ```typescript title=\"teleport-ah-to-bridge-hub.ts\"\n import { paseoAssetHub, paseoBridgeHub } from '@polkadot-api/descriptors';\n import { createClient, FixedSizeBinary, Enum } from 'polkadot-api';\n import { getWsProvider } from 'polkadot-api/ws-provider/node';\n import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat';\n import {\n XcmVersionedLocation,\n XcmVersionedAssetId,\n XcmV3Junctions,\n XcmV3MultiassetFungibility,\n XcmVersionedXcm,\n XcmV5Instruction,\n XcmV5Junctions,\n XcmV5Junction,\n XcmV5AssetFilter,\n XcmV5WildAsset,\n } from '@polkadot-api/descriptors';\n ```\n\n9. Define constants and a `main` function where you will implement all the logic:\n\n ```typescript title=\"teleport-ah-to-bridge-hub.ts\"\n // 1 PAS = 10^10 units\n const PAS_UNITS = 10_000_000_000n; // 1 PAS\n const PAS_CENTS = 100_000_000n; // 0.01 PAS\n\n // Paseo Asset Hub constants\n const PASEO_ASSET_HUB_RPC_ENDPOINT = 'ws://localhost:8001';\n const ASSET_HUB_ACCOUNT = '15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5'; // Alice (Paseo Asset Hub)\n\n // Bridge Hub destination\n const BRIDGE_HUB_RPC_ENDPOINT = 'ws://localhost:8000';\n const BRIDGE_HUB_PARA_ID = 1002;\n const BRIDGE_HUB_BENEFICIARY =\n async function main() {\n // Code will go here\n }\n ```\n\nAll the following code explained in the subsequent sections must be added inside the `main` function."} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 3, "depth": 2, "title": "Client and API Setup", "anchor": "client-and-api-setup", "start_char": 3989, "end_char": 4866, "estimated_token_count": 172, "token_estimator": "heuristic-v1", "text": "## Client and API Setup\n\nNow you are ready to start implementing the logic for the fee estimation for the teleport you want to perform. In this step, you will create the client for the Paseo Asset Hub parachain and generate the typed API to interact with the chain. Follow the steps below:\n\nCreate the API client. You will need to create a client for the Paseo Asset Hub parachain:\n\n```typescript title=\"teleport-ah-to-bridge-hub.ts\"\n // Connect to the Asset Hub parachain\n const assetHubClient = createClient(\n withPolkadotSdkCompat(getWsProvider(PASEO_ASSET_HUB_RPC_ENDPOINT)),\n );\n\n // Get the typed API for Asset Hub\n const assetHubApi = assetHubClient.getTypedApi(paseoAssetHub);\n```\n\nEnsure that you replace the endpoint URLs with the actual WebSocket endpoints. This example uses local chopsticks endpoints, but you can use public endpoints or run local nodes."} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 4, "depth": 2, "title": "Create the XCM Message", "anchor": "create-the-xcm-message", "start_char": 4866, "end_char": 6826, "estimated_token_count": 395, "token_estimator": "heuristic-v1", "text": "## Create the XCM Message\n\nNow, you can construct a proper XCM message using the new XCM V5 instructions for teleporting from Asset Hub to the Bridge Hub Chain:\n\n```typescript title=\"teleport-ah-to-bridge-hub.ts\"\nfunction createTeleportXcmToBridgeHub(paraId: number) {\n return XcmVersionedXcm.V5([\n // Withdraw PAS from Asset Hub (PAS on parachains is parents:1, interior: Here)\n XcmV5Instruction.WithdrawAsset([\n {\n id: { parents: 1, interior: XcmV5Junctions.Here() },\n fun: XcmV3MultiassetFungibility.Fungible(1n * PAS_UNITS), // 1 PAS\n },\n ]),\n // Pay local fees on Asset Hub in PAS\n XcmV5Instruction.PayFees({\n asset: {\n id: { parents: 1, interior: XcmV5Junctions.Here() },\n fun: XcmV3MultiassetFungibility.Fungible(10n * PAS_CENTS), // 0.01 PAS\n },\n }),\n // Send to Bridge Hub parachain (parents:1, interior: X1(Parachain(paraId)))\n XcmV5Instruction.InitiateTransfer({\n destination: {\n parents: 1,\n interior: XcmV5Junctions.X1(XcmV5Junction.Parachain(paraId)),\n },\n remote_fees: Enum(\n 'Teleport',\n XcmV5AssetFilter.Definite([\n {\n id: { parents: 1, interior: XcmV5Junctions.Here() },\n fun: XcmV3MultiassetFungibility.Fungible(10n * PAS_CENTS), // 0.01 PAS\n },\n ]),\n ),\n preserve_origin: false,\n remote_xcm: [\n XcmV5Instruction.DepositAsset({\n assets: XcmV5AssetFilter.Wild(XcmV5WildAsset.AllCounted(1)),\n beneficiary: {\n parents: 0,\n interior: XcmV5Junctions.X1(\n XcmV5Junction.AccountId32({\n network: undefined,\n id: FixedSizeBinary.fromAccountId32(BRIDGE_HUB_BENEFICIARY),\n }),\n ),\n },\n }),\n ],\n assets: [\n Enum('Teleport', XcmV5AssetFilter.Wild(XcmV5WildAsset.AllCounted(1))), // Send everything.\n ],\n }),\n ]);\n}\n```"} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 5, "depth": 2, "title": "Fee Estimation Function", "anchor": "fee-estimation-function", "start_char": 6826, "end_char": 20688, "estimated_token_count": 2699, "token_estimator": "heuristic-v1", "text": "## Fee Estimation Function\n\nBelow is a four-step breakdown of the logic needed to estimate the fees for the teleport.\n\nFirst, you need to create the function that will estimate the fees for the teleport:\n\n```typescript title=\"teleport-ah-to-bridge-hub.ts\"\nasync function estimateXcmFeesFromAssetHubToBridgeHub(\n xcm: any,\n assetHubApi: any,\n) {\n // Code will go here\n}\n```\n\n1. **Local execution fees on Asset Hub**: Compute the XCM weight locally, then convert that weight to PAS using Asset Hub's view of PAS (`parents: 1, interior: Here`). Add the code to the function:\n\n ```typescript title=\"teleport-ah-to-bridge-hub.ts\"\n console.log('=== Fee Estimation Process (Asset Hub → Bridge Hub) ===');\n\n // 1. LOCAL EXECUTION FEES on Asset Hub\n console.log('1. Calculating local execution fees on Asset Hub...');\n let localExecutionFees = 0n;\n\n const weightResult =\n await assetHubApi.apis.XcmPaymentApi.query_xcm_weight(xcm);\n if (weightResult.success) {\n console.log('✓ XCM weight (Asset Hub):', weightResult.value);\n\n // Convert weight to PAS fees from Asset Hub's perspective (parents:1, Here)\n const executionFeesResult =\n await assetHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee(\n weightResult.value,\n XcmVersionedAssetId.V4({\n parents: 1,\n interior: XcmV3Junctions.Here(),\n }),\n );\n\n if (executionFeesResult.success) {\n localExecutionFees = executionFeesResult.value;\n console.log(\n '✓ Local execution fees (Asset Hub):',\n localExecutionFees.toString(),\n 'PAS units',\n );\n } else {\n console.log(\n '✗ Failed to calculate local execution fees:',\n executionFeesResult.value,\n );\n }\n } else {\n console.log(\n '✗ Failed to query XCM weight on Asset Hub:',\n weightResult.value,\n );\n }\n ```\n\n2. **Dry-run and delivery fees to Bridge Hub**: Dry-run the XCM on Asset Hub to capture forwarded messages, locate the one targeting Bridge Hub (`parents: 1, interior: Here`), and ask for delivery fees. Add the code to the function:\n\n ```typescript title=\"teleport-ah-to-bridge-hub.ts\"\n // 2. DELIVERY FEES + REMOTE EXECUTION FEES\n console.log('\\n2. Calculating delivery and remote execution fees...');\n let deliveryFees = 0n;\n let remoteExecutionFees = 0n; // Skipped (Bridge Hub descriptor not available)\n\n // Origin from Asset Hub perspective\n const origin = XcmVersionedLocation.V5({\n parents: 0,\n interior: XcmV5Junctions.X1(\n XcmV5Junction.AccountId32({\n id: FixedSizeBinary.fromAccountId32(ASSET_HUB_ACCOUNT),\n network: undefined,\n }),\n ),\n });\n\n // Dry run the XCM locally on Asset Hub\n const dryRunResult = await assetHubApi.apis.DryRunApi.dry_run_xcm(\n origin,\n xcm,\n );\n\n if (\n dryRunResult.success &&\n dryRunResult.value.execution_result.type === 'Complete'\n ) {\n console.log('✓ Local dry run on Asset Hub successful');\n\n const { forwarded_xcms: forwardedXcms } = dryRunResult.value;\n\n // Find the XCM message sent to Bridge Hub (parents:1, interior: X1(Parachain(1002)))\n const bridgeHubXcmEntry = forwardedXcms.find(\n ([location, _]: [any, any]) =>\n (location.type === 'V4' || location.type === 'V5') &&\n location.value.parents === 1 &&\n location.value.interior?.type === 'X1' &&\n location.value.interior.value?.type === 'Parachain' &&\n location.value.interior.value.value === BRIDGE_HUB_PARA_ID,\n );\n\n if (bridgeHubXcmEntry) {\n const [destination, messages] = bridgeHubXcmEntry;\n const remoteXcm = messages[0];\n\n console.log('✓ Found XCM message to Bridge Hub');\n\n // Calculate delivery fees from Asset Hub to Bridge Hub\n const deliveryFeesResult =\n await assetHubApi.apis.XcmPaymentApi.query_delivery_fees(\n destination,\n remoteXcm,\n );\n\n if (\n deliveryFeesResult.success &&\n deliveryFeesResult.value.type === 'V5' &&\n deliveryFeesResult.value.value[0]?.fun?.type === 'Fungible'\n ) {\n deliveryFees = deliveryFeesResult.value.value[0].fun.value;\n console.log('✓ Delivery fees:', deliveryFees.toString(), 'PAS units');\n } else {\n console.log('✗ Failed to calculate delivery fees:', deliveryFeesResult);\n }\n ```\n\n3. **Remote execution fees on Bridge Hub**: Connect to Bridge Hub, recompute the forwarded XCM weight there, and convert weight to PAS (`parents: 0, interior: Here`). Add the code to the function:\n\n ```typescript title=\"teleport-ah-to-bridge-hub.ts\"\n // 3. REMOTE EXECUTION FEES on Bridge Hub\n console.log('\\n3. Calculating remote execution fees on Bridge Hub');\n try {\n const bridgeHubClient = createClient(\n withPolkadotSdkCompat(getWsProvider(BRIDGE_HUB_RPC_ENDPOINT)),\n );\n const bridgeHubApi = bridgeHubClient.getTypedApi(paseoBridgeHub);\n const remoteWeightResult =\n await bridgeHubApi.apis.XcmPaymentApi.query_xcm_weight(remoteXcm);\n const remoteFeesResult =\n await bridgeHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee(\n remoteWeightResult.value as {\n ref_time: bigint;\n proof_size: bigint;\n },\n XcmVersionedAssetId.V4({\n parents: 1,\n interior: XcmV3Junctions.Here(),\n }),\n );\n bridgeHubClient.destroy();\n remoteExecutionFees = remoteFeesResult.value as bigint;\n console.log(\n '✓ Remote execution fees:',\n remoteExecutionFees.toString(),\n 'PAS units',\n );\n } catch (error) {\n console.error(\n 'Error calculating remote execution fees on Bridge Hub:',\n error,\n );\n }\n } else {\n console.log('✗ No XCM message found to Bridge Hub');\n }\n } else {\n console.log('✗ Local dry run failed on Asset Hub:', dryRunResult.value);\n }\n ```\n\n4. **Sum and return totals**: Aggregate all parts, print a short summary, and return a structured result. Add the code to the function:\n\n ```typescript title=\"teleport-ah-to-bridge-hub.ts\"\n // 4. TOTAL FEES\n const totalFees = localExecutionFees + deliveryFees + remoteExecutionFees;\n\n console.log('\\n=== Fee Summary (Asset Hub → Bridge Hub) ===');\n console.log(\n 'Local execution fees:',\n localExecutionFees.toString(),\n 'PAS units',\n );\n console.log('Delivery fees:', deliveryFees.toString(), 'PAS units');\n console.log(\n 'Remote execution fees:',\n remoteExecutionFees.toString(),\n 'PAS units',\n );\n console.log('TOTAL FEES:', totalFees.toString(), 'PAS units');\n console.log(\n 'TOTAL FEES:',\n (Number(totalFees) / Number(PAS_UNITS)).toFixed(4),\n 'PAS',\n );\n\n return {\n localExecutionFees,\n deliveryFees,\n remoteExecutionFees,\n totalFees,\n };\n }\n ```\n\nThe full code for the fee estimation function is the following:\n\n??? code \"Fee Estimation Function\"\n\n ```typescript title=\"teleport-ah-to-bridge-hub.ts\"\n async function estimateXcmFeesFromAssetHubToBridgeHub(\n xcm: any,\n assetHubApi: any,\n ) {\n console.log('=== Fee Estimation Process (Asset Hub → Bridge Hub) ===');\n\n // 1. LOCAL EXECUTION FEES on Asset Hub\n console.log('1. Calculating local execution fees on Asset Hub...');\n let localExecutionFees = 0n;\n\n const weightResult =\n await assetHubApi.apis.XcmPaymentApi.query_xcm_weight(xcm);\n if (weightResult.success) {\n console.log('✓ XCM weight (Asset Hub):', weightResult.value);\n\n // Convert weight to PAS fees from Asset Hub's perspective (parents:1, Here)\n const executionFeesResult =\n await assetHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee(\n weightResult.value,\n XcmVersionedAssetId.V4({\n parents: 1,\n interior: XcmV3Junctions.Here(),\n }),\n );\n\n if (executionFeesResult.success) {\n localExecutionFees = executionFeesResult.value;\n console.log(\n '✓ Local execution fees (Asset Hub):',\n localExecutionFees.toString(),\n 'PAS units',\n );\n } else {\n console.log(\n '✗ Failed to calculate local execution fees:',\n executionFeesResult.value,\n );\n }\n } else {\n console.log(\n '✗ Failed to query XCM weight on Asset Hub:',\n weightResult.value,\n );\n }\n\n // 2. DELIVERY FEES + REMOTE EXECUTION FEES\n console.log('\\n2. Calculating delivery and remote execution fees...');\n let deliveryFees = 0n;\n let remoteExecutionFees = 0n; // Skipped (Bridge Hub descriptor not available)\n\n // Origin from Asset Hub perspective\n const origin = XcmVersionedLocation.V5({\n parents: 0,\n interior: XcmV5Junctions.X1(\n XcmV5Junction.AccountId32({\n id: FixedSizeBinary.fromAccountId32(ASSET_HUB_ACCOUNT),\n network: undefined,\n }),\n ),\n });\n\n // Dry run the XCM locally on Asset Hub\n const dryRunResult = await assetHubApi.apis.DryRunApi.dry_run_xcm(\n origin,\n xcm,\n );\n\n if (\n dryRunResult.success &&\n dryRunResult.value.execution_result.type === 'Complete'\n ) {\n console.log('✓ Local dry run on Asset Hub successful');\n\n const { forwarded_xcms: forwardedXcms } = dryRunResult.value;\n\n // Find the XCM message sent to Bridge Hub (parents:1, interior: X1(Parachain(1002)))\n const bridgeHubXcmEntry = forwardedXcms.find(\n ([location, _]: [any, any]) =>\n (location.type === 'V4' || location.type === 'V5') &&\n location.value.parents === 1 &&\n location.value.interior?.type === 'X1' &&\n location.value.interior.value?.type === 'Parachain' &&\n location.value.interior.value.value === BRIDGE_HUB_PARA_ID,\n );\n\n if (bridgeHubXcmEntry) {\n const [destination, messages] = bridgeHubXcmEntry;\n const remoteXcm = messages[0];\n\n console.log('✓ Found XCM message to Bridge Hub');\n\n // Calculate delivery fees from Asset Hub to Bridge Hub\n const deliveryFeesResult =\n await assetHubApi.apis.XcmPaymentApi.query_delivery_fees(\n destination,\n remoteXcm,\n );\n\n if (\n deliveryFeesResult.success &&\n deliveryFeesResult.value.type === 'V5' &&\n deliveryFeesResult.value.value[0]?.fun?.type === 'Fungible'\n ) {\n deliveryFees = deliveryFeesResult.value.value[0].fun.value;\n console.log('✓ Delivery fees:', deliveryFees.toString(), 'PAS units');\n } else {\n console.log('✗ Failed to calculate delivery fees:', deliveryFeesResult);\n }\n\n // 3. REMOTE EXECUTION FEES on Bridge Hub\n console.log('\\n3. Calculating remote execution fees on Bridge Hub');\n try {\n const bridgeHubClient = createClient(\n withPolkadotSdkCompat(getWsProvider(BRIDGE_HUB_RPC_ENDPOINT)),\n );\n const bridgeHubApi = bridgeHubClient.getTypedApi(paseoBridgeHub);\n const remoteWeightResult =\n await bridgeHubApi.apis.XcmPaymentApi.query_xcm_weight(remoteXcm);\n const remoteFeesResult =\n await bridgeHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee(\n remoteWeightResult.value as {\n ref_time: bigint;\n proof_size: bigint;\n },\n XcmVersionedAssetId.V4({\n parents: 1,\n interior: XcmV3Junctions.Here(),\n }),\n );\n bridgeHubClient.destroy();\n remoteExecutionFees = remoteFeesResult.value as bigint;\n console.log(\n '✓ Remote execution fees:',\n remoteExecutionFees.toString(),\n 'PAS units',\n );\n } catch (error) {\n console.error(\n 'Error calculating remote execution fees on Bridge Hub:',\n error,\n );\n }\n } else {\n console.log('✗ No XCM message found to Bridge Hub');\n }\n } else {\n console.log('✗ Local dry run failed on Asset Hub:', dryRunResult.value);\n }\n\n // 4. TOTAL FEES\n const totalFees = localExecutionFees + deliveryFees + remoteExecutionFees;\n\n console.log('\\n=== Fee Summary (Asset Hub → Bridge Hub) ===');\n console.log(\n 'Local execution fees:',\n localExecutionFees.toString(),\n 'PAS units',\n );\n console.log('Delivery fees:', deliveryFees.toString(), 'PAS units');\n console.log(\n 'Remote execution fees:',\n remoteExecutionFees.toString(),\n 'PAS units',\n );\n console.log('TOTAL FEES:', totalFees.toString(), 'PAS units');\n console.log(\n 'TOTAL FEES:',\n (Number(totalFees) / Number(PAS_UNITS)).toFixed(4),\n 'PAS',\n );\n\n return {\n localExecutionFees,\n deliveryFees,\n remoteExecutionFees,\n totalFees,\n };\n }\n ```"} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 6, "depth": 2, "title": "Complete Implementation", "anchor": "complete-implementation", "start_char": 20688, "end_char": 22403, "estimated_token_count": 411, "token_estimator": "heuristic-v1", "text": "## Complete Implementation\n\nNow put it all together in the main function:\n\n```typescript title=\"teleport-ah-to-bridge-hub.ts\"\nasync function main() {\n // Connect to the Asset Hub parachain\n const assetHubClient = createClient(\n withPolkadotSdkCompat(getWsProvider(PASEO_ASSET_HUB_RPC_ENDPOINT)),\n );\n\n // Get the typed API for Asset Hub\n const assetHubApi = assetHubClient.getTypedApi(paseoAssetHub);\n\n try {\n // Create the XCM message for teleport (Asset Hub → Bridge Hub)\n const xcm = createTeleportXcmToBridgeHub(BRIDGE_HUB_PARA_ID);\n\n console.log('=== XCM Teleport: Paseo Asset Hub → Bridge Hub ===');\n console.log('From:', ASSET_HUB_ACCOUNT, '(Alice on Asset Hub)');\n console.log('To:', BRIDGE_HUB_BENEFICIARY, '(Beneficiary on Bridge Hub)');\n console.log('Amount:', '1 PAS');\n console.log('');\n\n // Estimate all fees\n const fees = await estimateXcmFeesFromAssetHubToBridgeHub(xcm, assetHubApi);\n void fees; // prevent unused var under isolatedModules\n\n // Create the execute transaction on Asset Hub\n const tx = assetHubApi.tx.PolkadotXcm.execute({\n message: xcm,\n max_weight: {\n ref_time: 6000000000n,\n proof_size: 65536n,\n },\n });\n\n console.log('\\n=== Transaction Details ===');\n console.log('Transaction hex:', (await tx.getEncodedData()).asHex());\n console.log('Ready to submit!');\n } catch (error) {\n console.log('Error stack:', (error as Error).stack);\n console.error('Error occurred:', (error as Error).message);\n if ((error as Error).cause) {\n console.dir((error as Error).cause, { depth: null });\n }\n } finally {\n // Ensure client is always destroyed\n assetHubClient.destroy();\n }\n}\n```"} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 7, "depth": 2, "title": "Full Code", "anchor": "full-code", "start_char": 22403, "end_char": 33766, "estimated_token_count": 2142, "token_estimator": "heuristic-v1", "text": "## Full Code\n\nThe full code for the complete implementation is the following:\n\n??? code \"Teleport from Asset Hub to Bridge Hub\"\n\n ```typescript title=\"teleport-ah-to-bridge-hub.ts\"\n import { paseoAssetHub, paseoBridgeHub } from '@polkadot-api/descriptors';\n import { createClient, FixedSizeBinary, Enum } from 'polkadot-api';\n import { getWsProvider } from 'polkadot-api/ws-provider/node';\n import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat';\n import {\n XcmVersionedLocation,\n XcmVersionedAssetId,\n XcmV3Junctions,\n XcmV3MultiassetFungibility,\n XcmVersionedXcm,\n XcmV5Instruction,\n XcmV5Junctions,\n XcmV5Junction,\n XcmV5AssetFilter,\n XcmV5WildAsset,\n } from '@polkadot-api/descriptors';\n\n // 1 PAS = 10^10 units\n const PAS_UNITS = 10_000_000_000n; // 1 PAS\n const PAS_CENTS = 100_000_000n; // 0.01 PAS\n\n // Paseo Asset Hub constants\n const PASEO_ASSET_HUB_RPC_ENDPOINT = 'ws://localhost:8001';\n const ASSET_HUB_ACCOUNT = '15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5'; // Alice (Paseo Asset Hub)\n\n // Bridge Hub destination\n const BRIDGE_HUB_RPC_ENDPOINT = 'ws://localhost:8000';\n const BRIDGE_HUB_PARA_ID = 1002;\n const BRIDGE_HUB_BENEFICIARY =\n '14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3'; // Bob (Bridge Hub)\n\n // Create the XCM message for teleport (Asset Hub → Bridge Hub)\n function createTeleportXcmToBridgeHub(paraId: number) {\n return XcmVersionedXcm.V5([\n // Withdraw PAS from Asset Hub (PAS on parachains is parents:1, interior: Here)\n XcmV5Instruction.WithdrawAsset([\n {\n id: { parents: 1, interior: XcmV5Junctions.Here() },\n fun: XcmV3MultiassetFungibility.Fungible(1n * PAS_UNITS), // 1 PAS\n },\n ]),\n // Pay local fees on Asset Hub in PAS\n XcmV5Instruction.PayFees({\n asset: {\n id: { parents: 1, interior: XcmV5Junctions.Here() },\n fun: XcmV3MultiassetFungibility.Fungible(10n * PAS_CENTS), // 0.01 PAS\n },\n }),\n // Send to Bridge Hub parachain (parents:1, interior: X1(Parachain(paraId)))\n XcmV5Instruction.InitiateTransfer({\n destination: {\n parents: 1,\n interior: XcmV5Junctions.X1(XcmV5Junction.Parachain(paraId)),\n },\n remote_fees: Enum(\n 'Teleport',\n XcmV5AssetFilter.Definite([\n {\n id: { parents: 1, interior: XcmV5Junctions.Here() },\n fun: XcmV3MultiassetFungibility.Fungible(10n * PAS_CENTS), // 0.01 PAS\n },\n ]),\n ),\n preserve_origin: false,\n remote_xcm: [\n XcmV5Instruction.DepositAsset({\n assets: XcmV5AssetFilter.Wild(XcmV5WildAsset.AllCounted(1)),\n beneficiary: {\n parents: 0,\n interior: XcmV5Junctions.X1(\n XcmV5Junction.AccountId32({\n network: undefined,\n id: FixedSizeBinary.fromAccountId32(BRIDGE_HUB_BENEFICIARY),\n }),\n ),\n },\n }),\n ],\n assets: [\n Enum('Teleport', XcmV5AssetFilter.Wild(XcmV5WildAsset.AllCounted(1))), // Send everything.\n ],\n }),\n ]);\n }\n\n async function estimateXcmFeesFromAssetHubToBridgeHub(\n xcm: any,\n assetHubApi: any,\n ) {\n console.log('=== Fee Estimation Process (Asset Hub → Bridge Hub) ===');\n\n // 1. LOCAL EXECUTION FEES on Asset Hub\n console.log('1. Calculating local execution fees on Asset Hub...');\n let localExecutionFees = 0n;\n\n const weightResult =\n await assetHubApi.apis.XcmPaymentApi.query_xcm_weight(xcm);\n if (weightResult.success) {\n console.log('✓ XCM weight (Asset Hub):', weightResult.value);\n\n // Convert weight to PAS fees from Asset Hub's perspective (parents:1, Here)\n const executionFeesResult =\n await assetHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee(\n weightResult.value,\n XcmVersionedAssetId.V4({\n parents: 1,\n interior: XcmV3Junctions.Here(),\n }),\n );\n\n if (executionFeesResult.success) {\n localExecutionFees = executionFeesResult.value;\n console.log(\n '✓ Local execution fees (Asset Hub):',\n localExecutionFees.toString(),\n 'PAS units',\n );\n } else {\n console.log(\n '✗ Failed to calculate local execution fees:',\n executionFeesResult.value,\n );\n }\n } else {\n console.log(\n '✗ Failed to query XCM weight on Asset Hub:',\n weightResult.value,\n );\n }\n\n // 2. DELIVERY FEES + REMOTE EXECUTION FEES\n console.log('\\n2. Calculating delivery and remote execution fees...');\n let deliveryFees = 0n;\n let remoteExecutionFees = 0n; // Skipped (Bridge Hub descriptor not available)\n\n // Origin from Asset Hub perspective\n const origin = XcmVersionedLocation.V5({\n parents: 0,\n interior: XcmV5Junctions.X1(\n XcmV5Junction.AccountId32({\n id: FixedSizeBinary.fromAccountId32(ASSET_HUB_ACCOUNT),\n network: undefined,\n }),\n ),\n });\n\n // Dry run the XCM locally on Asset Hub\n const dryRunResult = await assetHubApi.apis.DryRunApi.dry_run_xcm(\n origin,\n xcm,\n );\n\n if (\n dryRunResult.success &&\n dryRunResult.value.execution_result.type === 'Complete'\n ) {\n console.log('✓ Local dry run on Asset Hub successful');\n\n const { forwarded_xcms: forwardedXcms } = dryRunResult.value;\n\n // Find the XCM message sent to Bridge Hub (parents:1, interior: X1(Parachain(1002)))\n const bridgeHubXcmEntry = forwardedXcms.find(\n ([location, _]: [any, any]) =>\n (location.type === 'V4' || location.type === 'V5') &&\n location.value.parents === 1 &&\n location.value.interior?.type === 'X1' &&\n location.value.interior.value?.type === 'Parachain' &&\n location.value.interior.value.value === BRIDGE_HUB_PARA_ID,\n );\n\n if (bridgeHubXcmEntry) {\n const [destination, messages] = bridgeHubXcmEntry;\n const remoteXcm = messages[0];\n\n console.log('✓ Found XCM message to Bridge Hub');\n\n // Calculate delivery fees from Asset Hub to Bridge Hub\n const deliveryFeesResult =\n await assetHubApi.apis.XcmPaymentApi.query_delivery_fees(\n destination,\n remoteXcm,\n );\n\n if (\n deliveryFeesResult.success &&\n deliveryFeesResult.value.type === 'V5' &&\n deliveryFeesResult.value.value[0]?.fun?.type === 'Fungible'\n ) {\n deliveryFees = deliveryFeesResult.value.value[0].fun.value;\n console.log('✓ Delivery fees:', deliveryFees.toString(), 'PAS units');\n } else {\n console.log('✗ Failed to calculate delivery fees:', deliveryFeesResult);\n }\n\n // 3. REMOTE EXECUTION FEES on Bridge Hub\n console.log('\\n3. Calculating remote execution fees on Bridge Hub');\n try {\n const bridgeHubClient = createClient(\n withPolkadotSdkCompat(getWsProvider(BRIDGE_HUB_RPC_ENDPOINT)),\n );\n const bridgeHubApi = bridgeHubClient.getTypedApi(paseoBridgeHub);\n const remoteWeightResult =\n await bridgeHubApi.apis.XcmPaymentApi.query_xcm_weight(remoteXcm);\n const remoteFeesResult =\n await bridgeHubApi.apis.XcmPaymentApi.query_weight_to_asset_fee(\n remoteWeightResult.value as {\n ref_time: bigint;\n proof_size: bigint;\n },\n XcmVersionedAssetId.V4({\n parents: 1,\n interior: XcmV3Junctions.Here(),\n }),\n );\n bridgeHubClient.destroy();\n remoteExecutionFees = remoteFeesResult.value as bigint;\n console.log(\n '✓ Remote execution fees:',\n remoteExecutionFees.toString(),\n 'PAS units',\n );\n } catch (error) {\n console.error(\n 'Error calculating remote execution fees on Bridge Hub:',\n error,\n );\n }\n } else {\n console.log('✗ No XCM message found to Bridge Hub');\n }\n } else {\n console.log('✗ Local dry run failed on Asset Hub:', dryRunResult.value);\n }\n\n // 4. TOTAL FEES\n const totalFees = localExecutionFees + deliveryFees + remoteExecutionFees;\n\n console.log('\\n=== Fee Summary (Asset Hub → Bridge Hub) ===');\n console.log(\n 'Local execution fees:',\n localExecutionFees.toString(),\n 'PAS units',\n );\n console.log('Delivery fees:', deliveryFees.toString(), 'PAS units');\n console.log(\n 'Remote execution fees:',\n remoteExecutionFees.toString(),\n 'PAS units',\n );\n console.log('TOTAL FEES:', totalFees.toString(), 'PAS units');\n console.log(\n 'TOTAL FEES:',\n (Number(totalFees) / Number(PAS_UNITS)).toFixed(4),\n 'PAS',\n );\n\n return {\n localExecutionFees,\n deliveryFees,\n remoteExecutionFees,\n totalFees,\n };\n }\n\n async function main() {\n // Connect to the Asset Hub parachain\n const assetHubClient = createClient(\n withPolkadotSdkCompat(getWsProvider(PASEO_ASSET_HUB_RPC_ENDPOINT)),\n );\n\n // Get the typed API for Asset Hub\n const assetHubApi = assetHubClient.getTypedApi(paseoAssetHub);\n\n try {\n // Create the XCM message for teleport (Asset Hub → Bridge Hub)\n const xcm = createTeleportXcmToBridgeHub(BRIDGE_HUB_PARA_ID);\n\n console.log('=== XCM Teleport: Paseo Asset Hub → Bridge Hub ===');\n console.log('From:', ASSET_HUB_ACCOUNT, '(Alice on Asset Hub)');\n console.log('To:', BRIDGE_HUB_BENEFICIARY, '(Beneficiary on Bridge Hub)');\n console.log('Amount:', '1 PAS');\n console.log('');\n\n // Estimate all fees\n const fees = await estimateXcmFeesFromAssetHubToBridgeHub(xcm, assetHubApi);\n void fees; // prevent unused var under isolatedModules\n\n // Create the execute transaction on Asset Hub\n const tx = assetHubApi.tx.PolkadotXcm.execute({\n message: xcm,\n max_weight: {\n ref_time: 6000000000n,\n proof_size: 65536n,\n },\n });\n\n console.log('\\n=== Transaction Details ===');\n console.log('Transaction hex:', (await tx.getEncodedData()).asHex());\n console.log('Ready to submit!');\n } catch (error) {\n console.log('Error stack:', (error as Error).stack);\n console.error('Error occurred:', (error as Error).message);\n if ((error as Error).cause) {\n console.dir((error as Error).cause, { depth: null });\n }\n } finally {\n // Ensure client is always destroyed\n assetHubClient.destroy();\n }\n }\n\n main().catch(console.error);\n\n ```"} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 8, "depth": 2, "title": "Running the Script", "anchor": "running-the-script", "start_char": 33766, "end_char": 38015, "estimated_token_count": 950, "token_estimator": "heuristic-v1", "text": "## Running the Script\n\nBefore running the script, you can use chopsticks to fork the Paseo Asset Hub and Paseo Bridge Hub chains locally. To do so, you can use the following files and commands:\n\n1. Create a new directory called `.chopsticks` and add the files:\n\n ??? code \"paseo-bridge-hub.yml\"\n\n {% raw %}\n ```yaml title=\".chopsticks/paseo-bridge-hub.yml\"\n endpoint: wss://bridge-hub-paseo.dotters.network\n mock-signature-host: true\n block: ${env.PASEO_BRIDGE_HUB_BLOCK_NUMBER}\n db: ./db.sqlite\n\n import-storage:\n Sudo:\n Key: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY # Alice\n System:\n Account:\n -\n -\n - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\n - providers: 1\n data:\n free: '10000000000000000000'\n ```\n {% endraw %}\n \n ??? code \"paseo-asset-hub.yml\"\n\n {% raw %}\n ```yaml title=\".chopsticks/paseo-asset-hub.yml\"\n endpoint: wss://asset-hub-paseo-rpc.n.dwellir.com\n mock-signature-host: true\n block: ${env.PASEO_ASSET_HUB_BLOCK_NUMBER}\n db: ./db.sqlite\n\n import-storage:\n Sudo:\n Key: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY # Alice\n System:\n Account:\n -\n -\n - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\n - providers: 1\n data:\n free: '10000000000000000000'\n ```\n {% endraw %}\n\n2. Run the following command to fork the Paseo Bridge Hub chain:\n\n ```bash\n chopsticks --config=.chopsticks/paseo-bridge-hub.yml\n ```\n\n After running the command, you will see the following output:\n\n
    \n chopsticks --config=.chopsticks/paseo-bridge-hub.yml\n [15:55:22.770] INFO: Paseo Bridge Hub RPC listening on http://[::]:8000 and ws://[::]:8000\n app: \"chopsticks\"\n
    \n\n3. Run the following command to fork the Paseo Asset Hub chain:\n\n ```bash\n chopsticks --config=.chopsticks/paseo-asset-hub.yml\n ```\n\n After running the commands, you will see the following output:\n\n
    \n chopsticks --config=.chopsticks/paseo-asset-hub.yml\n [15:55:22.770] INFO: Paseo Asset Hub Testnet RPC listening on http://[::]:8001 and ws://[::]:8001\n app: \"chopsticks\"\n
    \n\n4. Run the script:\n\n ```bash\n npx ts-node teleport-ah-to-bridge-hub.ts\n ```\n\nAfter running the script, you will see the following output:\n\n
    \n npx ts-node teleport-ah-to-bridge-hub.ts\n
    \n=== XCM Teleport: Paseo Asset Hub → Bridge Hub ===\nFrom: 15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5 (Alice on Asset Hub)\nTo: 14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3 (Beneficiary on Bridge Hub)\nAmount: 1 PAS\n\n=== Fee Estimation Process (Asset Hub → Bridge Hub) ===\n1. Calculating local execution fees on Asset Hub...\n✓ XCM weight (Asset Hub): { ref_time: 1462082000n, proof_size: 19578n }\n✓ Local execution fees (Asset Hub): 97890000 PAS units\n\n2. Calculating delivery and remote execution fees...\n✓ Local dry run on Asset Hub successful\n✓ Found XCM message to Bridge Hub\n✓ Delivery fees: 305150000 PAS units\n\n3. Calculating remote execution fees on Bridge Hub\n✓ Remote execution fees: 17965000 PAS units\n\n=== Fee Summary (Asset Hub → Bridge Hub) ===\nLocal execution fees: 97890000 PAS units\nDelivery fees: 305150000 PAS units\nRemote execution fees: 17965000 PAS units\nTOTAL FEES: 421005000 PAS units\nTOTAL FEES: 0.0421 PAS\n\n=== Transaction Details ===\nTransaction hex: 0x1f03050c00040100000700e40b54023001000002286bee31010100a90f0100000401000002286bee000400010204040d010204000101008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480700bca0650102000400\nReady to submit!\n\n\n
    "} -{"page_id": "chain-interactions-send-transactions-interoperability-estimate-xcm-fees", "page_title": "XCM Fee Estimation", "index": 9, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 38015, "end_char": 38625, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nThis approach provides accurate fee estimation for XCM teleports from Asset Hub to Bridge Hub Chain by properly simulating execution on both chains and utilizing dedicated runtime APIs for fee calculation. The fee breakdown helps you understand the cost structure of reverse cross-chain operations (parachain → bridge hub chain) and ensures your transactions have sufficient funds to complete successfully.\n\nThe key insight is understanding how asset references change based on the perspective of each chain in the XCM ecosystem, which is crucial for proper fee estimation and XCM construction."} -{"page_id": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", "page_title": "Transfer Assets Between Parachains", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 38, "end_char": 1008, "estimated_token_count": 223, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThis guide walks you through transferring tokens between two parachains using the [ParaSpell XCM SDK](/reference/tools/paraspell/){target=\\_blank}. This example utilizes [Asset Hub](/polkadot-protocol/architecture/system-chains/asset-hub/){target=\\_blank} and the [People Chain](/polkadot-protocol/architecture/system-chains/people/){target=\\_blank}. However, the same approach can be applied to transfers between other parachains.\n\nFor development purposes, this guide will use the [Polkadot TestNet](/develop/networks/#paseo){target=\\_blank}, so the transferred token will be PAS.\n\nIn this guide, you will:\n\n- Build an XCM transfer transaction using ParaSpell XCM SDK.\n- Perform a dry run to validate the transfer.\n- Verify the [Existential Deposit (ED)](/reference/glossary/#existential-deposit){target=\\_blank} requirement on the destination chain.\n- Retrieve information regarding the transfer, along with fee estimates.\n- Submit the transaction."} -{"page_id": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", "page_title": "Transfer Assets Between Parachains", "index": 1, "depth": 3, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 1008, "end_char": 1456, "estimated_token_count": 116, "token_estimator": "heuristic-v1", "text": "### Prerequisites\n\nBefore you begin, ensure you have the following:\n\n- Knowledge of the [fundamentals of Polkadot](/parachains/get-started/){target=\\_blank}.\n- Basic understanding of [XCM](/parachains/interoperability/get-started/){target=\\_blank}.\n- Basic familiarity with JavaScript or TypeScript.\n- Installed [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm){target=\\_blank}, a JavaScript and TypeScript package manager."} -{"page_id": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", "page_title": "Transfer Assets Between Parachains", "index": 2, "depth": 2, "title": "Initialize Your Project", "anchor": "initialize-your-project", "start_char": 1456, "end_char": 3282, "estimated_token_count": 438, "token_estimator": "heuristic-v1", "text": "## Initialize Your Project\n\nCreate the project folder:\n\n```bash\nmkdir paraspell-transfer && \\\ncd paraspell-transfer\n```\n\nInitialize the JavaScript project:\n\n```bash\nnpm init -y\n```\n\nInstall dev dependencies:\n\n```bash\nnpm install --save-dev @types/node@^22.12.0 tsx@^4.20.6 typescript@^5.7.3\n```\n\nInstall the required dependencies:\n\n```bash\nnpm install --save @paraspell/sdk@11.12.6 polkadot-api@1.20.0 @polkadot-labs/hdkd-helpers@0.0.26 @polkadot-labs/hdkd@0.0.25\n```\n\nNow add the following setup code to `index.ts`:\n\n```ts title=\"index.ts\"\nimport { Builder, hasDryRunSupport } from '@paraspell/sdk';\nimport {\n entropyToMiniSecret,\n mnemonicToEntropy,\n ss58Address,\n} from '@polkadot-labs/hdkd-helpers';\nimport { getPolkadotSigner } from 'polkadot-api/signer';\nimport { sr25519CreateDerive } from '@polkadot-labs/hdkd';\nimport { inspect } from 'util';\n\n// PAS token has 10 decimals\nconst PAS_UNITS = 10_000_000_000n;\n\nconst SEED_PHRASE =\n 'INSERT_YOUR_SEED_PHRASE';\n\n// Create Sr25519 signer from mnemonic\nfunction getSigner() {\n const entropy = mnemonicToEntropy(SEED_PHRASE);\n const miniSecret = entropyToMiniSecret(entropy);\n const derive = sr25519CreateDerive(miniSecret);\n const keyPair = derive('');\n return getPolkadotSigner(keyPair.publicKey, 'Sr25519', keyPair.sign);\n}\n\nconst RECIPIENT_ADDRESS = ss58Address(getSigner().publicKey);\nconst SENDER_ADDRESS = ss58Address(getSigner().publicKey);\n```\n\nReplace the `INSERT_YOUR_SEED_PHRASE` with the seed phrase from your Polkadot development account.\n\nBe sure to fund this account with some PAS tokens on the Paseo Asset Hub using the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1000){target=_blank}.\n\n!!!warning \"Security Warning\"\n Never commit your mnemonic phrase to production code. Use environment variables or secure key management systems."} -{"page_id": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", "page_title": "Transfer Assets Between Parachains", "index": 3, "depth": 2, "title": "Build a Token Transfer Transaction", "anchor": "build-a-token-transfer-transaction", "start_char": 3282, "end_char": 4195, "estimated_token_count": 229, "token_estimator": "heuristic-v1", "text": "## Build a Token Transfer Transaction\n\nThe next step is to build the transaction that you intend to execute.\n\nIn this example, you will transfer 10 PAS tokens from Paseo's Asset Hub to Paseo's People Chain system parachain.\n\nAdd the ParaSpell transaction code to your `index.ts` file:\n\n```ts title=\"index.ts\"\nasync function transfer() {\n const signer = getSigner();\n\n const tx = await Builder()\n .from('AssetHubPaseo')\n .to('PeoplePaseo')\n .currency({\n symbol: 'PAS',\n amount: 10n * PAS_UNITS, // 10 PAS\n })\n .address(RECIPIENT_ADDRESS)\n .build();\n\n console.log('Built transaction:', inspect(tx, { colors: true, depth: null }));\n\n const result = await tx.signAndSubmit(signer);\n console.log(inspect(result, { colors: true, depth: null }));\n process.exit(0);\n}\n```\n\nDo not execute it just yet. You will perform a dry run of this transaction first to ensure it works as expected."} -{"page_id": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", "page_title": "Transfer Assets Between Parachains", "index": 4, "depth": 2, "title": "Perform a Dry Run", "anchor": "perform-a-dry-run", "start_char": 4195, "end_char": 8689, "estimated_token_count": 832, "token_estimator": "heuristic-v1", "text": "## Perform a Dry Run\n\nDry runs simulate the transaction without broadcasting it, allowing you to confirm success in advance.\n\nAdd the following dry run code to your `index.ts` script:\n\n```ts title=\"index.ts\"\nasync function dryRunTransfer() {\n if (!hasDryRunSupport('AssetHubPaseo')) {\n console.log('Dry run is not supported on AssetHubPaseo.');\n return;\n }\n\n const tx = await Builder()\n .from('AssetHubPaseo')\n .to('PeoplePaseo')\n .currency({\n symbol: 'PAS',\n amount: 10n * PAS_UNITS,\n })\n .address(RECIPIENT_ADDRESS)\n .senderAddress(SENDER_ADDRESS)\n .dryRun();\n\n console.log(inspect(tx, { colors: true, depth: null }));\n process.exit(0);\n}\n\ndryRunTransfer();\n```\nRun the script using the following command:\n\n```bash\nnpx tsx index.ts\n```\n\nThe result of the dry run will look similar to the following example output:\n\n
    \n npx tsx index.ts\n {\n failureReason: undefined,\n failureChain: undefined,\n origin: {\n success: true,\n fee: 17965000n,\n currency: 'PAS',\n asset: {\n symbol: 'PAS',\n isNative: true,\n decimals: 10,\n existentialDeposit: '100000000',\n location: { parents: 1, interior: { Here: null } },\n isFeeAsset: true,\n amount: 100000000000n\n },\n weight: undefined,\n forwardedXcms: [\n {\n type: 'V3',\n value: {\n parents: 1,\n interior: { type: 'X1', value: { type: 'Parachain', value: 1004 } }\n }\n },\n [\n {\n type: 'V3',\n value: [\n {\n type: 'ReceiveTeleportedAsset',\n value: [\n {\n id: {\n type: 'Concrete',\n value: {\n parents: 1,\n interior: { type: 'Here', value: undefined }\n }\n },\n fun: { type: 'Fungible', value: 100000000000n }\n }\n ]\n },\n { type: 'ClearOrigin', value: undefined },\n {\n type: 'BuyExecution',\n value: {\n fees: {\n id: {\n type: 'Concrete',\n value: {\n parents: 1,\n interior: { type: 'Here', value: undefined }\n }\n },\n fun: { type: 'Fungible', value: 100000000000n }\n },\n weight_limit: { type: 'Unlimited', value: undefined }\n }\n },\n {\n type: 'DepositAsset',\n value: {\n assets: {\n type: 'Wild',\n value: { type: 'AllCounted', value: 1 }\n },\n beneficiary: {\n parents: 0,\n interior: {\n type: 'X1',\n value: {\n type: 'AccountId32',\n value: {\n network: undefined,\n id: FixedSizeBinary {\n asText: [Function (anonymous)],\n asHex: [Function (anonymous)],\n asOpaqueHex: [Function (anonymous)],\n asBytes: [Function (anonymous)],\n asOpaqueBytes: [Function (anonymous)]\n }\n }\n }\n }\n }\n }\n },\n {\n type: 'SetTopic',\n value: FixedSizeBinary {\n asText: [Function (anonymous)],\n asHex: [Function (anonymous)],\n asOpaqueHex: [Function (anonymous)],\n asBytes: [Function (anonymous)],\n asOpaqueBytes: [Function (anonymous)]\n }\n }\n ]\n }\n ]\n ],\n destParaId: 1004\n },\n assetHub: undefined,\n bridgeHub: undefined,\n destination: {\n success: true,\n fee: 817598n,\n currency: 'PAS',\n asset: {\n symbol: 'PAS',\n isNative: true,\n decimals: 10,\n existentialDeposit: '1000000000',\n location: { parents: 1, interior: { Here: null } },\n isFeeAsset: true\n },\n weight: { refTime: 176858000n, proofSize: 0n },\n forwardedXcms: [],\n destParaId: undefined\n },\n hops: []\n}\n
    "} -{"page_id": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", "page_title": "Transfer Assets Between Parachains", "index": 5, "depth": 2, "title": "Verify the Existential Deposit", "anchor": "verify-the-existential-deposit", "start_char": 8689, "end_char": 9871, "estimated_token_count": 316, "token_estimator": "heuristic-v1", "text": "## Verify the Existential Deposit\n\nCheck if the recipient account meets the [Existential Deposit (ED)](/polkadot-protocol/glossary/#existential-deposit){target=\\_blank} requirement before sending by using [`verifyEdOnDestination`](https://paraspell.github.io/docs/sdk/xcmUtils.html#verify-ed-on-destination){target=\\_blank}:\n\n```ts title=\"index.ts\"\nasync function verifyED() {\n const isValid = await Builder()\n .from('AssetHubPaseo')\n .to('PeoplePaseo')\n .currency({\n symbol: 'PAS',\n amount: 10n * PAS_UNITS,\n })\n .address(RECIPIENT_ADDRESS)\n .senderAddress(SENDER_ADDRESS)\n .verifyEdOnDestination();\n\n console.log(`ED verification ${isValid ? 'successful' : 'failed'}.`);\n process.exit(0);\n}\n\nverifyED();\n```\nComment out the `dryRunTransfer()` function so that it is not executed again. Then, execute the `verifyED()` by running the following command:\n\n```bash\nnpx tsx index.ts\n```\n\nAfter that, you will get output confirming the ED which will look similar to the following:\n\n
    \n npx tsx index.ts\n ED verification successful.\n
    "} -{"page_id": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", "page_title": "Transfer Assets Between Parachains", "index": 6, "depth": 2, "title": "Get Transfer Info and Fee Estimates", "anchor": "get-transfer-info-and-fee-estimates", "start_char": 9871, "end_char": 26422, "estimated_token_count": 3019, "token_estimator": "heuristic-v1", "text": "## Get Transfer Info and Fee Estimates\n\nBefore sending an XCM transaction, it is helpful to estimate the fees associated with executing and delivering the cross-chain message.\n\nParaSpell has a helpful function for this: [`getTransferInfo()`](https://paraspell.github.io/docs/sdk/xcmUtils.html#xcm-transfer-info){target=\\_blank}. This function returns an estimate of the associated XCM fees, along with the account's balance before and after the fees are paid.\n\n```ts title=\"index.ts\"\nasync function XcmTransferInfo() {\n const info = await Builder()\n .from('AssetHubPaseo')\n .to('PeoplePaseo')\n .currency({\n symbol: 'PAS',\n amount: 10n * PAS_UNITS,\n })\n .address(RECIPIENT_ADDRESS)\n .senderAddress(SENDER_ADDRESS)\n .getTransferInfo();\n\n console.log('Transfer Info:', info);\n process.exit(0);\n}\n\nXcmTransferInfo();\n```\n\nComment out the `verifyED()` function so it doesn't execute again. Then, execute the `XcmTransferInfo()` function by running the following command:\n\n```bash\nnpx tsx index.ts\n```\n\nYou will see all the information for your transfer similar to the following example:\n\n
    \n npx tsx index.ts\n Transfer Info: {\n chain: {\n origin: \"AssetHubPaseo\",\n destination: \"PeoplePaseo\",\n ecosystem: \"PAS\",\n },\n origin: {\n selectedCurrency: {\n sufficient: true,\n balance: 9799197260420n,\n balanceAfter: 9699197260420n,\n currencySymbol: \"PAS\",\n asset: [Object ...],\n existentialDeposit: 100000000n,\n },\n xcmFee: {\n sufficient: true,\n fee: 17965000n,\n balance: 9799197260420n,\n balanceAfter: 9799179295420n,\n currencySymbol: \"PAS\",\n asset: [Object ...],\n },\n },\n assetHub: undefined,\n bridgeHub: undefined,\n hops: [],\n destination: {\n receivedCurrency: {\n sufficient: true,\n receivedAmount: 99999182402n,\n balance: 199998364804n,\n balanceAfter: 299997547206n,\n currencySymbol: \"PAS\",\n asset: [Object ...],\n existentialDeposit: 1000000000n,\n },\n xcmFee: {\n fee: 817598n,\n balance: 199998364804n,\n balanceAfter: 299997547206n,\n currencySymbol: \"PAS\",\n asset: [Object ...],\n },\n },\n}\n
    \nNow that you have:\n\n- Completed a successful dry run of the transaction.\n- Verified the existential deposit on the recipient account.\n- Obtained an estimate of the associated XCM fees.\n\nYou can execute the transfer function by adding the following function call:\n\n```typescript title=\"index.ts\"\ntransfer();\n```\n\nComment out the `XcmTransferInfo()` function so it doesn't execute again. Then, execute the transfer by running the following command: \n\n```bash\nnpx tsx index.ts\n```\n\nYour `transfer` function will submit the transaction, and you will get the following output:\n\n
    \n npx tsx index.ts\n ...\n Built transaction: {\n getPaymentInfo: [AsyncFunction: getPaymentInfo],\n getEstimatedFees: [AsyncFunction: getEstimatedFees],\n decodedCall: {\n type: 'PolkadotXcm',\n value: {\n type: 'limited_teleport_assets',\n value: {\n dest: {\n type: 'V5',\n value: {\n parents: 1,\n interior: { type: 'X1', value: { type: 'Parachain', value: 1004 } }\n }\n },\n beneficiary: {\n type: 'V5',\n value: {\n parents: 0,\n interior: {\n type: 'X1',\n value: {\n type: 'AccountId32',\n value: {\n network: undefined,\n id: FixedSizeBinary {\n asText: [Function (anonymous)],\n asHex: [Function (anonymous)],\n asOpaqueHex: [Function (anonymous)],\n asBytes: [Function (anonymous)],\n asOpaqueBytes: [Function (anonymous)]\n }\n }\n }\n }\n }\n },\n assets: {\n type: 'V5',\n value: [\n {\n id: { parents: 1, interior: { type: 'Here', value: null } },\n fun: { type: 'Fungible', value: 100000000000n }\n }\n ]\n },\n fee_asset_item: 0,\n weight_limit: { type: 'Unlimited' }\n }\n }\n },\n getEncodedData: [Function: getEncodedData],\n sign: [Function: sign],\n signSubmitAndWatch: [Function: signSubmitAndWatch],\n signAndSubmit: [Function: signAndSubmit]\n}\n
    \nOnce the transaction is successfully included in a block, you will see the recipient's account balance updated, and you will receive output similar to the following.\n\n???- code \"Successful Transaction Submission\"\n This output will be returned once the transaction has been successfully included in a block.\n\n
    \n ...\n {\n txHash: '0x6fbecc0b284adcff46ab39872659c2567395c865adef5f8cbea72f25b6042609',\n block: {\n index: 2,\n number: 2524809,\n hash: '0xa39a96d5921402c6e8f67e48b8395d6b21382c72d4d30f8497a0e9f890bc0d4c'\n },\n ok: true,\n events: [\n {\n type: 'Balances',\n value: {\n type: 'Withdraw',\n value: {\n who: '15DMtB5BDCJqw4uZtByTWXGqViAVx7XjRsxWbTH5tfrHLe8j',\n amount: 15668864n\n }\n },\n topics: []\n },\n {\n type: 'Balances',\n value: {\n type: 'Burned',\n value: {\n who: '15DMtB5BDCJqw4uZtByTWXGqViAVx7XjRsxWbTH5tfrHLe8j',\n amount: 100000000000n\n }\n },\n topics: []\n },\n {\n type: 'PolkadotXcm',\n value: {\n type: 'Attempted',\n value: {\n outcome: {\n type: 'Complete',\n value: { used: { ref_time: 190990000n, proof_size: 3593n } }\n }\n }\n },\n topics: []\n },\n {\n type: 'Balances',\n value: {\n type: 'Burned',\n value: {\n who: '15DMtB5BDCJqw4uZtByTWXGqViAVx7XjRsxWbTH5tfrHLe8j',\n amount: 304850000n\n }\n },\n topics: []\n },\n {\n type: 'Balances',\n value: {\n type: 'Minted',\n value: {\n who: '14xmwinmCEz6oRrFdczHKqHgWNMiCysE2KrA4jXXAAM1Eogk',\n amount: 304850000n\n }\n },\n topics: []\n },\n {\n type: 'PolkadotXcm',\n value: {\n type: 'FeesPaid',\n value: {\n paying: {\n parents: 0,\n interior: {\n type: 'X1',\n value: {\n type: 'AccountId32',\n value: {\n network: { type: 'Polkadot', value: undefined },\n id: FixedSizeBinary {\n asText: [Function (anonymous)],\n asHex: [Function (anonymous)],\n asOpaqueHex: [Function (anonymous)],\n asBytes: [Function (anonymous)],\n asOpaqueBytes: [Function (anonymous)]\n }\n }\n }\n }\n },\n fees: [\n {\n id: {\n parents: 1,\n interior: { type: 'Here', value: undefined }\n },\n fun: { type: 'Fungible', value: 304850000n }\n }\n ]\n }\n },\n topics: []\n },\n {\n type: 'XcmpQueue',\n value: {\n type: 'XcmpMessageSent',\n value: {\n message_hash: FixedSizeBinary {\n asText: [Function (anonymous)],\n asHex: [Function (anonymous)],\n asOpaqueHex: [Function (anonymous)],\n asBytes: [Function (anonymous)],\n asOpaqueBytes: [Function (anonymous)]\n }\n }\n },\n topics: []\n },\n {\n type: 'PolkadotXcm',\n value: {\n type: 'Sent',\n value: {\n origin: {\n parents: 0,\n interior: {\n type: 'X1',\n value: {\n type: 'AccountId32',\n value: {\n network: { type: 'Polkadot', value: undefined },\n id: FixedSizeBinary {\n asText: [Function (anonymous)],\n asHex: [Function (anonymous)],\n asOpaqueHex: [Function (anonymous)],\n asBytes: [Function (anonymous)],\n asOpaqueBytes: [Function (anonymous)]\n }\n }\n }\n }\n },\n destination: {\n parents: 1,\n interior: { type: 'X1', value: { type: 'Parachain', value: 1002 } }\n },\n message: [\n {\n type: 'ReceiveTeleportedAsset',\n value: [\n {\n id: {\n parents: 1,\n interior: { type: 'Here', value: undefined }\n },\n fun: { type: 'Fungible', value: 100000000000n }\n }\n ]\n },\n { type: 'ClearOrigin', value: undefined },\n {\n type: 'BuyExecution',\n value: {\n fees: {\n id: {\n parents: 1,\n interior: { type: 'Here', value: undefined }\n },\n fun: { type: 'Fungible', value: 100000000000n }\n },\n weight_limit: { type: 'Unlimited', value: undefined }\n }\n },\n {\n type: 'DepositAsset',\n value: {\n assets: {\n type: 'Wild',\n value: { type: 'AllCounted', value: 1 }\n },\n beneficiary: {\n parents: 0,\n interior: {\n type: 'X1',\n value: {\n type: 'AccountId32',\n value: {\n network: undefined,\n id: FixedSizeBinary {\n asText: [Function (anonymous)],\n asHex: [Function (anonymous)],\n asOpaqueHex: [Function (anonymous)],\n asBytes: [Function (anonymous)],\n asOpaqueBytes: [Function (anonymous)]\n }\n }\n }\n }\n }\n }\n }\n ],\n message_id: FixedSizeBinary {\n asText: [Function (anonymous)],\n asHex: [Function (anonymous)],\n asOpaqueHex: [Function (anonymous)],\n asBytes: [Function (anonymous)],\n asOpaqueBytes: [Function (anonymous)]\n }\n }\n },\n topics: []\n },\n {\n type: 'Balances',\n value: {\n type: 'Deposit',\n value: {\n who: '13UVJyLgBASGhE2ok3TvxUfaQBGUt88JCcdYjHvUhvQkFTTx',\n amount: 15668864n\n }\n },\n topics: []\n },\n {\n type: 'TransactionPayment',\n value: {\n type: 'TransactionFeePaid',\n value: {\n who: '15DMtB5BDCJqw4uZtByTWXGqViAVx7XjRsxWbTH5tfrHLe8j',\n actual_fee: 15668864n,\n tip: 0n\n }\n },\n topics: []\n },\n {\n type: 'System',\n value: {\n type: 'ExtrinsicSuccess',\n value: {\n dispatch_info: {\n weight: { ref_time: 952851000n, proof_size: 13382n },\n class: { type: 'Normal', value: undefined },\n pays_fee: { type: 'Yes', value: undefined }\n }\n }\n },\n topics: []\n }\n ]\n }\n
    \nAfter executing the transfer, check the account balance on [Polkadot.js Apps](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.turboflakes.io%2Fasset-hub-paseo){target=\\_blank} for [Paseo's Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.turboflakes.io%2Fasset-hub-paseo#/accounts){target=\\_blank} and [Paseo's People Chain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.ibp.network%2Fpeople-paseo#/accounts){target=\\_blank}.\n\nYou should see:\n\n- The recipient account now has 10 more PAS tokens.\n- The sender account has the transfer amount (10 PAS) + the fees amount debited from their account balance.\n\nYou have now successfully created and sent a cross-chain transfer using the ParaSpell XCM SDK!\n\n???- code \"Full Code\"\n\n ```typescript title=\"index.ts\"\n import { Builder, hasDryRunSupport } from '@paraspell/sdk';\n import {\n entropyToMiniSecret,\n mnemonicToEntropy,\n ss58Address,\n } from '@polkadot-labs/hdkd-helpers';\n import { getPolkadotSigner } from 'polkadot-api/signer';\n import { sr25519CreateDerive } from '@polkadot-labs/hdkd';\n import { inspect } from 'util';\n\n // PAS token has 10 decimals\n const PAS_UNITS = 10_000_000_000n;\n\n const SEED_PHRASE =\n 'INSERT_YOUR_SEED_PHRASE';\n\n // Create Sr25519 signer from mnemonic\n function getSigner() {\n const entropy = mnemonicToEntropy(SEED_PHRASE);\n const miniSecret = entropyToMiniSecret(entropy);\n const derive = sr25519CreateDerive(miniSecret);\n const keyPair = derive('');\n return getPolkadotSigner(keyPair.publicKey, 'Sr25519', keyPair.sign);\n }\n\n const RECIPIENT_ADDRESS = ss58Address(getSigner().publicKey);\n const SENDER_ADDRESS = ss58Address(getSigner().publicKey);\n\n async function transfer() {\n const signer = getSigner();\n\n const tx = await Builder()\n .from('AssetHubPaseo')\n .to('PeoplePaseo')\n .currency({\n symbol: 'PAS',\n amount: 10n * PAS_UNITS, // 10 PAS\n })\n .address(RECIPIENT_ADDRESS)\n .build();\n\n console.log('Built transaction:', inspect(tx, { colors: true, depth: null }));\n\n const result = await tx.signAndSubmit(signer);\n console.log(inspect(result, { colors: true, depth: null }));\n process.exit(0);\n }\n\n async function dryRunTransfer() {\n if (!hasDryRunSupport('AssetHubPaseo')) {\n console.log('Dry run is not supported on AssetHubPaseo.');\n return;\n }\n\n const tx = await Builder()\n .from('AssetHubPaseo')\n .to('PeoplePaseo')\n .currency({\n symbol: 'PAS',\n amount: 10n * PAS_UNITS,\n })\n .address(RECIPIENT_ADDRESS)\n .senderAddress(SENDER_ADDRESS)\n .dryRun();\n\n console.log(inspect(tx, { colors: true, depth: null }));\n process.exit(0);\n }\n\n dryRunTransfer();\n\n async function verifyED() {\n const isValid = await Builder()\n .from('AssetHubPaseo')\n .to('PeoplePaseo')\n .currency({\n symbol: 'PAS',\n amount: 10n * PAS_UNITS,\n })\n .address(RECIPIENT_ADDRESS)\n .senderAddress(SENDER_ADDRESS)\n .verifyEdOnDestination();\n\n console.log(`ED verification ${isValid ? 'successful' : 'failed'}.`);\n process.exit(0);\n }\n\n verifyED();\n\n async function XcmTransferInfo() {\n const info = await Builder()\n .from('AssetHubPaseo')\n .to('PeoplePaseo')\n .currency({\n symbol: 'PAS',\n amount: 10n * PAS_UNITS,\n })\n .address(RECIPIENT_ADDRESS)\n .senderAddress(SENDER_ADDRESS)\n .getTransferInfo();\n\n console.log('Transfer Info:', info);\n process.exit(0);\n }\n\n XcmTransferInfo();\n\n transfer();\n\n ```"} -{"page_id": "chain-interactions-send-transactions-interoperability-transfer-assets-parachains", "page_title": "Transfer Assets Between Parachains", "index": 7, "depth": 2, "title": "Next Steps", "anchor": "next-steps", "start_char": 26422, "end_char": 26764, "estimated_token_count": 84, "token_estimator": "heuristic-v1", "text": "## Next Steps\n\n- Read the Docs: Dive deeper into the features of the [ParaSpell XCM SDK](https://paraspell.github.io/docs/sdk/getting-started.html){target=\\_blank} documentation.\n\n- Learn about XCM: Understand the underlying protocol by visiting the [Introduction to XCM page](/parachains/interoperability/get-started/) in the Polkadot Docs."} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 66, "end_char": 389, "estimated_token_count": 58, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe Asset Hub provides a powerful feature that allows users to pay transaction fees using alternative tokens instead of the native token of the chain.\n\nThis tutorial demonstrates how to send a DOT transfer transaction while paying the fees using a different token (USDT in this example) on the Asset Hub."} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 1, "depth": 2, "title": "Environment Setup", "anchor": "environment-setup", "start_char": 389, "end_char": 1465, "estimated_token_count": 288, "token_estimator": "heuristic-v1", "text": "## Environment Setup\n\nLet's set up the development environment for this tutorial:\n\n1. Create a new directory and initialize the project:\n\n ```bash\n mkdir fee-payment-tutorial && \\\n cd fee-payment-tutorial\n ```\n\n2. Initialize the project:\n\n ```bash\n npm init -y\n ```\n\n3. Install dev dependencies:\n\n ```bash\n npm install --save-dev @types/node@^22.12.0 ts-node@^10.9.2 typescript@^5.7.3\n ```\n\n4. Install dependencies:\n\n ```bash\n npm install --save @polkadot-labs/hdkd@^0.0.13 @polkadot-labs/hdkd-helpers@^0.0.13 polkadot-api@1.9.5\n ```\n\n5. Create TypeScript configuration:\n\n ```bash\n npx tsc --init && npm pkg set type=module\n ```\n\n The command `npm pkg set type=module` is used to set the type of the project to module. This is necessary to use the `import` statement in the TypeScript code.\n\n6. Generate Polkadot API types for Asset Hub:\n\n ```bash\n npx papi add assetHub -n polkadot_asset_hub\n ```\n\n7. Create a new file called `fee-payment-transaction.ts`:\n\n ```bash\n touch fee-payment-transaction.ts\n ```"} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 2, "depth": 2, "title": "Local Asset Hub Setup", "anchor": "local-asset-hub-setup", "start_char": 1465, "end_char": 2109, "estimated_token_count": 162, "token_estimator": "heuristic-v1", "text": "## Local Asset Hub Setup\n\nBefore running the script, you'll need to fork the Asset Hub locally using Chopsticks:\n\n```bash\nchopsticks -c polkadot-asset-hub\n```\n\nThis command forks the Asset Hub chain, making it available at `ws://localhost:8000`. By running `polkadot-asset-hub`, you're using the Asset Hub fork with the configuration specified in the [`polkadot-asset-hub.yml`](https://github.com/AcalaNetwork/chopsticks/blob/master/configs/polkadot-asset-hub.yml){target=_blank} file. This configuration defines Alice's account with USDT assets. If you want to use a different chain, ensure the account you're using has the necessary assets."} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 3, "depth": 2, "title": "Implementation", "anchor": "implementation", "start_char": 2109, "end_char": 2377, "estimated_token_count": 55, "token_estimator": "heuristic-v1", "text": "## Implementation\n\nIn the following sections, you'll set up imports and constants, create a transaction signer, and connect to the Polkadot Asset Hub chain. Then, you'll create and send a DOT transfer transaction, requesting that fees be paid in USDT instead of DOT."} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 4, "depth": 3, "title": "Import Dependencies", "anchor": "import-dependencies", "start_char": 2377, "end_char": 3041, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "### Import Dependencies\n\nAdd the following imports to your `fee-payment-transaction.ts` file:\n\n```typescript title=\"fee-payment-transaction.ts\"\nimport { sr25519CreateDerive } from \"@polkadot-labs/hdkd\";\nimport {\n DEV_PHRASE,\n entropyToMiniSecret,\n mnemonicToEntropy,\n} from \"@polkadot-labs/hdkd-helpers\";\nimport { getPolkadotSigner } from \"polkadot-api/signer\";\nimport { createClient } from \"polkadot-api\";\nimport { assetHub } from \"@polkadot-api/descriptors\";\nimport { withPolkadotSdkCompat } from \"polkadot-api/polkadot-sdk-compat\";\nimport { getWsProvider } from \"polkadot-api/ws-provider/node\";\nimport { MultiAddress } from \"@polkadot-api/descriptors\";\n```"} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 5, "depth": 3, "title": "Define Constants", "anchor": "define-constants", "start_char": 3041, "end_char": 3329, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "### Define Constants\n\nDefine the constants for your transaction:\n\n```typescript title=\"fee-payment-transaction.ts\"\nconst TARGET_ADDRESS = \"14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3\"; // Bob's address\nconst TRANSFER_AMOUNT = 3_000_000_000n; // 3 DOT\nconst USD_ASSET_ID = 1337;\n```"} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 6, "depth": 3, "title": "Create a Signer", "anchor": "create-a-signer", "start_char": 3329, "end_char": 3900, "estimated_token_count": 117, "token_estimator": "heuristic-v1", "text": "### Create a Signer\n\nCreate a signer using Alice's development account:\n\n```typescript title=\"fee-payment-transaction.ts\"\nconst createSigner = async () => {\n const entropy = mnemonicToEntropy(DEV_PHRASE);\n const miniSecret = entropyToMiniSecret(entropy);\n const derive = sr25519CreateDerive(miniSecret);\n const hdkdKeyPair = derive(\"//Alice\");\n const polkadotSigner = getPolkadotSigner(\n hdkdKeyPair.publicKey,\n \"Sr25519\",\n hdkdKeyPair.sign\n );\n return polkadotSigner;\n};\n```\n\nThis function will return a signer that can be used to sign the transaction."} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 7, "depth": 3, "title": "Setup the Client and API", "anchor": "setup-the-client-and-api", "start_char": 3900, "end_char": 4207, "estimated_token_count": 73, "token_estimator": "heuristic-v1", "text": "### Setup the Client and API\n\nCreate the client connection to the local Asset Hub:\n\n```typescript title=\"fee-payment-transaction.ts\"\nconst client = createClient(\n withPolkadotSdkCompat(\n getWsProvider(\"ws://localhost:8000\") // Chopsticks Asset Hub\n )\n);\n\nconst api = client.getTypedApi(assetHub);\n```"} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 8, "depth": 3, "title": "Create the Transaction", "anchor": "create-the-transaction", "start_char": 4207, "end_char": 4565, "estimated_token_count": 83, "token_estimator": "heuristic-v1", "text": "### Create the Transaction\n\nCreate a standard DOT transfer transaction:\n\n```typescript title=\"fee-payment-transaction.ts\"\nconst tx = api.tx.Balances.transfer_keep_alive({\n dest: MultiAddress.Id(TARGET_ADDRESS),\n value: BigInt(TRANSFER_AMOUNT),\n});\n```\n\nThis creates a transaction that transfers 3 DOT to Bob's address while keeping Alice's account alive."} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 9, "depth": 3, "title": "Sign and Submit with Alternative Fee Payment", "anchor": "sign-and-submit-with-alternative-fee-payment", "start_char": 4565, "end_char": 5515, "estimated_token_count": 270, "token_estimator": "heuristic-v1", "text": "### Sign and Submit with Alternative Fee Payment\n\nThe key part of this tutorial is specifying an alternative asset for fee payment. This is done through the `asset` parameter in the `signAndSubmit` options:\n\n```typescript title=\"fee-payment-transaction.ts\"\nconst signer = await createSigner();\n\nconst result = await tx.signAndSubmit(signer, {\n asset: {\n parents: 0,\n interior: {\n type: \"X2\",\n value: [\n { type: \"PalletInstance\", value: 50 },\n { type: \"GeneralIndex\", value: BigInt(USD_ASSET_ID) },\n ],\n },\n },\n});\n\nconst { txHash, ok, block, events } = result;\nconsole.log(`Tx finalized: ${txHash} (ok=${ok})`);\nconsole.log(`Block: #${block.number} ${block.hash} [tx index ${block.index}]`);\n\nconsole.log(\"Events:\");\nfor (const ev of events) {\n const type = (ev as any).type ?? \"unknown\";\n console.log(`- ${type}`);\n}\n\nprocess.exit(0);\n```\n\nThis specifies that the fees should be paid using the USDT asset."} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 10, "depth": 2, "title": "Full Code", "anchor": "full-code", "start_char": 5515, "end_char": 7890, "estimated_token_count": 523, "token_estimator": "heuristic-v1", "text": "## Full Code\n\nThe full code for the complete implementation is the following:\n\n??? code \"Complete Code\"\n\n ```typescript title=\"fee-payment-transaction.ts\"\n import { sr25519CreateDerive } from \"@polkadot-labs/hdkd\";\n import {\n DEV_PHRASE,\n entropyToMiniSecret,\n mnemonicToEntropy,\n } from \"@polkadot-labs/hdkd-helpers\";\n import { getPolkadotSigner } from \"polkadot-api/signer\";\n import { createClient } from \"polkadot-api\";\n import { assetHub } from \"@polkadot-api/descriptors\";\n import { withPolkadotSdkCompat } from \"polkadot-api/polkadot-sdk-compat\";\n import { getWsProvider } from \"polkadot-api/ws-provider/node\";\n import { MultiAddress } from \"@polkadot-api/descriptors\";\n\n const TARGET_ADDRESS = \"14E5nqKAp3oAJcmzgZhUD2RcptBeUBScxKHgJKU4HPNcKVf3\"; // Bob's address\n const TRANSFER_AMOUNT = 3_000_000_000n; // 3 DOT\n const USD_ASSET_ID = 1337;\n\n const createSigner = async () => {\n const entropy = mnemonicToEntropy(DEV_PHRASE);\n const miniSecret = entropyToMiniSecret(entropy);\n const derive = sr25519CreateDerive(miniSecret);\n const hdkdKeyPair = derive(\"//Alice\");\n const polkadotSigner = getPolkadotSigner(\n hdkdKeyPair.publicKey,\n \"Sr25519\",\n hdkdKeyPair.sign\n );\n return polkadotSigner;\n };\n\n const client = createClient(\n withPolkadotSdkCompat(\n getWsProvider(\"ws://localhost:8000\") // Chopsticks Asset Hub\n )\n );\n\n const api = client.getTypedApi(assetHub);\n\n const tx = api.tx.Balances.transfer_keep_alive({\n dest: MultiAddress.Id(TARGET_ADDRESS),\n value: BigInt(TRANSFER_AMOUNT),\n });\n\n const signer = await createSigner();\n\n const result = await tx.signAndSubmit(signer, {\n asset: {\n parents: 0,\n interior: {\n type: \"X2\",\n value: [\n { type: \"PalletInstance\", value: 50 },\n { type: \"GeneralIndex\", value: BigInt(USD_ASSET_ID) },\n ],\n },\n },\n });\n\n const { txHash, ok, block, events } = result;\n console.log(`Tx finalized: ${txHash} (ok=${ok})`);\n console.log(`Block: #${block.number} ${block.hash} [tx index ${block.index}]`);\n\n console.log(\"Events:\");\n for (const ev of events) {\n const type = (ev as any).type ?? \"unknown\";\n console.log(`- ${type}`);\n }\n\n process.exit(0);\n ```"} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 11, "depth": 2, "title": "Running the Script", "anchor": "running-the-script", "start_char": 7890, "end_char": 7985, "estimated_token_count": 28, "token_estimator": "heuristic-v1", "text": "## Running the Script\n\nTo run the script:\n\n```bash\nnpx ts-node fee-payment-transaction.ts\n```"} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 12, "depth": 2, "title": "Expected Output", "anchor": "expected-output", "start_char": 7985, "end_char": 8853, "estimated_token_count": 196, "token_estimator": "heuristic-v1", "text": "## Expected Output\n\nWhen you run the script successfully, you should see output similar to:\n\n
    \n npx ts-node fee-payment-transaction.ts\n
    \nTx finalized: 0x771956fdf40b3741bdc3c1e981a6daacbe5521877ad1915542e7413bb4a820bc (ok=true)\nBlock: #9645060 0x57710514f168b5c444c8e47b1e1a31dd9e7bc7e9a51d8d25ccdbc6053e159f6b [tx index 2]\nEvents:\n- Assets\n- Balances\n- Assets\n- AssetConversion\n- Balances\n- Balances\n- AssetTxPayment\n- System\n
    \n
    \nThe key events to look for are:\n\n- **Assets**: The asset was transferred.\n- **Balances**: The fees were paid using the alternative asset.\n- **AssetConversion**: The fees were converted to the alternative asset.\n- **AssetTxPayment**: The fees were paid using the alternative asset.\n- **System**: The transaction was successful."} -{"page_id": "chain-interactions-send-transactions-pay-fees-with-different-tokens", "page_title": "Send a Transaction While Paying the Fee with a Different Token", "index": 13, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 8853, "end_char": 9257, "estimated_token_count": 61, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nPaying transaction fees with alternative tokens on Asset Hub provides significant flexibility for users and applications.\n\nThe key takeaway is understanding how to specify alternative assets using the XCM location format, which opens up possibilities for building applications that can operate entirely using specific token ecosystems while still leveraging the full power of the network."} -{"page_id": "chain-interactions-token-operations-convert-assets", "page_title": "Convert Assets on Asset Hub", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 31, "end_char": 613, "estimated_token_count": 137, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nAsset Conversion is an Automated Market Maker (AMM) utilizing [Uniswap V2](https://github.com/Uniswap/v2-core){target=\\_blank} logic and implemented as a pallet on Polkadot's Asset Hub.\n\nThis guide will provide detailed information about the key functionalities offered by the [Asset Conversion](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/asset-conversion){target=\\_blank} pallet on Asset Hub, including:\n\n- Creating a liquidity pool.\n- Adding liquidity to a pool.\n- Swapping assets.\n- Withdrawing liquidity from a pool."} -{"page_id": "chain-interactions-token-operations-convert-assets", "page_title": "Convert Assets on Asset Hub", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 613, "end_char": 1321, "estimated_token_count": 169, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore converting assets on Asset Hub, you must ensure you have:\n\n- Access to the [Polkadot.js Apps](https://polkadot.js.org/apps){target=\\_blank} interface and a connection with the intended blockchain.\n- A funded wallet containing the assets you wish to convert and enough available funds to cover the transaction fees.\n- An asset registered on Asset Hub that you want to convert. If you haven't created an asset on Asset Hub yet, refer to the [Register a Local Asset](/chain-interactions/token-operations/register-local-asset/){target=\\_blank} or [Register a Foreign Asset](/chain-interactions/token-operations/register-foreign-asset/){target=\\_blank} documentation to create an asset."} -{"page_id": "chain-interactions-token-operations-convert-assets", "page_title": "Convert Assets on Asset Hub", "index": 2, "depth": 2, "title": "Create a Liquidity Pool", "anchor": "create-a-liquidity-pool", "start_char": 1321, "end_char": 4337, "estimated_token_count": 687, "token_estimator": "heuristic-v1", "text": "## Create a Liquidity Pool\n\nIf an asset on Asset Hub does not have an existing liquidity pool, the first step is to create one.\n\nThe asset conversion pallet provides the `createPool` extrinsic to create a new liquidity pool, creating an empty liquidity pool and a new `LP token` asset.\n\n!!! tip\n A testing token with the asset ID `1112` and the name `PPM` was created for this example.\n\nAs stated in the [Test Environment Setup](#test-environment-setup) section, this tutorial is based on the assumption that you have an instance of Polkadot Asset Hub running locally. Therefore, the demo liquidity pool will be created between DOT and PPM tokens. However, the same steps can be applied to any other asset on Asset Hub.\n\nFrom the Asset Hub perspective, the Multilocation that identifies the PPM token is the following:\n\n```javascript\n{\n parents: 0,\n interior: {\n X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]\n }\n}\n```\n\nThe `PalletInstance` value of `50` represents the Assets pallet on Asset Hub. The `GeneralIndex` value of `1112` is the PPM asset's asset ID.\n\nTo create the liquidity pool, you can follow these steps:\n\n1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:\n\n 1. Select **Developer** from the top menu.\n 2. Click on **Extrinsics** from the dropdown menu.\n\n ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)\n\n2. Select extrinsic to create the pool:\n\n 1. Select the **`AssetConversion`** pallet.\n 2. Choose the **`createPool`** extrinsic from the list of available extrinsics.\n\n ![Create Pool Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-02.webp)\n\n3. Fill in the required fields:\n\n 1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents.\n\n ```javascript\n {\n parents: 0,\n interior: 'Here'\n }\n ```\n\n 2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies.\n\n ```javascript\n {\n parents: 0,\n interior: {\n X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]\n }\n }\n ```\n\n 3. Click on **Submit Transaction** to create the liquidity pool.\n\n ![Create Pool Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-03.webp)\n\nSigning and submitting the transaction triggers the creation of the liquidity pool. To verify the new pool's creation, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`PoolCreated`** event was emitted.\n\n![Pool Created Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-04.webp)\n\nAs the preceding image shows, the **`lpToken`** ID created for this pool is 19. This ID is essential to identify the liquidity pool and associated LP tokens."} -{"page_id": "chain-interactions-token-operations-convert-assets", "page_title": "Convert Assets on Asset Hub", "index": 3, "depth": 2, "title": "Add Liquidity to a Pool", "anchor": "add-liquidity-to-a-pool", "start_char": 4337, "end_char": 7492, "estimated_token_count": 690, "token_estimator": "heuristic-v1", "text": "## Add Liquidity to a Pool\n\nThe `addLiquidity` extrinsic allows users to provide liquidity to a pool of two assets. Users specify their preferred amounts for both assets and minimum acceptable quantities. The function determines the best asset contribution, which may vary from the amounts desired but won't fall below the specified minimums. Providers receive liquidity tokens representing their pool portion in return for their contribution.\n\nTo add liquidity to a pool, follow these steps:\n\n1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:\n\n 1. Select **Developer** from the top menu.\n 2. Click on **Extrinsics** from the dropdown menu.\n\n ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)\n\n2. Select extrinsic to add liqudity:\n\n 1. Select the **`assetConversion`** pallet.\n 2. Choose the **`addLiquidity`** extrinsic from the list of available extrinsics.\n\n ![Add Liquidity Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-05.webp)\n\n3. Fill in the required fields:\n\n 1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents.\n\n ```javascript\n {\n parents: 0,\n interior: 'Here'\n }\n ```\n\n 2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies.\n\n ```javascript\n {\n parents: 0,\n interior: {\n X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]\n }\n }\n ```\n\n 3. **`amount1Desired`**: The amount of the first asset that will be contributed to the pool.\n 4. **`amount2Desired`**: The quantity of the second asset intended for pool contribution.\n 5. **`amount1Min`**: The minimum amount of the first asset that will be contributed.\n 6. **`amount2Min`**: The lowest acceptable quantity of the second asset for contribution.\n 7. **`mintTo`**: The account to which the liquidity tokens will be minted.\n 8. Click on **Submit Transaction** to add liquidity to the pool.\n\n ![Add Liquidity Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-06.webp)\n\n !!! warning\n Ensure that the appropriate amount of tokens provided has been minted previously and is available in your account before adding liquidity to the pool.\n\n In this case, the liquidity provided to the pool is between DOT tokens and PPM tokens with the asset ID 1112 on Polkadot Asset Hub. The intention is to provide liquidity for 1 DOT token (`u128` value of 1000000000000 as it has 10 decimals) and 1 PPM token (`u128` value of 1000000000000 as it also has 10 decimals).\n\nSigning and submitting the transaction adds liquidity to the pool. To verify the liquidity addition, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`LiquidityAdded`** event was emitted.\n\n![Liquidity Added Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-07.webp)"} -{"page_id": "chain-interactions-token-operations-convert-assets", "page_title": "Convert Assets on Asset Hub", "index": 4, "depth": 2, "title": "Swap Assets", "anchor": "swap-assets", "start_char": 7492, "end_char": 7508, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Swap Assets"} -{"page_id": "chain-interactions-token-operations-convert-assets", "page_title": "Convert Assets on Asset Hub", "index": 5, "depth": 3, "title": "Swap from an Exact Amount of Tokens", "anchor": "swap-from-an-exact-amount-of-tokens", "start_char": 7508, "end_char": 10879, "estimated_token_count": 722, "token_estimator": "heuristic-v1", "text": "### Swap from an Exact Amount of Tokens\n\nThe asset conversion pallet enables users to exchange a specific quantity of one asset for another in a designated liquidity pool by swapping them for an exact amount of tokens. It guarantees the user will receive at least a predetermined minimum amount of the second asset. This function increases trading predictability and allows users to conduct asset exchanges with confidence that they are assured a minimum return.\n\nTo swap assets for an exact amount of tokens, follow these steps:\n\n1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:\n\n 1. Select **Developer** from the top menu.\n 2. Click on **Extrinsics** from the dropdown menu.\n\n ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)\n\n2. Select extrinsic to swap assets:\n\n 1. Select the **`AssetConversion`** pallet.\n 2. Choose the **`swapExactTokensForTokens`** extrinsic from the list of available extrinsics.\n\n ![Swap From Exact Tokens Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-08.webp)\n\n3. Fill in the required fields:\n\n 1. **`path: Vec`**: An array of Multilocations representing the path of the swap. The first and last elements of the array are the input and output assets, respectively. In this case, the path consists of two elements:\n\n - **`0: StagingXcmV3MultiLocation`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents.\n\n ```javascript\n {\n parents: 0,\n interior: 'Here'\n }\n ```\n\n - **`1: StagingXcmV3MultiLocation`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies.\n\n ```javascript\n {\n parents: 0,\n interior: {\n X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]\n }\n }\n ```\n\n 2. **`amountOut`**: The exact amount of the second asset that the user wants to receive.\n 3. **`amountInMax`**: The maximum amount of the first asset that the user is willing to swap.\n 4. **`sendTo`**: The account to which the swapped assets will be sent.\n 5. **`keepAlive`**: A boolean value that determines whether the pool should be kept alive after the swap.\n 6. Click on **Submit Transaction** to swap assets for an exact amount of tokens.\n\n ![Swap For Exact Tokens Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-09.webp)\n\n !!! warning\n Ensure that the appropriate amount of tokens provided has been minted previously and is available in your account before adding liquidity to the pool.\n\n In this case, the intention is to swap 0.01 DOT token (u128 value of 100000000000 as it has 10 decimals) for 0.04 PPM token (u128 value of 400000000000 as it also has 10 decimals).\n\nSigning and submitting the transaction will execute the swap. To verify execution, check the **Explorer** section on the Polkadot.js Apps interface and make sure that the **`SwapExecuted`** event was emitted.\n\n![Swap From Exact Tokens Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-10.webp)"} -{"page_id": "chain-interactions-token-operations-convert-assets", "page_title": "Convert Assets on Asset Hub", "index": 6, "depth": 3, "title": "Swap to an Exact Amount of Tokens", "anchor": "swap-to-an-exact-amount-of-tokens", "start_char": 10879, "end_char": 14189, "estimated_token_count": 721, "token_estimator": "heuristic-v1", "text": "### Swap to an Exact Amount of Tokens\n\nConversely, the Asset Conversion pallet comes with a function that allows users to trade a variable amount of one asset to acquire a precise quantity of another. It ensures that users stay within a set maximum of the initial asset to obtain the desired amount of the second asset. This provides a method to control transaction costs while achieving the intended result.\n\nTo swap assets for an exact amount of tokens, follow these steps:\n\n1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:\n\n 1. Select **Developer** from the top menu.\n 2. Click on **Extrinsics** from the dropdown menu.\n\n ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)\n\n2. Select extrinsic to swap tokens:\n\n 1. Select the **`AssetConversion`** pallet.\n 2. Choose the **`swapTokensForExactTokens`** extrinsic from the list of available extrinsics.\n\n ![Swap Tokens For Exact Tokens Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-11.webp)\n\n3. Fill in the required fields:\n\n 1. **`path: Vec`**: An array of Multilocations representing the path of the swap. The first and last elements of the array are the input and output assets, respectively. In this case, the path consists of two elements:\n - **`0: StagingXcmV3MultiLocation`**: The Multilocation of the first asset in the pool. In this case, it is the PPM token, which the following Multilocation represents.\n\n ```javascript\n {\n parents: 0,\n interior: {\n X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]\n }\n }\n ```\n\n - **`1: StagingXcmV3MultiLocation`**: The second asset's Multilocation within the pool. This refers to the DOT token, which the following Multilocation identifies.\n\n ```javascript\n {\n parents: 0,\n interior: 'Here'\n }\n ```\n\n 2. **`amountOut`**: The exact amount of the second asset that the user wants to receive.\n 3. **`amountInMax`**: The maximum amount of the first asset that the user is willing to swap.\n 4. **`sendTo`**: The account to which the swapped assets will be sent.\n 5. **`keepAlive`**: A boolean value that determines whether the pool should be kept alive after the swap.\n 6. Click on **Submit Transaction** to swap assets for an exact amount of tokens.\n\n ![Swap Tokens For Exact Tokens Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-12.webp)\n\n !!! warning\n Before swapping assets, ensure that the tokens provided have been minted previously and are available in your account.\n\n In this case, the intention is to swap 0.01 DOT token (`u128` value of 100000000000 as it has ten decimals) for 0.04 PPM token (`u128` value of 400000000000 as it also has ten decimals).\n\nSigning and submitting the transaction will execute the swap. To verify execution, check the **Explorer** section on the Polkadot.js Apps interface and make sure that the **`SwapExecuted`** event was emitted.\n\n![Swap Tokens For Exact Tokens Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-13.webp)"} -{"page_id": "chain-interactions-token-operations-convert-assets", "page_title": "Convert Assets on Asset Hub", "index": 7, "depth": 2, "title": "Withdraw Liquidity from a Pool", "anchor": "withdraw-liquidity-from-a-pool", "start_char": 14189, "end_char": 17403, "estimated_token_count": 691, "token_estimator": "heuristic-v1", "text": "## Withdraw Liquidity from a Pool\n\nThe Asset Conversion pallet provides the `removeLiquidity` extrinsic to remove liquidity from a pool. This function allows users to withdraw the liquidity they offered from a pool, returning the original assets. When calling this function, users specify the number of liquidity tokens (representing their share in the pool) they wish to burn. They also set minimum acceptable amounts for the assets they expect to receive back. This mechanism ensures that users can control the minimum value they receive, protecting against unfavorable price movements during the withdrawal process.\n\nTo withdraw liquidity from a pool, follow these steps:\n\n1. Navigate to the **Extrinsics** section on the Polkadot.js Apps interface:\n\n 1. Select **Developer** from the top menu.\n 2. Click on **Extrinsics** from the dropdown menu.\n\n ![Extrinsics Section](/images/chain-interactions/token-operations/convert-assets/convert-assets-01.webp)\n\n2. Select extrinsic to withdraw liqudity from a pool:\n\n 1. Select the **`AssetConversion`** pallet.\n 2. Choose the **`removeLiquidity`** extrinsic from the list of available extrinsics.\n\n ![Remove Liquidity Extrinsic](/images/chain-interactions/token-operations/convert-assets/convert-assets-14.webp)\n\n3. Fill in the required fields:\n\n 1. **`asset1`**: The Multilocation of the first asset in the pool. In this case, it is the DOT token, which the following Multilocation represents.\n\n ```javascript\n {\n parents: 0,\n interior: 'Here'\n }\n ```\n\n 2. **`asset2`**: The second asset's Multilocation within the pool. This refers to the PPM token, which the following Multilocation identifies.\n\n ```javascript\n {\n parents: 0,\n interior: {\n X2: [{ PalletInstance: 50 }, { GeneralIndex: 1112 }]\n }\n }\n ```\n\n 3. **`lpTokenBurn`**: The number of liquidity tokens to burn.\n 4. **`amount1MinReceived`**: The minimum amount of the first asset that the user expects to receive.\n 5. **`amount2MinReceived`**: The minimum quantity of the second asset the user expects to receive.\n 6. **`withdrawTo`**: The account to which the withdrawn assets will be sent.\n 7. Click on **Submit Transaction** to withdraw liquidity from the pool.\n\n ![Remove Liquidity Fields](/images/chain-interactions/token-operations/convert-assets/convert-assets-15.webp)\n\n !!! warning\n Ensure that the tokens provided have been minted previously and are available in your account before withdrawing liquidity from the pool.\n\n In this case, the intention is to withdraw 0.05 liquidity tokens from the pool, expecting to receive 0.004 DOT token (`u128` value of 40000000000 as it has 10 decimals) and 0.04 PPM token (`u128` value of 400000000000 as it also has 10 decimals).\n\nSigning and submitting the transaction will initiate the withdrawal of liquidity from the pool. To verify the withdrawal, check the **Explorer** section on the Polkadot.js Apps interface and ensure that the **`LiquidityRemoved`** event was emitted.\n\n![Remove Liquidity Event](/images/chain-interactions/token-operations/convert-assets/convert-assets-16.webp)"} -{"page_id": "chain-interactions-token-operations-convert-assets", "page_title": "Convert Assets on Asset Hub", "index": 8, "depth": 2, "title": "Test Environment Setup", "anchor": "test-environment-setup", "start_char": 17403, "end_char": 18507, "estimated_token_count": 242, "token_estimator": "heuristic-v1", "text": "## Test Environment Setup\n\nTo test the Asset Conversion pallet, you can set up a local test environment to simulate different scenarios. This guide uses Chopsticks to spin up an instance of Polkadot Asset Hub. For further details on using Chopsticks, please refer to the [Chopsticks documentation](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\\_blank}.\n\nTo set up a local test environment, execute the following command:\n\n```bash\nnpx @acala-network/chopsticks \\\n--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml\n```\n\nThis command initiates a lazy fork of Polkadot Asset Hub, including the most recent block information from the network. For Kusama Asset Hub testing, simply switch out `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command.\n\nYou now have a local Asset Hub instance up and running, ready for you to test various asset conversion procedures. The process here mirrors what you'd do on MainNet. After completing a transaction on TestNet, you can apply the same steps to convert assets on MainNet."} -{"page_id": "chain-interactions-token-operations-register-foreign-asset", "page_title": "Register a Foreign Asset on Asset Hub", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 41, "end_char": 1111, "estimated_token_count": 234, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nAs outlined in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\\_blank}, Asset Hub supports two categories of assets: local and foreign. Local assets are created on the Asset Hub system parachain and are identified by integer IDs. On the other hand, foreign assets, which originate outside of Asset Hub, are recognized by [Multilocations](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\\_blank}.\n\nWhen registering a foreign asset on Asset Hub, it's essential to notice that the process involves communication between two parachains. The Asset Hub parachain will be the destination of the foreign asset, while the source parachain will be the origin of the asset. The communication between the two parachains is facilitated by the [Cross-Chain Message Passing (XCMP)](/parachains/interoperability/get-started/){target=\\_blank} protocol.\n\nThis guide will take you through the process of registering a foreign asset on the Asset Hub parachain."} -{"page_id": "chain-interactions-token-operations-register-foreign-asset", "page_title": "Register a Foreign Asset on Asset Hub", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 1111, "end_char": 2805, "estimated_token_count": 472, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nThe Asset Hub parachain is one of the system parachains on a relay chain, such as [Polkadot](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpolkadot.api.onfinality.io%2Fpublic-ws#/explorer){target=\\_blank} or [Kusama](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fkusama.api.onfinality.io%2Fpublic-ws#/explorer){target=\\_blank}. To interact with these parachains, you can use the [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} interface for:\n\n- [Polkadot Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/explorer){target=\\_blank}\n- [Kusama Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fsys.ibp.network%2Fstatemine#/explorer){target=\\_blank}\n\nFor testing purposes, you can also interact with the Asset Hub instance on the following test networks:\n\n- [Paseo Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fpas-rpc.stakeworld.io%2Fassethub#/explorer){target=\\_blank}\n\nBefore you start, ensure that you have: \n\n- Access to the Polkadot.js Apps interface, and you are connected to the desired chain.\n- A parachain that supports the XCMP protocol to interact with the Asset Hub parachain.\n- A funded wallet to pay for the transaction fees and subsequent registration of the foreign asset.\n\nThis guide will use Polkadot, its local Asset Hub instance, and the [Astar](https://astar.network/){target=\\_blank} parachain (`ID` 2006), as stated in the [Test Environment Setup](#test-environment-setup) section. However, the process is the same for other relay chains and their respective Asset Hub parachain, regardless of the network you are using and the parachain owner of the foreign asset."} -{"page_id": "chain-interactions-token-operations-register-foreign-asset", "page_title": "Register a Foreign Asset on Asset Hub", "index": 2, "depth": 2, "title": "Steps to Register a Foreign Asset", "anchor": "steps-to-register-a-foreign-asset", "start_char": 2805, "end_char": 2843, "estimated_token_count": 8, "token_estimator": "heuristic-v1", "text": "## Steps to Register a Foreign Asset"} -{"page_id": "chain-interactions-token-operations-register-foreign-asset", "page_title": "Register a Foreign Asset on Asset Hub", "index": 3, "depth": 3, "title": "Asset Hub", "anchor": "asset-hub", "start_char": 2843, "end_char": 5911, "estimated_token_count": 701, "token_estimator": "heuristic-v1", "text": "### Asset Hub\n\n1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner.\n\n - Testing foreign asset registration is recommended on TestNet before proceeding to MainNet. If you haven't set up a local testing environment yet, consult the [Environment setup](#test-environment-setup) guide. After setting up, connect to the Local Node (Chopsticks) at `ws://127.0.0.1:8000`.\n - For live network operations, connect to the Asset Hub parachain. You can choose either Polkadot or Kusama Asset Hub from the dropdown menu, selecting your preferred RPC provider.\n\n2. Navigate to the **Extrinsics** page:\n\n 1. Click on the **Developer** tab from the top navigation bar.\n 2. Select **Extrinsics** from the dropdown.\n\n ![Access to Developer Extrinsics section](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-01.webp)\n\n3. Select the Foreign Assets pallet:\n\n 3. Select the **`foreignAssets`** pallet from the dropdown list.\n 4. Choose the **`create`** extrinsic.\n\n ![Select the Foreign Asset pallet](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-02.webp)\n\n3. Fill out the required fields and click on the copy icon to copy the **encoded call data** to your clipboard. The fields to be filled are:\n\n - **id**: As this is a foreign asset, the ID will be represented by a Multilocation that reflects its origin. For this case, the Multilocation of the asset will be from the source parachain perspective.\n \n ```javascript\n { parents: 1, interior: { X1: [{ Parachain: 2006 }] } }\n ```\n\n - **admin**: Refers to the account that will be the admin of this asset. This account will be able to manage the asset, including updating its metadata. As the registered asset corresponds to a native asset of the source parachain, the admin account should be the sovereign account of the source parachain.\n \n The sovereign account can be obtained through [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/){target=\\_blank}.\n\n Ensure that **Sibling** is selected and that the **Para ID** corresponds to the source parachain. In this case, since the guide follows the test setup stated in the [Test Environment Setup](#test-environment-setup) section, the **Para ID** is `2006`.\n\n ![Get parachain sovereign account](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-03.webp)\n\n\n - **`minBalance`**: The minimum balance required to hold this asset.\n\n ![Fill out the required fields](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-04.webp)\n\n !!! tip \n If you need an example of the encoded call data, you can copy the following:\n ```\n 0x3500010100591f007369626cd6070000000000000000000000000000000000000000000000000000a0860100000000000000000000000000\n ```"} -{"page_id": "chain-interactions-token-operations-register-foreign-asset", "page_title": "Register a Foreign Asset on Asset Hub", "index": 4, "depth": 3, "title": "Source Parachain", "anchor": "source-parachain", "start_char": 5911, "end_char": 7553, "estimated_token_count": 297, "token_estimator": "heuristic-v1", "text": "### Source Parachain\n\n1. Navigate to the **Developer > Extrinsics** section.\n2. Create the extrinsic to register the foreign asset through XCM:\n\n 1. Paste the **encoded call data** copied in the previous step.\n 2. Click the **Submit Transaction** button.\n\n ![Register foreign asset through XCM](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-05.webp)\n\n This XCM call involves withdrawing DOT from the sibling account of the parachain, using it to initiate an execution. The transaction will be carried out with XCM as the origin kind, and will be a hex-encoded call to create a foreign asset on Asset Hub for the specified parachain asset multilocation. Any surplus will be refunded, and the asset will be deposited into the sibling account.\n\n !!! warning\n Note that the sovereign account on the Asset Hub parachain must have a sufficient balance to cover the XCM `BuyExecution` instruction. If the account does not have enough balance, the transaction will fail.\n\n If you want to have the whole XCM call ready to be copied, go to the **Developer > Extrinsics > Decode** section and paste the following hex-encoded call data:\n\n ```text\n 0x6300330003010100a10f030c000400010000070010a5d4e81300010000070010a5d4e80006030700b4f13501419ce03500010100591f007369626cd607000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n ```\n\n Be sure to replace the encoded call data with the one you copied in the previous step.\n\nAfter the transaction is successfully executed, the foreign asset will be registered on the Asset Hub parachain."} -{"page_id": "chain-interactions-token-operations-register-foreign-asset", "page_title": "Register a Foreign Asset on Asset Hub", "index": 5, "depth": 2, "title": "Asset Registration Verification", "anchor": "asset-registration-verification", "start_char": 7553, "end_char": 8100, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "## Asset Registration Verification\n\nTo confirm that a foreign asset has been successfully accepted and registered on the Asset Hub parachain, you can navigate to the `Network > Explorer` section of the Polkadot.js Apps interface for Asset Hub. You should be able to see an event that includes the following details:\n\n![Asset registration event](/images/chain-interactions/token-operations/register-foreign-asset/register-a-foreign-asset-06.webp)\n\nIn the image above, the **success** field indicates whether the asset registration was successful."} -{"page_id": "chain-interactions-token-operations-register-foreign-asset", "page_title": "Register a Foreign Asset on Asset Hub", "index": 6, "depth": 2, "title": "Test Environment Setup", "anchor": "test-environment-setup", "start_char": 8100, "end_char": 9757, "estimated_token_count": 398, "token_estimator": "heuristic-v1", "text": "## Test Environment Setup\n\nTo test the foreign asset registration process before deploying it on a live network, you can set up a local parachain environment. This guide uses Chopsticks to simulate that process. For more information on using Chopsticks, please refer to the [Chopsticks documentation](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\\_blank}.\n\nTo set up a test environment, run the following command:\n\n```bash\nnpx @acala-network/chopsticks xcm \\\n--r polkadot \\\n--p polkadot-asset-hub \\\n--p astar\n```\n\nThe preceding command will create a lazy fork of Polkadot as the relay chain, its Asset Hub instance, and the Astar parachain. The `xcm` parameter enables communication through the XCMP protocol between the relay chain and the parachains, allowing the registration of foreign assets on Asset Hub. For further information on the chopsticks usage of the XCMP protocol, refer to the [XCM Testing](/tutorials/polkadot-sdk/testing/fork-live-chains/#xcm-testing){target=\\_blank} section of the Chopsticks documentation.\n\nAfter executing the command, the terminal will display output indicating the Polkadot relay chain, the Polkadot Asset Hub, and the Astar parachain are running locally and connected through XCM. You can access them individually via the Polkadot.js Apps interface.\n\n- [Polkadot Relay Chain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8002#/explorer){target=\\_blank}\n- [Polkadot Asset Hub](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8000#/explorer){target=\\_blank}\n- [Astar Parachain](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Flocalhost%3A8001#/explorer){target=\\_blank}"} -{"page_id": "chain-interactions-token-operations-register-local-asset", "page_title": "Register a Local Asset", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 39, "end_char": 541, "estimated_token_count": 104, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nAs detailed in the [Asset Hub Overview](/polkadot-protocol/architecture/system-chains/asset-hub){target=\\_blank} page, Asset Hub accommodates two types of assets: local and foreign. Local assets are those that were created in Asset Hub and are identifiable by an integer ID. On the other hand, foreign assets originate from a sibling parachain and are identified by a Multilocation.\n\nThis guide will take you through the steps of registering a local asset on the Asset Hub parachain."} -{"page_id": "chain-interactions-token-operations-register-local-asset", "page_title": "Register a Local Asset", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 541, "end_char": 1097, "estimated_token_count": 130, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have access to the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\\_blank} interface and a funded wallet with DOT or KSM.\n\n- For Polkadot Asset Hub, you would need a deposit of 10 DOT and around 0.201 DOT for the metadata.\n- For Kusama Asset Hub, the deposit is 0.1 KSM and around 0.000669 KSM for the metadata.\n\nYou need to ensure that your Asset Hub account balance is a bit more than the sum of those two deposits, which should seamlessly account for the required deposits and transaction fees."} -{"page_id": "chain-interactions-token-operations-register-local-asset", "page_title": "Register a Local Asset", "index": 2, "depth": 2, "title": "Steps to Register a Local Asset", "anchor": "steps-to-register-a-local-asset", "start_char": 1097, "end_char": 4321, "estimated_token_count": 802, "token_estimator": "heuristic-v1", "text": "## Steps to Register a Local Asset\n\nTo register a local asset on the Asset Hub parachain, follow these steps:\n\n1. Open the [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\\_blank} interface and connect to the Asset Hub parachain using the network selector in the top left corner.\n\n - You may prefer to test local asset registration on TestNet before registering the asset on a MainNet hub. If you still need to set up a local testing environment, review the [Environment setup](#test-setup-environment) section for instructions. Once the local environment is set up, connect to the Local Node (Chopsticks) available on `ws://127.0.0.1:8000`.\n - For the live network, connect to the **Asset Hub** parachain. Either Polkadot or Kusama Asset Hub can be selected from the dropdown list, choosing the desired RPC provider.\n\n2. Click on the **Network** tab on the top navigation bar and select **Assets** from the dropdown list.\n\n ![Access to Asset Hub through Polkadot.JS](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-01.webp)\n\n3. Now, you need to examine all the registered asset IDs. This step is crucial to ensure that the asset ID you are about to register is unique. Asset IDs are displayed in the **assets** column.\n\n ![Asset IDs on Asset Hub](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-02.webp)\n\n4. Once you have confirmed that the asset ID is unique, click on the **Create** button on the top right corner of the page.\n\n ![Create a new asset](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-03.webp)\n\n5. Fill in the required fields in the **Create Asset** form:\n\n 1. **creator account**: The account to be used for creating this asset and setting up the initial metadata.\n 2. **asset name**: The descriptive name of the asset you are registering.\n 3. **asset symbol**: The symbol that will be used to represent the asset.\n 4. **asset decimals**: The number of decimal places for this token, with a maximum of 20 allowed through the user interface.\n 5. **minimum balance**: The minimum balance for the asset. This is specified in the units and decimals as requested.\n 6. **asset ID**: The selected id for the asset. This should not match an already-existing asset id.\n 7. Click on the **Next** button.\n \n ![Create Asset Form](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-04.webp)\n\n6. Choose the accounts for the roles listed below:\n\n 1. **admin account**: The account designated for continuous administration of the token.\n 2. **issuer account**: The account that will be used for issuing this token.\n 3. **freezer account**: The account that will be used for performing token freezing operations.\n 4. Click on the **Create** button.\n\n ![Admin, Issuer, Freezer accounts](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-05.webp)\n\n7. Click on the **Sign and Submit** button to complete the asset registration process.\n\n ![Sign and Submit](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-06.webp)"} -{"page_id": "chain-interactions-token-operations-register-local-asset", "page_title": "Register a Local Asset", "index": 3, "depth": 2, "title": "Verify Asset Registration", "anchor": "verify-asset-registration", "start_char": 4321, "end_char": 5247, "estimated_token_count": 247, "token_estimator": "heuristic-v1", "text": "## Verify Asset Registration\n\nAfter completing these steps, the asset will be successfully registered. You can now view your asset listed on the [**Assets**](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fasset-hub-polkadot-rpc.dwellir.com#/assets){target=\\_blank} section of the Polkadot.js Apps interface.\n\n![Asset listed on Polkadot.js Apps](/images/chain-interactions/token-operations/register-local-asset/register-a-local-asset-07.webp)\n\n!!! tip\n Take into consideration that the **Assets** section’s link may differ depending on the network you are using. For the local environment, enter `ws://127.0.0.1:8000` into the **Custom Endpoint** field.\n\nIn this way, you have successfully registered a local asset on the Asset Hub parachain.\n\nFor an in-depth explanation about Asset Hub and its features, see the [Asset Hub](/chain-interactions/token-operations/convert-assets/){target=\\_blank} entry in the Polkadot Wiki."} -{"page_id": "chain-interactions-token-operations-register-local-asset", "page_title": "Register a Local Asset", "index": 4, "depth": 2, "title": "Test Setup Environment", "anchor": "test-setup-environment", "start_char": 5247, "end_char": 6355, "estimated_token_count": 240, "token_estimator": "heuristic-v1", "text": "## Test Setup Environment\n\nYou can set up a local parachain environment to test the asset registration process before deploying it on the live network. This guide uses Chopsticks to simulate that process. For further information on chopsticks usage, refer to the [Chopsticks](/develop/toolkit/parachains/fork-chains/chopsticks/get-started){target=\\_blank} documentation.\n\nTo set up a test environment, execute the following command:\n\n```bash\nnpx @acala-network/chopsticks \\\n--config=https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/polkadot-asset-hub.yml\n```\n\nThe above command will spawn a lazy fork of Polkadot Asset Hub with the latest block data from the network. If you need to test Kusama Asset Hub, replace `polkadot-asset-hub.yml` with `kusama-asset-hub.yml` in the command.\n\nAn Asset Hub instance is now running locally, and you can proceed with the asset registration process. Note that the local registration process does not differ from the live network process. Once you have a successful TestNet transaction, you can use the same steps to register the asset on MainNet."} -{"page_id": "chain-interactions", "page_title": "Chain Interactions Overview", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 22, "end_char": 995, "estimated_token_count": 166, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nChain interactions form the foundation of building applications on Polkadot. Whether you're querying on-chain data, executing transactions, enabling cross-chain communication, or managing accounts, understanding how to interact with Polkadot-based chains is essential for application developers.\n\nThis section provides comprehensive guidance on the various ways to interact with Polkadot chains, from basic queries to complex cross-chain operations. You'll learn how to:\n\n- Query on-chain state and subscribe to blockchain events.\n- Send transactions and manage their lifecycle.\n- Enable interoperability between parachains through XCM.\n- Manage tokens and perform token operations.\n- Create and manage accounts programmatically.\n\nWhether you're building a frontend application, a backend service, or integrating with the Polkadot ecosystem, these guides will equip you with the knowledge and tools to effectively interact with chains across the network."} -{"page_id": "chain-interactions", "page_title": "Chain Interactions Overview", "index": 1, "depth": 2, "title": "Core Interaction Patterns", "anchor": "core-interaction-patterns", "start_char": 995, "end_char": 1025, "estimated_token_count": 5, "token_estimator": "heuristic-v1", "text": "## Core Interaction Patterns"} -{"page_id": "chain-interactions", "page_title": "Chain Interactions Overview", "index": 2, "depth": 3, "title": "Query On-Chain Data", "anchor": "query-on-chain-data", "start_char": 1025, "end_char": 1898, "estimated_token_count": 223, "token_estimator": "heuristic-v1", "text": "### Query On-Chain Data\n\nAccessing blockchain state is fundamental to building responsive applications. Polkadot offers several methods to query on-chain data, each suited for different use cases.\n\n- **[SDK integration](/chain-interactions/query-data/query-sdks/)**: Programmatically read blockchain state using:\n\n - [Polkadot API (PAPI)](/reference/tools/papi/)\n - [Polkadot.js](/reference/tools/polkadot-js-api/)\n - [Dedot](/reference/tools/dedot/)\n - [Python Substrate Interface](/reference/tools/py-substrate-interface/)\n - [Subxt](/reference/tools/subxt/)\n\n- **[REST API access](/chain-interactions/query-data/query-rest/)**: Query chain data through standardized REST endpoints for simpler integration.\n- **[Runtime API calls](/chain-interactions/query-data/runtime-api-calls/)**: Execute runtime APIs directly for specialized queries and operations."} -{"page_id": "chain-interactions", "page_title": "Chain Interactions Overview", "index": 3, "depth": 3, "title": "Send Transactions", "anchor": "send-transactions", "start_char": 1898, "end_char": 2608, "estimated_token_count": 150, "token_estimator": "heuristic-v1", "text": "### Send Transactions\n\nTransactions are the primary mechanism for modifying blockchain state. Understanding transaction construction, signing, and submission is crucial for building interactive applications.\n\n- **[Transaction construction](/chain-interactions/send-transactions/with-sdks/)**: Build transactions using various SDKs with proper encoding and formatting.\n- **[Fee estimation](/chain-interactions/send-transactions/calculate-transaction-fees/)**: Calculate transaction fees to ensure sufficient balance and optimize costs.\n- **[Multi-token fees](/chain-interactions/send-transactions/pay-fees-with-different-tokens/)**: Learn how to pay transaction fees with different tokens on supported chains."} -{"page_id": "chain-interactions", "page_title": "Chain Interactions Overview", "index": 4, "depth": 3, "title": "Send Cross-Chain Transactions", "anchor": "send-cross-chain-transactions", "start_char": 2608, "end_char": 3431, "estimated_token_count": 196, "token_estimator": "heuristic-v1", "text": "### Send Cross-Chain Transactions\n\nPolkadot enables native cross-chain capabilities through Cross-Consensus Messaging (XCM), allowing chains to securely communicate and transfer assets across the ecosystem.\n\n- **[Transfer assets between parachains](/chain-interactions/send-transactions/interoperability/transfer-assets-parachains/)**: Understand how to construct and send XCM messages using [ParaSpell XCM SDK](/reference/tools/paraspell/){target=\\_blank} and [Polkadot API (PAPI)](/reference/tools/papi/){target=\\_blank}.\n- **[Transfer assets out of Polkadot](/chain-interactions/send-transactions/interoperability/transfer-assets-out-of-polkadot/)**: Connect to blockchains outside the Polkadot ecosystem using [Snowbridge](https://wiki.polkadot.com/learn/learn-snowbridge/){target=\\_blank} and other bridge solutions."} -{"page_id": "chain-interactions", "page_title": "Chain Interactions Overview", "index": 5, "depth": 3, "title": "Manage Tokens", "anchor": "manage-tokens", "start_char": 3431, "end_char": 4284, "estimated_token_count": 203, "token_estimator": "heuristic-v1", "text": "### Manage Tokens\n\nPolkadot Hub provides a unified platform for managing assets across the ecosystem. Understanding token operations is essential for DeFi applications and multi-chain asset management.\n\n- **[Local asset registration](/chain-interactions/token-operations/register-local-asset/)**: Learn how assets created in Asset Hub are registered on the network.\n- **[Foregin asset registration](/chain-interactions/token-operations/register-foreign-asset/)**: Learn how assets created outside of Asset Hub are registered on the network.\n- **[Convert assets](/chain-interactions/token-operations/convert-assets/)**: Convert, swap, and manage assets on-chain using the Asset Conversion pallet.\n- **Asset Hub integration**: Interact with Polkadot's central asset management hub using [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\\_blank}."} -{"page_id": "chain-interactions", "page_title": "Chain Interactions Overview", "index": 6, "depth": 3, "title": "Manage Accounts", "anchor": "manage-accounts", "start_char": 4284, "end_char": 4756, "estimated_token_count": 101, "token_estimator": "heuristic-v1", "text": "### Manage Accounts\n\nAccount management forms the basis of user identity and authentication in blockchain applications. Learn how to create, manage, and query accounts programmatically.\n\n- **[Account creation](/chain-interactions/accounts/create-account/)**: Generate accounts using various SDKs in Rust, Python, and JavaScript.\n- **[Account queries](/chain-interactions/accounts/query-accounts/)**: Retrieve account information including balances, nonces, and metadata."} -{"page_id": "chain-interactions", "page_title": "Chain Interactions Overview", "index": 7, "depth": 2, "title": "Development Tools and SDKs", "anchor": "development-tools-and-sdks", "start_char": 4756, "end_char": 5737, "estimated_token_count": 235, "token_estimator": "heuristic-v1", "text": "## Development Tools and SDKs\n\nThe Polkadot ecosystem offers a rich set of tools and libraries to facilitate chain interactions:\n\n- **[Polkadot API (PAPI)](/reference/tools/papi/)**: Modern, type-safe TypeScript library with full metadata support.\n- **[Polkadot.js](/reference/tools/polkadot-js-api/)**: Comprehensive JavaScript library with extensive ecosystem support.\n- **[Dedot](/reference/tools/dedot/)**: Lightweight TypeScript library optimized for performance.\n- **[Python Substrate Interface](/reference/tools/py-substrate-interface/)**: Polkadot Substrate Interface for streamlined development.\n- **[Subxt](/reference/tools/subxt/)**: Rust library for building robust substrate-based applications.\n- **[Polkadot.js Apps](https://polkadot.js.org/apps/)**: Web-based interface for exploring and interacting with chains.\n\nEach tool has its strengths, and choosing the right one depends on your project requirements, programming language preference, and specific use cases."} -{"page_id": "chain-interactions", "page_title": "Chain Interactions Overview", "index": 8, "depth": 2, "title": "Next Steps", "anchor": "next-steps", "start_char": 5737, "end_char": 6632, "estimated_token_count": 209, "token_estimator": "heuristic-v1", "text": "## Next Steps\n\nExplore the sections below to dive deeper into specific chain interaction patterns:\n\n- **[Query On-Chain Data](/chain-interactions/query-data/query-sdks/)**: Learn to read blockchain state efficiently.\n- **[Send Transactions](/chain-interactions/send-transactions/with-sdks/)**: Master transaction construction and submission.\n- **[Send Cross-Chain Transactions](/chain-interactions/send-transactions/interoperability/transfer-assets-parachains/)**: Enable cross-chain communication with XCM.\n- **[Manage Tokens](/chain-interactions/token-operations/register-local-asset/)**: Manage assets across the Polkadot ecosystem.\n- **[Manage Accounts](/chain-interactions/accounts/create-account/)**: Create and query accounts programmatically.\n\nEach section provides practical examples, code snippets, and comprehensive guides to help you build production-ready applications on Polkadot."} {"page_id": "get-support-ai-ready-docs", "page_title": "AI Ready Docs", "index": 0, "depth": 2, "title": "How to Use These Files", "anchor": "how-to-use-these-files", "start_char": 286, "end_char": 952, "estimated_token_count": 164, "token_estimator": "heuristic-v1", "text": "## How to Use These Files\n\n- **Quick navigation**: Use `llms.txt` to give models a high-level map of the site.\n- **Lightweight context**: Use `site-index.json` for smaller context windows or when you only need targeted retrieval.\n- **Full content**: Use `llms-full.jsonl` for large-context models or preparing data for RAG pipelines.\n- **Focused bundles**: Use category files (e.g., `basics.md`, `parachains.md`) to limit content to a specific theme or task for more focused responses.\n\nThese AI-ready files do not include any persona or system prompts. They are purely informational and can be used without conflicting with your existing agent or tool prompting."} {"page_id": "get-support-ai-ready-docs", "page_title": "AI Ready Docs", "index": 1, "depth": 2, "title": "Download LLM Files", "anchor": "download-llm-files", "start_char": 952, "end_char": 7998, "estimated_token_count": 2068, "token_estimator": "heuristic-v1", "text": "## Download LLM Files\n\n| Category | Description | File | Actions |\n|----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Index | Markdown URL index for documentation pages, links to essential repos, and additional resources in the llms.txt standard format. | llms.txt |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/llms.txt\" } [:octicons-download-16:](){ .llms-dl data-path=\"/llms.txt\" data-filename=\"llms.txt\" }
    |\n| Site index (JSON) | Lightweight site index of JSON objects (one per page) with metadata and content previews. | site-index.json |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/site-index.json\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/site-index.json\" data-filename=\"site-index.json\" }
    |\n| Full site contents (JSONL) | Full content of documentation site enhanced with metadata. | llms-full.jsonl |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/llms-full.jsonl\" } [:octicons-download-16:](){ .llms-dl data-path=\"/llms-full.jsonl\" data-filename=\"llms-full.jsonl\" }
    |\n| Basics | Polkadot general knowledge base to provide context around overview and beginner-level content. | basics.md |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/categories/basics.md\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/categories/basics.md\" data-filename=\"basics.md\" }
    |\n| Reference | Reference material including key functions and glossary. | reference.md |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/categories/reference.md\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/categories/reference.md\" data-filename=\"reference.md\" }
    |\n| Smart Contracts | How to develop and deploy Solidity smart contracts on Polkadot Hub. | smart-contracts.md |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/categories/smart-contracts.md\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/categories/smart-contracts.md\" data-filename=\"smart-contracts.md\" }
    |\n| Parachains | How-to guides related to building, customizing, deploying, and maintaining a parachain. | parachains.md |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/categories/parachains.md\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/categories/parachains.md\" data-filename=\"parachains.md\" }
    |\n| DApps | Information and tutorials for application developers. | dapps.md |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/categories/dapps.md\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/categories/dapps.md\" data-filename=\"dapps.md\" }
    |\n| Networks | Information about the various Polkadot networks (Polkadot, Kusama, Westend, Paseo), their purposes, and how they fit into the development workflow. | networks.md |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/categories/networks.md\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/categories/networks.md\" data-filename=\"networks.md\" }
    |\n| Polkadot Protocol | Polkadot's core architecture, including the relay chain, parachains, system chains, interoperability, and main actors. | polkadot-protocol.md |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/categories/polkadot-protocol.md\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/categories/polkadot-protocol.md\" data-filename=\"polkadot-protocol.md\" }
    |\n| Infrastructure | Operational aspects of supporting the Polkadot network, including how to run a node or validator and staking mechanics. | infrastructure.md |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/categories/infrastructure.md\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/categories/infrastructure.md\" data-filename=\"infrastructure.md\" }
    |\n| Tooling | An overview of various development tools available for Polkadot development. | tooling.md |
    [:octicons-copy-16:](){ .llms-copy data-path=\"/ai/categories/tooling.md\" } [:octicons-download-16:](){ .llms-dl data-path=\"/ai/categories/tooling.md\" data-filename=\"tooling.md\" }
    |\n\n!!! note\n The `llms-full.jsonl` file may exceed the input limits of some language models due to its size. If you encounter limitations, consider using the smaller `site-index.json` or category bundle files instead."} {"page_id": "get-support-explore-resources", "page_title": "Subscribe to Updates", "index": 0, "depth": 2, "title": "🧠 Stack Exchange", "anchor": "stack-exchange", "start_char": 178, "end_char": 403, "estimated_token_count": 53, "token_estimator": "heuristic-v1", "text": "## 🧠 Stack Exchange\n\n- Browse commonly asked technical questions.\n- Ask your own and get detailed responses from experienced devs.\n\n👉 **[Visit Polkadot Stack Exchange](https://substrate.stackexchange.com/){target=\\_blank}**"} @@ -395,13 +315,13 @@ {"page_id": "parachains-interoperability-channels-with-system-parachains", "page_title": "Opening HRMP Channels with System Parachains", "index": 3, "depth": 3, "title": "Fund Parachain Sovereign Account", "anchor": "fund-parachain-sovereign-account", "start_char": 1338, "end_char": 2961, "estimated_token_count": 357, "token_estimator": "heuristic-v1", "text": "### Fund Parachain Sovereign Account\n\nThe [sovereign account](https://github.com/polkadot-fellows/xcm-format/blob/10726875bd3016c5e528c85ed6e82415e4b847d7/README.md?plain=1#L50){target=_blank} for parachain 2500 on the relay chain must be funded so it can take care of any XCM transact fees.\n\nUse [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank} UI to connect to the relay chain and transfer funds from your account to the parachain 2500 sovereign account.\n\n![](/images/parachains/interoperability/channels-common/channels-01.webp)\n\n??? note \"Calculating Parachain Sovereign Account\"\n To generate the sovereign account address for a parachain, you'll need to follow these steps:\n\n 1. Determine if the parachain is an \"up/down\" chain (parent or child) or a \"sibling\" chain:\n\n - Up/down chains use the prefix `0x70617261` (which decodes to `b\"para\"`).\n - Sibling chains use the prefix `0x7369626c` (which decodes to `b\"sibl\"`).\n\n 2. Calculate the u32 scale encoded value of the parachain ID:\n\n - Parachain 2500 would be encoded as `c4090000`.\n\n 3. Combine the prefix and parachain ID encoding to form the full sovereign account address:\n\n The sovereign account of parachain 2500 in relay chain will be `0x70617261c4090000000000000000000000000000000000000000000000000000`\n and the SS58 format of this address is `5Ec4AhPSY2GEE4VoHUVheqv5wwq2C1HMKa7c9fVJ1WKivX1Y`.\n \n To perform this conversion, you can also use the **\"Para ID\" to Address** section in [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/){target=\\_blank}."} {"page_id": "parachains-interoperability-channels-with-system-parachains", "page_title": "Opening HRMP Channels with System Parachains", "index": 4, "depth": 3, "title": "Create Establish Channel with System Extrinsic", "anchor": "create-establish-channel-with-system-extrinsic", "start_char": 2961, "end_char": 3767, "estimated_token_count": 183, "token_estimator": "heuristic-v1", "text": "### Create Establish Channel with System Extrinsic\n\n1. In Polkadot.js Apps, connect to the relay chain, navigate to the **Developer** dropdown and select the **Extrinsics** option.\n\n ![](/images/parachains/interoperability/channels-common/channels-02.webp)\n\n2. Construct an `establish_channel_with_system` extrinsic call:\n\n 1. Select the **`hrmp`** pallet.\n 2. Choose the **`establish_channel_with_system`** extrinsic.\n 3. Fill in the parameters:\n - **`target_system_chain`**: Parachain ID of the target system chain (in this case, 1000).\n 4. Copy the encoded call data.\n ![](/images/parachains/interoperability/channels-with-system-parachains/system-parachains-01.webp)\n\n The encoded call data for establishing a channel with system parachain 1000 should be `0x3c0ae8030000`."} {"page_id": "parachains-interoperability-channels-with-system-parachains", "page_title": "Opening HRMP Channels with System Parachains", "index": 5, "depth": 3, "title": "Craft and Submit the XCM Message", "anchor": "craft-and-submit-the-xcm-message", "start_char": 3767, "end_char": 7203, "estimated_token_count": 671, "token_estimator": "heuristic-v1", "text": "### Craft and Submit the XCM Message\n\nConnect to parachain 2500 using Polkadot.js Apps to send the XCM message to the relay chain. Input the necessary parameters as illustrated in the image below. Make sure to:\n\n1. Insert your previously encoded `establish_channel_with_system` call data into the **`call`** field.\n2. Provide beneficiary details.\n3. Dispatch the XCM message to the relay chain by clicking the **Submit Transaction** button.\n\n![](/images/parachains/interoperability/channels-with-system-parachains/system-parachains-02.webp)\n\n!!! note\n The exact process and parameters for submitting this XCM message may vary depending on your specific parachain and relay chain configurations. Always refer to the most current documentation for your particular network setup.\n\nAfter successfully submitting the XCM message to the relay chain, two [`HrmpSystemChannelOpened`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/hrmp/pallet/enum.Event.html#variant.HrmpSystemChannelOpened){target=\\_blank} events are emitted, indicating that the channels are now present in storage under [`HrmpOpenChannelRequests`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/hrmp/pallet/storage_types/struct.HrmpOpenChannelRequests.html){target=\\_blank}. However, the channels are not actually set up until the start of the next session, at which point bidirectional communication between parachain 2500 and system chain 1000 is established.\n\nTo verify this, wait for the next session and then follow these steps:\n\n1. Using Polkadot.js Apps, connect to the relay chain and navigate to the **Developer** dropdown, then select **Chain state**.\n\n ![](/images/parachains/interoperability/channels-common/channels-03.webp)\n\n2. Query the HRMP channels:\n\n 1. Select **`hrmp`** from the options.\n 2. Choose the **`hrmpChannels`** call.\n 3. Click the **+** button to execute the query.\n\n ![](/images/parachains/interoperability/channels-with-system-parachains/system-parachains-03.webp)\n \n3. Examine the query results. You should see output similar to the following:\n\n ```json\n [\n [\n [\n {\n \"sender\": 1000,\n \"recipient\": 2500\n }\n ],\n {\n \"maxCapacity\": 8,\n \"maxTotalSize\": 8192,\n \"maxMessageSize\": 1048576,\n \"msgCount\": 0,\n \"totalSize\": 0,\n \"mqcHead\": null,\n \"senderDeposit\": 0,\n \"recipientDeposit\": 0\n }\n ],\n [\n [\n {\n \"sender\": 2500,\n \"recipient\": 1000\n }\n ],\n {\n \"maxCapacity\": 8,\n \"maxTotalSize\": 8192,\n \"maxMessageSize\": 1048576,\n \"msgCount\": 0,\n \"totalSize\": 0,\n \"mqcHead\": null,\n \"senderDeposit\": 0,\n \"recipientDeposit\": 0\n }\n ]\n ]\n\n ```\n\nThe output confirms the successful establishment of two HRMP channels:\n\n- From chain 1000 (system chain) to chain 2500 (parachain).\n- From chain 2500 (parachain) to chain 1000 (system chain).\n\nThis bidirectional channel enables direct communication between the system chain and the parachain, allowing for cross-chain message passing."} -{"page_id": "parachains-interoperability-get-started", "page_title": "Introduction to XCM", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 23, "end_char": 695, "estimated_token_count": 113, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.\n\nWith XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation."} -{"page_id": "parachains-interoperability-get-started", "page_title": "Introduction to XCM", "index": 1, "depth": 2, "title": "Messaging Format", "anchor": "messaging-format", "start_char": 695, "end_char": 1569, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Messaging Format\n\nXCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics.\n\nXCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing."} -{"page_id": "parachains-interoperability-get-started", "page_title": "Introduction to XCM", "index": 2, "depth": 2, "title": "The Four Principles of XCM", "anchor": "the-four-principles-of-xcm", "start_char": 1569, "end_char": 2505, "estimated_token_count": 174, "token_estimator": "heuristic-v1", "text": "## The Four Principles of XCM\n\nXCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems:\n\n- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes.\n- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended.\n- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin.\n- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems.\n\nThese principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments."} -{"page_id": "parachains-interoperability-get-started", "page_title": "Introduction to XCM", "index": 3, "depth": 2, "title": "The XCM Tech Stack", "anchor": "the-xcm-tech-stack", "start_char": 2505, "end_char": 2869, "estimated_token_count": 75, "token_estimator": "heuristic-v1", "text": "## The XCM Tech Stack\n\n![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp)\n\nThe XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels."} -{"page_id": "parachains-interoperability-get-started", "page_title": "Introduction to XCM", "index": 4, "depth": 2, "title": "Core Functionalities of XCM", "anchor": "core-functionalities-of-xcm", "start_char": 2869, "end_char": 3865, "estimated_token_count": 165, "token_estimator": "heuristic-v1", "text": "## Core Functionalities of XCM\n\nXCM enhances cross-consensus communication by introducing several powerful features:\n\n- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management.\n- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification.\n- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location.\n\nThe standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications."} -{"page_id": "parachains-interoperability-get-started", "page_title": "Introduction to XCM", "index": 5, "depth": 2, "title": "XCM Example", "anchor": "xcm-example", "start_char": 3865, "end_char": 6877, "estimated_token_count": 704, "token_estimator": "heuristic-v1", "text": "## XCM Example\n\nThe following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA).\n\n```rust\nlet message = Xcm(vec![\n WithdrawAsset((Here, amount).into()),\n BuyExecution { \n fees: (Here, amount).into(), \n weight_limit: WeightLimit::Unlimited \n },\n DepositAsset {\n assets: All.into(),\n beneficiary: MultiLocation {\n parents: 0,\n interior: Junction::AccountId32 {\n network: None,\n id: BOB.clone().into()\n }.into(),\n }.into()\n }\n]);\n```\n\nThe message consists of three instructions described as follows:\n\n- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register.\n\n ```rust\n WithdrawAsset((Here, amount).into()),\n ```\n\n - **`Here`**: The native parachain token.\n - **`amount`**: The number of tokens that are transferred.\n\n The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register.\n\n- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\\_blank} of the XCM instructions.\n\n ```rust\n BuyExecution { \n fees: (Here, amount).into(), \n weight_limit: WeightLimit::Unlimited \n },\n ```\n\n - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight.\n - **`weight_limit`**: Defines the maximum fees that can be used to buy weight.\n\n- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\\_blank}**: Moves the remaining tokens from the holding register to Bob’s account.\n\n ```rust\n DepositAsset {\n assets: All.into(),\n beneficiary: MultiLocation {\n parents: 0,\n interior: Junction::AccountId32 {\n network: None,\n id: BOB.clone().into()\n }.into(),\n }.into()\n }\n ```\n\n - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited.\n \nThis step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\\_blank}."} -{"page_id": "parachains-interoperability-get-started", "page_title": "Introduction to XCM", "index": 6, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 6877, "end_char": 7450, "estimated_token_count": 117, "token_estimator": "heuristic-v1", "text": "## Overview\n\nXCM revolutionizes cross-chain communication by enabling use cases such as:\n\n- Token transfers between blockchains.\n- Asset locking for cross-chain smart contract interactions.\n- Remote execution of functions on other blockchains.\n\nThese functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\\_blank}."} +{"page_id": "parachains-interoperability-get-started", "page_title": "Get Started with XCM", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 24, "end_char": 696, "estimated_token_count": 113, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot’s unique value lies in its ability to enable interoperability between parachains and other blockchain systems. At the core of this capability is XCM (Cross-Consensus Messaging)—a flexible messaging format that facilitates communication and collaboration between independent consensus systems.\n\nWith XCM, one chain can send intents to another one, fostering a more interconnected ecosystem. Although it was developed specifically for Polkadot, XCM is a universal format, usable in any blockchain environment. This guide provides an overview of XCM’s core principles, design, and functionality, alongside practical examples of its implementation."} +{"page_id": "parachains-interoperability-get-started", "page_title": "Get Started with XCM", "index": 1, "depth": 2, "title": "Messaging Format", "anchor": "messaging-format", "start_char": 696, "end_char": 1570, "estimated_token_count": 153, "token_estimator": "heuristic-v1", "text": "## Messaging Format\n\nXCM is not a protocol but a standardized [messaging format](https://github.com/polkadot-fellows/xcm-format){target=\\_blank}. It defines the structure and behavior of messages but does not handle their delivery. This separation allows developers to focus on crafting instructions for target systems without worrying about transmission mechanics.\n\nXCM messages are intent-driven, outlining desired actions for the receiving blockchain to consider and potentially alter its state. These messages do not directly execute changes; instead, they rely on the host chain's environment to interpret and implement them. By utilizing asynchronous composability, XCM facilitates efficient execution where messages can be processed independently of their original order, similar to how RESTful services handle HTTP requests without requiring sequential processing."} +{"page_id": "parachains-interoperability-get-started", "page_title": "Get Started with XCM", "index": 2, "depth": 2, "title": "The Four Principles of XCM", "anchor": "the-four-principles-of-xcm", "start_char": 1570, "end_char": 2506, "estimated_token_count": 174, "token_estimator": "heuristic-v1", "text": "## The Four Principles of XCM\n\nXCM adheres to four guiding principles that ensure robust and reliable communication across consensus systems:\n\n- **Asynchronous**: XCM messages operate independently of sender acknowledgment, avoiding delays due to blocked processes.\n- **Absolute**: XCM messages are guaranteed to be delivered and interpreted accurately, in order, and timely. Once a message is sent, one can be sure it will be processed as intended.\n- **Asymmetric**: XCM messages follow the 'fire and forget' paradigm meaning no automatic feedback is provided to the sender. Any results must be communicated separately to the sender with an additional message back to the origin.\n- **Agnostic**: XCM operates independently of the specific consensus mechanisms, making it compatible across diverse systems.\n\nThese principles guarantee that XCM provides a reliable framework for cross-chain communication, even in complex environments."} +{"page_id": "parachains-interoperability-get-started", "page_title": "Get Started with XCM", "index": 3, "depth": 2, "title": "The XCM Tech Stack", "anchor": "the-xcm-tech-stack", "start_char": 2506, "end_char": 2870, "estimated_token_count": 75, "token_estimator": "heuristic-v1", "text": "## The XCM Tech Stack\n\n![Diagram of the XCM tech stack](/images/parachains/interoperability/get-started/intro-to-xcm-01.webp)\n\nThe XCM tech stack is designed to facilitate seamless interoperable communication between chains that reside within the Polkadot ecosystem. XCM can be used to express the meaning of the messages over each of the communication channels."} +{"page_id": "parachains-interoperability-get-started", "page_title": "Get Started with XCM", "index": 4, "depth": 2, "title": "Core Functionalities of XCM", "anchor": "core-functionalities-of-xcm", "start_char": 2870, "end_char": 3866, "estimated_token_count": 165, "token_estimator": "heuristic-v1", "text": "## Core Functionalities of XCM\n\nXCM enhances cross-consensus communication by introducing several powerful features:\n\n- **Programmability**: Supports dynamic message handling, allowing for more comprehensive use cases. Includes branching logic, safe dispatches for version checks, and asset operations like NFT management.\n- **Functional Multichain Decomposition**: Enables mechanisms such as remote asset locking, asset namespacing, and inter-chain state referencing, with contextual message identification.\n- **Bridging**: Establishes a universal reference framework for multi-hop setups, connecting disparate systems like Ethereum and Bitcoin with the Polkadot relay chain acting as a universal location.\n\nThe standardized format for messages allows parachains to handle tasks like user balances, governance, and staking, freeing the Polkadot relay chain to focus on shared security. These features make XCM indispensable for implementing scalable and interoperable blockchain applications."} +{"page_id": "parachains-interoperability-get-started", "page_title": "Get Started with XCM", "index": 5, "depth": 2, "title": "XCM Example", "anchor": "xcm-example", "start_char": 3866, "end_char": 6878, "estimated_token_count": 704, "token_estimator": "heuristic-v1", "text": "## XCM Example\n\nThe following is a simplified XCM message demonstrating a token transfer from Alice to Bob on the same chain (ParaA).\n\n```rust\nlet message = Xcm(vec![\n WithdrawAsset((Here, amount).into()),\n BuyExecution { \n fees: (Here, amount).into(), \n weight_limit: WeightLimit::Unlimited \n },\n DepositAsset {\n assets: All.into(),\n beneficiary: MultiLocation {\n parents: 0,\n interior: Junction::AccountId32 {\n network: None,\n id: BOB.clone().into()\n }.into(),\n }.into()\n }\n]);\n```\n\nThe message consists of three instructions described as follows:\n\n- **[WithdrawAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#withdrawasset){target=\\_blank}**: Transfers a specified number of tokens from Alice's account to a holding register.\n\n ```rust\n WithdrawAsset((Here, amount).into()),\n ```\n\n - **`Here`**: The native parachain token.\n - **`amount`**: The number of tokens that are transferred.\n\n The first instruction takes as an input the MultiAsset that should be withdrawn. The MultiAsset describes the native parachain token with the `Here` keyword. The `amount` parameter is the number of tokens that are transferred. The withdrawal account depends on the origin of the message. In this example the origin of the message is Alice. The `WithdrawAsset` instruction moves `amount` number of native tokens from Alice's account into the holding register.\n\n- **[BuyExecution](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#buyexecution){target=\\_blank}**: Allocates fees to cover the execution [weight](/reference/glossary/#weight){target=\\_blank} of the XCM instructions.\n\n ```rust\n BuyExecution { \n fees: (Here, amount).into(), \n weight_limit: WeightLimit::Unlimited \n },\n ```\n\n - **`fees`**: Describes the asset in the holding register that should be used to pay for the weight.\n - **`weight_limit`**: Defines the maximum fees that can be used to buy weight.\n\n- **[DepositAsset](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#depositasset){target=\\_blank}**: Moves the remaining tokens from the holding register to Bob’s account.\n\n ```rust\n DepositAsset {\n assets: All.into(),\n beneficiary: MultiLocation {\n parents: 0,\n interior: Junction::AccountId32 {\n network: None,\n id: BOB.clone().into()\n }.into(),\n }.into()\n }\n ```\n\n - **`All`**: The wildcard for the asset(s) to be deposited. In this case, all assets in the holding register should be deposited.\n \nThis step-by-step process showcases how XCM enables precise state changes within a blockchain system. You can find a complete XCM message example in the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\\_blank}."} +{"page_id": "parachains-interoperability-get-started", "page_title": "Get Started with XCM", "index": 6, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 6878, "end_char": 7451, "estimated_token_count": 117, "token_estimator": "heuristic-v1", "text": "## Overview\n\nXCM revolutionizes cross-chain communication by enabling use cases such as:\n\n- Token transfers between blockchains.\n- Asset locking for cross-chain smart contract interactions.\n- Remote execution of functions on other blockchains.\n\nThese functionalities empower developers to build innovative, multi-chain applications, leveraging the strengths of various blockchain networks. To stay updated on XCM’s evolving format or contribute, visit the [XCM repository](https://github.com/paritytech/xcm-docs/blob/main/examples/src/0_first_look/mod.rs){target=\\_blank}."} {"page_id": "parachains-launch-a-parachain-deploy-to-polkadot", "page_title": "Deploy on Polkadot", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 22, "end_char": 439, "estimated_token_count": 89, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPreviously, you learned how to [choose and set up a parachain template](/parachains/launch-a-parachain/choose-a-template/){target=\\_blank}. Now, you'll take the next step towards a production-like environment by deploying your parachain to the Polkadot TestNet. Deploying to a TestNet is a crucial step for validating your parachain's functionality and preparing it for eventual MainNet deployment."} {"page_id": "parachains-launch-a-parachain-deploy-to-polkadot", "page_title": "Deploy on Polkadot", "index": 1, "depth": 2, "title": "Get Started with an Account and Tokens", "anchor": "get-started-with-an-account-and-tokens", "start_char": 439, "end_char": 2420, "estimated_token_count": 540, "token_estimator": "heuristic-v1", "text": "## Get Started with an Account and Tokens\n\nTo perform any action on the Polkadot TestNet, you need PAS tokens, which can be requested from the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=0){target=\\_blank}. To store the tokens, you must have access to a Polkadot-SDK-compatible wallet. Go to the [Polkadot Wallets](https://polkadot.com/get-started/wallets/){target=\\_blank} page to view different options for a Polkadot wallet, or use the [Polkadot.js browser extension](https://polkadot.js.org/extension/){target=\\_blank}, which is suitable for development purposes.\n\n!!!warning \n Development keys and accounts should never hold assets of actual value and should not be used for production.\n\nThe [Polkadot.js Apps](https://polkadot.js.org/apps/){target=\\_blank} interface can be used to get you started for testing purposes.\n\nTo prepare an account, follow these steps:\n\n1. Open the [Polkadot.js Apps: Paseo](https://polkadot.js.org/apps/?rpc=wss://paseo.dotters.network#/explorer){target=\\_blank} interface and connect to the Polkadot TestNet (Paseo).\n\n ![](/images/parachains/launch-a-parachain/deploy-to-polkadot/deploy-to-polkadot-1.webp)\n\n2. Navigate to the **Accounts** section:\n\n 1. Click on the **Accounts** tab in the top menu.\n 2. Select the **Accounts** option from the dropdown menu.\n \n ![](/images/parachains/launch-a-parachain/deploy-to-polkadot/deploy-to-polkadot-2.webp)\n\n3. Copy the address of the account you want to use for the parachain deployment.\n\n ![](/images/parachains/launch-a-parachain/deploy-to-polkadot/deploy-to-polkadot-3.webp)\n\n4. Visit the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=0){target=\\_blank} and paste the copied address in the input field. Ensure that the network is set to Paseo and click on the **Get some PASs** button.\n\n ![](/images/parachains/launch-a-parachain/deploy-to-polkadot/deploy-to-polkadot-4.webp)\n\n After a few seconds, you will receive 5000 PAS tokens in your account."} {"page_id": "parachains-launch-a-parachain-deploy-to-polkadot", "page_title": "Deploy on Polkadot", "index": 2, "depth": 2, "title": "Reserve a Parachain Identifier", "anchor": "reserve-a-parachain-identifier", "start_char": 2420, "end_char": 3577, "estimated_token_count": 303, "token_estimator": "heuristic-v1", "text": "## Reserve a Parachain Identifier\n\nYou must reserve a parachain identifier (ID) before registering your parachain on Paseo. You'll be assigned the next available identifier.\n\nTo reserve a parachain identifier, follow these steps:\n\n1. Navigate to the **Parachains** section:\n\n 1. Click on the **Network** tab in the top menu.\n 2. Select the **Parachains** option from the dropdown menu.\n\n ![](/images/parachains/launch-a-parachain/deploy-to-polkadot/deploy-to-polkadot-5.webp)\n\n2. Register a ParaId:\n\n 1. Select the **Parathreads** tab.\n 2. Click on the **+ ParaId** button.\n\n ![](/images/parachains/launch-a-parachain/deploy-to-polkadot/deploy-to-polkadot-6.webp)\n\n3. Review the transaction and click on the **+ Submit** button.\n\n ![](/images/parachains/launch-a-parachain/deploy-to-polkadot/deploy-to-polkadot-7.webp)\n\n For this case, the next available parachain identifier is `4508`.\n\n4. After submitting the transaction, you can navigate to the **Explorer** tab and check the list of recent events for successful `registrar.Reserved`.\n\n ![](/images/parachains/launch-a-parachain/deploy-to-polkadot/deploy-to-polkadot-8.webp)"} @@ -455,416 +375,30 @@ {"page_id": "parachains-runtime-maintenance-unlock-parachains", "page_title": "Unlock a Parachain", "index": 3, "depth": 3, "title": "Prepare the Unlock Call", "anchor": "prepare-the-unlock-call", "start_char": 2758, "end_char": 4174, "estimated_token_count": 341, "token_estimator": "heuristic-v1", "text": "### Prepare the Unlock Call\n\nBefore sending the XCM, you need to construct the relay chain call that will be executed. Follow these steps to prepare the `registrar.removeLock` extrinsic:\n\n1. In [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank}, connect to the relay chain, navigate to the **Developer** dropdown and select the **Extrinsics** option.\n\n2. Build the `registrar.removeLock` extrinsic:\n\n 1. Select the **registrar** pallet.\n 2. Choose the **removeLock** extrinsic.\n 3. Fill in the parachain ID parameter (e.g., `2006`).\n 4. Copy the **encoded call data**.\n\n ![](/images/parachains/runtime-maintenance/unlock-parachains/unlock-parachain-2.webp)\n\n To ensure your encoded call data is correct, check this [example](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fdot-rpc.stakeworld.io#/extrinsics/decode/0x4604d6070000){target=\\_blank} of a decoded `removeLock` call for parachain 2006. Your encoded data should follow the same pattern.\n\n3. Determine the transaction weight required for executing the call. You can estimate this by executing the `transactionPaymentCallApi.queryCallInfo` runtime call with the encoded call data previously obtained:\n\n ![](/images/parachains/runtime-maintenance/unlock-parachains/unlock-parachain-3.webp)\n\n This weight information is crucial for properly configuring your XCM message's execution parameters in the next steps."} {"page_id": "parachains-runtime-maintenance-unlock-parachains", "page_title": "Unlock a Parachain", "index": 4, "depth": 3, "title": "Fund the Sovereign Account", "anchor": "fund-the-sovereign-account", "start_char": 4174, "end_char": 6051, "estimated_token_count": 414, "token_estimator": "heuristic-v1", "text": "### Fund the Sovereign Account\n\nFor a successful XCM execution, the [sovereign account](https://github.com/polkadot-fellows/xcm-format/blob/10726875bd3016c5e528c85ed6e82415e4b847d7/README.md?plain=1#L50){target=\\_blank} of your parachain on the relay chain must have sufficient funds to cover transaction fees. The sovereign account is a deterministic address derived from your parachain ID.\n\nYou can identify your parachain's sovereign account using either of these methods:\n\n=== \"Runtime API\"\n\n Execute the `locationToAccountApi.convertLocation` runtime API call to convert your parachain's location into its sovereign account address on the relay chain.\n\n ![](/images/parachains/runtime-maintenance/unlock-parachains/unlock-parachain-7.webp)\n\n=== \"Substrate Utilities\"\n\n Use the **\"Para ID\" to Address** section in [Substrate Utilities](https://www.shawntabrizi.com/substrate-js-utilities/){target=\\_blank} with the **Child** option selected.\n\n=== \"Manual Calculation\"\n\n 1. Identify the appropriate prefix:\n\n - For parent/child chains use the prefix `0x70617261` (which decodes to `b\"para\"`).\n \n 2. Encode your parachain ID as a u32 [SCALE](/polkadot-protocol/parachain-basics/data-encoding#data-types){target=\\_blank} value:\n\n - For parachain 2006, this would be `d6070000`.\n\n 3. Combine the prefix with the encoded ID to form the sovereign account address:\n\n - **Hex**: `0x70617261d6070000000000000000000000000000000000000000000000000000`\n - **SS58 format**: `5Ec4AhPW97z4ZyYkd3mYkJrSeZWcwVv4wiANES2QrJi1x17F`\n\nYou can transfer funds to this account from any account on the relay chain using a standard transfer. To calculate the amount needed, refer to the [XCM Payment API](/develop/interoperability/xcm-runtime-apis/#xcm-payment-api){target=\\_blank}. The calculation will depend on the XCM built in the next step."} {"page_id": "parachains-runtime-maintenance-unlock-parachains", "page_title": "Unlock a Parachain", "index": 5, "depth": 3, "title": "Craft and Submit the XCM", "anchor": "craft-and-submit-the-xcm", "start_char": 6051, "end_char": 9232, "estimated_token_count": 710, "token_estimator": "heuristic-v1", "text": "### Craft and Submit the XCM\n\nWith the call data prepared and the sovereign account funded, you can now construct and send the XCM from your parachain to the relay chain. The XCM will need to perform several operations in sequence:\n\n1. Withdraw DOT from your parachain's sovereign account.\n2. Buy execution to pay for transaction fees.\n3. Execute the `registrar.removeLock` extrinsic.\n4. Return any unused funds to your sovereign account.\n\nHere's how to submit this XCM using Astar (Parachain 2006) as an example:\n\n1. In [Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank}, connect to the parachain, navigate to the **Developer** dropdown and select the **Extrinsics** option.\n\n2. Create a `sudo.sudo` extrinsic that executes `polkadotXcm.send`:\n\n 1. Use the `sudo.sudo` extrinsic to execute the following call as Root.\n 2. Select the **polkadotXcm** pallet.\n 3. Choose the **send** extrinsic.\n 4. Set the **dest** parameter as the relay chain.\n\n ![](/images/parachains/runtime-maintenance/unlock-parachains/unlock-parachain-4.webp)\n\n3. Construct the XCM and submit it:\n\n 1. Add a **WithdrawAsset** instruction.\n 2. Add a **BuyExecution** instruction.\n - **fees**:\n - **id**: The asset location to use for the fee payment. In this example, the relay chain native asset is used.\n - **fun**: Select `Fungible` and use the same amount you withdrew from the sovereign account in the previous step.\n - **weightLimit**: Use `Unlimited`.\n 3. Add a **Transact** instruction with the following parameters:\n - **originKind**: Use `Native`.\n - **requireWeightAtMost**: Use the weight calculated previously.\n - **call**: Use the encoded call data generated before.\n 4. Add a **RefundSurplus** instruction.\n 5. Add a **DepositAsset** instruction to send the remaining funds to the parachain sovereign account.\n 6. Click the **Submit Transaction** button.\n\n ![](/images/parachains/runtime-maintenance/unlock-parachains/unlock-parachain-5.webp)\n\n If the amount withdrawn in the first instruction is exactly the amount needed to pay the transaction fees, instructions 4 and 5 can be omitted.\n\n To validate your XCM, examine the following reference [extrinsic](https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fastar.public.curie.radiumblock.co%2Fws#/extrinsics/decode/0x63003300040100041400040000000700e40b5402130000000700e40b540200060042d3c91800184604d6070000140d0100000100591f){target=_blank} showing the proper instruction sequence and parameter formatting. Following this structure will help ensure successful execution of your message.\n\nAfter submitting the transaction, wait for it to be finalized and then verify that your parachain has been successfully unlocked by following the steps described in the [Check if the Parachain is Locked](#check-if-the-parachain-is-locked) section. If the parachain shows as unlocked, your operation has been successful. If it still appears locked, verify that your XCM transaction was processed correctly and consider troubleshooting the XCM built.\n\n![](/images/parachains/runtime-maintenance/unlock-parachains/unlock-parachain-6.webp)"} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 15, "end_char": 1193, "estimated_token_count": 242, "token_estimator": "heuristic-v1", "text": "## Introduction\n\n[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.\n\nThis guide walks you through installing Chopsticks and provides information on configuring a local blockchain fork. By streamlining testing and experimentation, Chopsticks empowers developers to innovate and accelerate their blockchain projects within the Polkadot ecosystem.\n\nFor additional support and information, please reach out through [GitHub Issues](https://github.com/AcalaNetwork/chopsticks/issues){target=_blank}.\n\n!!! warning\n Chopsticks uses [Smoldot](https://github.com/smol-dot/smoldot){target=_blank} light client, which only supports the native Polkadot SDK API. Consequently, a Chopsticks-based fork doesn't support Ethereum JSON-RPC calls, meaning you cannot use it to fork your chain and connect Metamask."} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 1193, "end_char": 1500, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have the following installed:\n\n- [Node.js](https://nodejs.org/en/){target=\\_blank}.\n- A package manager such as [npm](https://www.npmjs.com/){target=\\_blank}, which should be installed with Node.js by default, or [Yarn](https://yarnpkg.com/){target=\\_blank}."} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 2, "depth": 2, "title": "Install Chopsticks", "anchor": "install-chopsticks", "start_char": 1500, "end_char": 1792, "estimated_token_count": 55, "token_estimator": "heuristic-v1", "text": "## Install Chopsticks\n\nYou can install Chopsticks globally or locally in your project. Choose the option that best fits your development workflow. This documentation explains the features of Chopsticks version `1.2.2`. Make sure you're using the correct version to match these instructions."} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 3, "depth": 3, "title": "Global Installation", "anchor": "global-installation", "start_char": 1792, "end_char": 2035, "estimated_token_count": 61, "token_estimator": "heuristic-v1", "text": "### Global Installation\n\nTo install Chopsticks globally, allowing you to use it across multiple projects, run:\n\n```bash\nnpm i -g @acala-network/chopsticks@1.2.2\n```\n\nNow, you should be able to run the `chopsticks` command from your terminal."} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 4, "depth": 3, "title": "Local Installation", "anchor": "local-installation", "start_char": 2035, "end_char": 2524, "estimated_token_count": 128, "token_estimator": "heuristic-v1", "text": "### Local Installation\n\nTo use Chopsticks in a specific project, first create a new directory and initialize a Node.js project:\n\n```bash\nmkdir my-chopsticks-project\ncd my-chopsticks-project\nnpm init -y\n```\n\nThen, install Chopsticks as a local dependency:\n\n```bash\nnpm i @acala-network/chopsticks@1.2.2\n```\n\nFinally, you can run Chopsticks using the `npx` command. To see all available options and commands, run it with the `--help` flag:\n\n```bash\nnpx @acala-network/chopsticks --help\n```"} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 5, "depth": 2, "title": "Configure Chopsticks", "anchor": "configure-chopsticks", "start_char": 2524, "end_char": 3873, "estimated_token_count": 360, "token_estimator": "heuristic-v1", "text": "## Configure Chopsticks\n\nTo run Chopsticks, you need to configure some parameters. This can be set either through using a configuration file or the command line interface (CLI). The parameters that can be configured are as follows:\n\n- **`genesis`**: The link to a parachain's raw genesis file to build the fork from, instead of an endpoint.\n- **`timestamp`**: Timestamp of the block to fork from.\n- **`endpoint`**: The endpoint of the parachain to fork.\n- **`block`**: Use to specify at which block hash or number to replay the fork.\n- **`wasm-override`**: Path of the Wasm to use as the parachain runtime, instead of an endpoint's runtime.\n- **`db`**: Path to the name of the file that stores or will store the parachain's database.\n- **`config`**: Path or URL of the config file.\n- **`port`**: The port to expose an endpoint on.\n- **`build-block-mode`**: How blocks should be built in the fork: batch, manual, instant.\n- **`import-storage`**: A pre-defined JSON/YAML storage path to override in the parachain's storage.\n- **`allow-unresolved-imports`**: Whether to allow Wasm unresolved imports when using a Wasm to build the parachain.\n- **`html`**: Include to generate storage diff preview between blocks.\n- **`mock-signature-host`**: Mock signature host so that any signature starts with `0xdeadbeef` and filled by `0xcd` is considered valid."} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 6, "depth": 3, "title": "Configuration File", "anchor": "configuration-file", "start_char": 3873, "end_char": 5072, "estimated_token_count": 271, "token_estimator": "heuristic-v1", "text": "### Configuration File\n\nThe Chopsticks source repository includes a collection of [YAML](https://yaml.org/){target=\\_blank} files that can be used to set up various Polkadot SDK chains locally. You can download these configuration files from the [repository's `configs` folder](https://github.com/AcalaNetwork/chopsticks/tree/master/configs){target=\\_blank}.\n\nAn example of a configuration file for Polkadot is as follows:\n\n{% raw %}\n```yaml\nendpoint:\n - wss://rpc.ibp.network/polkadot\n - wss://polkadot-rpc.dwellir.com\nmock-signature-host: true\nblock: ${env.POLKADOT_BLOCK_NUMBER}\ndb: ./db.sqlite\nruntime-log-level: 5\n\nimport-storage:\n System:\n Account:\n - - - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\n - providers: 1\n data:\n free: '10000000000000000000'\n ParasDisputes:\n $removePrefix: ['disputes'] # those can makes block building super slow\n\n```\n{% endraw %}\n\nThe configuration file allows you to modify the storage of the forked network by rewriting the pallet, state component and value that you want to change. For example, Polkadot's file rewrites Alice's `system.Account` storage so that the free balance is set to `10000000000000000000`."} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 7, "depth": 3, "title": "CLI Flags", "anchor": "cli-flags", "start_char": 5072, "end_char": 5253, "estimated_token_count": 35, "token_estimator": "heuristic-v1", "text": "### CLI Flags\n\nAlternatively, all settings (except for genesis and timestamp) can be configured via command-line flags, providing a comprehensive method to set up the environment."} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 8, "depth": 2, "title": "WebSocket Commands", "anchor": "websocket-commands", "start_char": 5253, "end_char": 10537, "estimated_token_count": 1272, "token_estimator": "heuristic-v1", "text": "## WebSocket Commands\n\nChopstick's internal WebSocket server has special endpoints that allow the manipulation of the local Polkadot SDK chain.\n\nThese are the methods that can be invoked and their parameters:\n\n- **dev_newBlock** (newBlockParams): Generates one or more new blocks.\n\n === \"Parameters\"\n\n - **`newBlockParams` ++\"NewBlockParams\"++**: The parameters to build the new block with. Where the `NewBlockParams` interface includes the following properties.\n\n - **`count` ++\"number\"++**: The number of blocks to build.\n - **`dmp` ++\"{ msg: string, sentAt: number }[]\"++**: The downward messages to include in the block.\n - **`hrmp` ++\"Record\"++**: The horizontal messages to include in the block.\n - **`to` ++\"number\"++**: The block number to build to.\n - **`transactions` ++\"string[]\"++**: The transactions to include in the block.\n - **`ump` ++\"Record\"++**: The upward messages to include in the block.\n - **`unsafeBlockHeight` ++\"number\"++**: Build block using a specific block height (unsafe).\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_newBlock', { count: 1 });\n }\n\n main();\n\n ```\n\n- **dev_setBlockBuildMode** (buildBlockMode): Sets block build mode.\n\n === \"Parameter\"\n \n - **`buildBlockMode` ++\"BuildBlockMode\"++**: The build mode. Can be any of the following modes:\n\n ```ts\n export enum BuildBlockMode {\n Batch = 'Batch', /** One block per batch (default) */\n Instant = 'Instant', /** One block per transaction */\n Manual = 'Manual', /** Only build when triggered */\n }\n ```\n \n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_setBlockBuildMode', 'Instant');\n }\n\n main();\n\n ```\n\n- **dev_setHead** (hashOrNumber): Sets the head of the blockchain to a specific hash or number.\n\n === \"Parameter\"\n\n - **`hashOrNumber` ++\"string | number\"++**: The block hash or number to set as head.\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_setHead', 500);\n }\n\n main();\n\n ```\n\n- **dev_setRuntimeLogLevel** (runtimeLogLevel): Sets the runtime log level.\n\n === \"Parameter\"\n\n - **`runtimeLogLevel` ++\"number\"++**: The runtime log level to set.\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_setRuntimeLogLevel', 1);\n }\n\n main();\n\n ```\n\n- **dev_setStorage** (values, blockHash): Creates or overwrites the value of any storage.\n\n === \"Parameters\"\n\n - **`values` ++\"object\"++**: JSON object resembling the path to a storage value.\n - **`blockHash` ++\"string\"++**: The block hash to set the storage value.\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n import { Keyring } from '@polkadot/keyring';\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n const keyring = new Keyring({ type: 'ed25519' });\n const bob = keyring.addFromUri('//Bob');\n const storage = {\n System: {\n Account: [[[bob.address], { data: { free: 100000 }, nonce: 1 }]],\n },\n };\n await api.rpc('dev_setStorage', storage);\n }\n\n main();\n\n ```\n\n- **dev_timeTravel** (date): Sets the timestamp of the block to a specific date\".\n\n === \"Parameter\"\n\n - **`date` ++\"string\"++**: Timestamp or date string to set. All future blocks will be sequentially created after this point in time.\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_timeTravel', '2030-08-15T00:00:00');\n }\n\n main();\n\n ```"} -{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Get Started", "index": 9, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 10537, "end_char": 10894, "estimated_token_count": 91, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
    \n\n- Tutorial __Fork a Chain with Chopsticks__\n\n ---\n\n Visit this guide for step-by-step instructions for configuring and interacting with your forked chain.\n\n [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/fork-live-chains/)\n\n
    "} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 15, "end_char": 767, "estimated_token_count": 125, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nZombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.\n\nThis guide will outline the different installation methods for Zombienet, provide step-by-step instructions for setting up on various platforms, and highlight essential provider-specific features and requirements.\n\nBy following this guide, Zombienet will be up and running quickly, ready to streamline your blockchain testing and development workflows."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 1, "depth": 2, "title": "Install Zombienet", "anchor": "install-zombienet", "start_char": 767, "end_char": 5021, "estimated_token_count": 901, "token_estimator": "heuristic-v1", "text": "## Install Zombienet\n\nZombienet releases are available on the [Zombienet repository](https://github.com/paritytech/zombienet){target=\\_blank}.\n\nMultiple options are available for installing Zombienet, depending on the user's preferences and the environment where it will be used. The following section will guide you through the installation process for each option.\n\n=== \"Use the executable\"\n\n Install Zombienet using executables by visiting the [latest release](https://github.com/paritytech/zombienet/releases){target=\\_blank} page and selecting the appropriate asset for your operating system. You can download the executable and move it to a directory in your PATH. \n\n Each release includes executables for Linux and macOS. Executables are generated using [pkg](https://github.com/vercel/pkg){target=\\_blank}, which allows the Zombienet CLI to operate without requiring Node.js to be installed. \n\n Then, ensure the downloaded file is executable:\n\n ```bash\n chmod +x zombienet-macos-arm64\n ```\n\n Finally, you can run the following command to check if the installation was successful. If so, it will display the version of the installed Zombienet:\n\n ```bash\n ./zombienet-macos-arm64 version\n ```\n\n If you want to add the `zombienet` executable to your PATH, you can move it to a directory in your PATH, such as `/usr/local/bin`:\n\n ```bash\n mv zombienet-macos-arm64 /usr/local/bin/zombienet\n ```\n\n Now you can refer to the `zombienet` executable directly.\n\n ```bash\n zombienet version\n ```\n\n=== \"Use Nix\"\n\n For Nix users, the Zombienet repository provides a [`flake.nix`](https://github.com/paritytech/zombienet/blob/main/flake.nix){target=\\_blank} file to install Zombienet making it easy to incorporate Zombienet into Nix-based projects.\n \n To install Zombienet utilizing Nix, users can run the following command, triggering the fetching of the flake and subsequently installing the Zombienet package:\n\n ```bash\n nix run github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION -- \\\n spawn INSERT_ZOMBIENET_CONFIG_FILE_NAME.toml\n ```\n\n Replace the `INSERT_ZOMBIENET_VERSION` with the desired version of Zombienet and the `INSERT_ZOMBIENET_CONFIG_FILE_NAME` with the name of the configuration file you want to use.\n\n To run the command above, you need to have [Flakes](https://nixos.wiki/wiki/Flakes#Enable_flakes){target=\\_blank} enabled.\n\n Alternatively, you can also include the Zombienet binary in the PATH for the current shell using the following command:\n \n ```bash\n nix shell github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION\n ```\n\n=== \"Use Docker\"\n\n Zombienet can also be run using Docker. The Zombienet repository provides a Docker image that can be used to run the Zombienet CLI. To run Zombienet using Docker, you can use the following command:\n\n ```bash\n docker run -it --rm \\\n -v $(pwd):/home/nonroot/zombie-net/host-current-files \\\n paritytech/zombienet\n ```\n\n The command above will run the Zombienet CLI inside a Docker container and mount the current directory to the `/home/nonroot/zombie-net/host-current-files` directory. This allows Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path.\n\n Inside the Docker container, you can run the Zombienet CLI commands. First, you need to set up Zombienet to download the necessary binaries:\n\n ```bash\n npm run zombie -- setup polkadot polkadot-parachain\n ```\n\n After that, you need to add those binaries to the PATH:\n\n ```bash\n export PATH=/home/nonroot/zombie-net:$PATH\n ```\n\n Finally, you can run the Zombienet CLI commands. For example, to spawn a network using a specific configuration file, you can run the following command:\n\n ```bash\n npm run zombie -- -p native spawn host-current-files/minimal.toml\n ```\n\n The command above mounts the current directory to the `/workspace` directory inside the Docker container, allowing Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 2, "depth": 2, "title": "Providers", "anchor": "providers", "start_char": 5021, "end_char": 5804, "estimated_token_count": 185, "token_estimator": "heuristic-v1", "text": "## Providers\n\nZombienet supports different backend providers for running the nodes. At this moment, [Kubernetes](https://kubernetes.io/){target=\\_blank}, [Podman](https://podman.io/){target=\\_blank}, and local providers are supported, which can be declared as `kubernetes`, `podman`, or `native`, respectively.\n\nTo use a particular provider, you can specify it in the network file or use the `--provider` flag in the CLI:\n\n```bash\nzombienet spawn network.toml --provider INSERT_PROVIDER\n```\n\nAlternatively, you can set the provider in the network file:\n\n```toml\n[settings]\nprovider = \"INSERT_PROVIDER\"\n...\n```\n\nIt's important to note that each provider has specific requirements and associated features. The following sections cover each provider's requirements and added features."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 3, "depth": 3, "title": "Kubernetes", "anchor": "kubernetes", "start_char": 5804, "end_char": 7333, "estimated_token_count": 329, "token_estimator": "heuristic-v1", "text": "### Kubernetes\n\nKubernetes is a portable, extensible, open-source platform for managing containerized workloads and services. Zombienet is designed to be compatible with a variety of Kubernetes clusters, including: \n\n- [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine){target=\\_blank}\n- [Docker Desktop](https://docs.docker.com/desktop/features/kubernetes/){target=\\_blank}\n- [kind](https://kind.sigs.k8s.io/){target=\\_blank}\n\n#### Requirements\n \nTo effectively interact with your cluster, you'll need to ensure that [`kubectl`](https://kubernetes.io/docs/reference/kubectl/){target=\\_blank} is installed on your system. This Kubernetes command-line tool allows you to run commands against Kubernetes clusters. If you don't have `kubectl` installed, you can follow the instructions provided in the [Kubernetes documentation](https://kubernetes.io/docs/tasks/tools/#kubectl){target=\\_blank}.\n\nTo create resources such as namespaces, pods, and CronJobs within the target cluster, you must grant your user or service account the appropriate permissions. These permissions are essential for managing and deploying applications effectively within Kubernetes.\n\n#### Features\n \nIf available, Zombienet uses the Prometheus operator to oversee monitoring and visibility. This configuration ensures that only essential networking-related pods are deployed. Using the Prometheus operator, Zombienet improves its ability to monitor and manage network activities within the Kubernetes cluster efficiently."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 4, "depth": 3, "title": "Podman", "anchor": "podman", "start_char": 7333, "end_char": 8929, "estimated_token_count": 374, "token_estimator": "heuristic-v1", "text": "### Podman\n\nPodman is a daemonless container engine for developing, managing, and running Open Container Initiative (OCI) containers and container images on Linux-based systems. Zombienet supports Podman rootless as a provider on Linux machines. Although Podman has support for macOS through an internal virtual machine (VM), the Zombienet provider code requires Podman to run natively on Linux.\n\n#### Requirements\n \nTo use Podman as a provider, you need to have Podman installed on your system. You can install Podman by following the instructions provided on the [Podman website](https://podman.io/getting-started/installation){target=\\_blank}.\n\n#### Features\n \nUsing Podman, Zombienet deploys additional pods to enhance the monitoring and visibility of the active network. Specifically, pods for [Prometheus](https://prometheus.io/){target=\\_blank}, [Tempo](https://grafana.com/docs/tempo/latest/operations/monitor/){target=\\_blank}, and [Grafana](https://grafana.com/){target=\\_blank} are included in the deployment. Grafana is configured with Prometheus and Tempo as data sources.\n\nUpon launching Zombienet, access to these monitoring services is facilitated through specific URLs provided in the output:\n\n- **Prometheus**: `http://127.0.0.1:34123`\n- **Tempo**: `http://127.0.0.1:34125`\n- **Grafana**: `http://127.0.0.1:41461`\n\nIt's important to note that Grafana is deployed with default administrator access. \n \nWhen network operations cease, either from halting a running spawn with the `Ctrl+C` command or test completion, Zombienet automatically removes all associated pods."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 5, "depth": 3, "title": "Local Provider", "anchor": "local-provider", "start_char": 8929, "end_char": 10889, "estimated_token_count": 420, "token_estimator": "heuristic-v1", "text": "### Local Provider\n\nThe Zombienet local provider, also called native, enables you to run nodes as local processes in your environment.\n\n#### Requirements\n \nYou must have the necessary binaries for your network (such as `polkadot` and `polkadot-parachain`). These binaries should be available in your PATH, allowing Zombienet to spawn the nodes as local processes.\n\nTo install the necessary binaries, you can use the Zombienet CLI command:\n\n```bash\nzombienet setup polkadot polkadot-parachain\n```\n\nThis command will download and prepare the necessary binaries for Zombienet's use.\n\nIf you need to use a custom binary, ensure the binary is available in your PATH. You can also specify the binary path in the network configuration file. The following example uses the custom [OpenZeppelin template](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\\_blank}:\n\nFirst, clone the OpenZeppelin template repository using the following command:\n\n```bash\ngit clone https://github.com/OpenZeppelin/polkadot-runtime-templates \\\n&& cd polkadot-runtime-templates/generic-template\n```\n\nNext, run the command to build the custom binary:\n\n```bash\ncargo build --release\n```\n\nFinally, add the custom binary to your PATH as follows:\n\n```bash\nexport PATH=$PATH:INSERT_PATH_TO_RUNTIME_TEMPLATES/parachain-template-node/target/release\n```\n\nAlternatively, you can specify the binary path in the network configuration file. The local provider exclusively utilizes the command configuration for nodes, which supports both relative and absolute paths. You can employ the `default_command` configuration to specify the binary for spawning all nodes in the relay chain.\n\n```toml\n[relaychain]\nchain = \"rococo-local\"\ndefault_command = \"./bin-v1.6.0/polkadot\"\n\n[parachain]\nid = 1000\n\n [parachain.collators]\n name = \"collator01\"\n command = \"./target/release/parachain-template-node\"\n```\n\n#### Features\n\nThe local provider does not offer any additional features."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 6, "depth": 2, "title": "Configure Zombienet", "anchor": "configure-zombienet", "start_char": 10889, "end_char": 11501, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Configure Zombienet\n\nEffective network configuration is crucial for deploying and managing blockchain systems. Zombienet simplifies this process by offering versatile configuration options in both JSON and TOML formats. Whether setting up a simple test network or a complex multi-node system, Zombienet's tools provide the flexibility to customize every aspect of your network's setup.\n\nThe following sections will explore the structure and usage of Zombienet configuration files, explain key settings for network customization, and walk through CLI commands and flags to optimize your development workflow."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 7, "depth": 3, "title": "Configuration Files", "anchor": "configuration-files", "start_char": 11501, "end_char": 11979, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "### Configuration Files\n\nThe network configuration file can be either JSON or TOML format. The Zombienet repository also provides a collection of [example configuration files](https://github.com/paritytech/zombienet/tree/main/examples){target=\\_blank} that can be used as a reference.\n\nEach section may include provider-specific keys that aren't recognized by other providers. For example, if you use the local provider, any references to images for nodes will be disregarded."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 8, "depth": 3, "title": "CLI Usage", "anchor": "cli-usage", "start_char": 11979, "end_char": 13771, "estimated_token_count": 502, "token_estimator": "heuristic-v1", "text": "### CLI Usage\n\nZombienet provides a CLI that allows interaction with the tool. The CLI can receive commands and flags to perform different kinds of operations. These operations use the following syntax:\n\n```bash\nzombienet \n```\n\nThe following sections will guide you through the primary usage of the Zombienet CLI and the available commands and flags.\n\n#### CLI Commands\n\n- **`spawn `**: Spawn the network defined in the [configuration file](#configuration-files).\n- **`test `**: Run tests on the spawned network using the assertions and tests defined in the [test file](/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/#the-test-file){target=\\_blank}.\n- **`setup `**: Set up the Zombienet development environment to download and use the `polkadot` or `polkadot-parachain` executable.\n- **`convert `**: Transforms a [polkadot-launch](https://github.com/paritytech/polkadot-launch){target=\\_blank} configuration file with a `.js` or `.json` extension into a Zombienet configuration file.\n- **`version`**: Prints Zombienet version.\n- **`help`**: Prints help information.\n\n#### CLI Flags\n\nYou can use the following flags to customize the behavior of the CLI:\n\n- **`-p`, `--provider`**: Override the [provider](#providers) to use.\n- **`-d`, `--dir`**: Specify a directory path for placing the network files instead of using the default temporary path.\n- **`-f`, `--force`**: Force override all prompt commands.\n- **`-l`, `--logType`**: Type of logging on the console. Defaults to `table`.\n- **`-m`, `--monitor`**: Start as monitor and don't auto clean up network.\n- **`-c`, `--spawn-concurrency`**: Number of concurrent spawning processes to launch. Defaults to `1`.\n- **`-h`, `--help`**: Display help for command."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 9, "depth": 3, "title": "Settings", "anchor": "settings", "start_char": 13771, "end_char": 16964, "estimated_token_count": 866, "token_estimator": "heuristic-v1", "text": "### Settings\n\nThrough the keyword `settings`, it's possible to define the general settings for the network. The available keys are:\n\n- **`global_volumes?`** ++\"GlobalVolume[]\"++: A list of global volumes to use.\n\n ??? child \"`GlobalVolume` interface definition\"\n ```js\n export interface GlobalVolume {\n name: string;\n fs_type: string;\n mount_path: string;\n }\n ```\n\n- **`bootnode`** ++\"boolean\"++: Add bootnode to network. Defaults to `true`.\n- **`bootnode_domain?`** ++\"string\"++: Domain to use for bootnode.\n- **`timeout`** ++\"number\"++: Global timeout to use for spawning the whole network.\n- **`node_spawn_timeout?`** ++\"number\"++: Timeout to spawn pod/process.\n- **`grafana?`** ++\"boolean\"++: Deploy an instance of Grafana.\n- **`prometheus?`** ++\"boolean\"++: Deploy an instance of Prometheus.\n- **`telemetry?`** ++\"boolean\"++: Enable telemetry for the network.\n- **`jaeger_agent?`** ++\"string\"++: The Jaeger agent endpoint passed to the nodes. Only available on Kubernetes.\n- **`tracing_collator_url?`** ++\"string\"++: The URL of the tracing collator used to query by the tracing assertion. Should be tempo query compatible.\n- **`tracing_collator_service_name?`** ++\"string\"++: Service name for tempo query frontend. Only available on Kubernetes. Defaults to `tempo-tempo-distributed-query-frontend`.\n- **`tracing_collator_service_namespace?`** ++\"string\"++: Namespace where tempo is running. Only available on Kubernetes. Defaults to `tempo`.\n- **`tracing_collator_service_port?`** ++\"number\"++: Port of the query instance of tempo. Only available on Kubernetes. Defaults to `3100`.\n- **`enable_tracing?`** ++\"boolean\"++: Enable the tracing system. Only available on Kubernetes. Defaults to `true`.\n- **`provider`** ++\"string\"++: Provider to use. Default is `kubernetes`\".\n- **`polkadot_introspector?`** ++\"boolean\"++: Deploy an instance of polkadot-introspector. Only available on Podman and Kubernetes. Defaults to `false`.\n- **`backchannel?`** ++\"boolean\"++: Deploy an instance of backchannel server. Only available on Kubernetes. Defaults to `false`.\n- **`image_pull_policy?`** ++\"string\"++: Image pull policy to use in the network. Possible values are `Always`, `IfNotPresent`, and `Never`.\n- **`local_ip?`** ++\"string\"++: IP used for exposing local services (rpc/metrics/monitors). Defaults to `\"127.0.0.1\"`.\n- **`global_delay_network_global_settings?`** ++\"number\"++: Delay in seconds to apply to the network.\n- **`node_verifier?`** ++\"string\"++: Specify how to verify node readiness or deactivate by using `None`. Possible values are `None` and `Metric`. Defaults to `Metric`.\n\nFor example, the following configuration file defines a minimal example for the settings:\n\n=== \"TOML\"\n\n ```toml title=\"base-example.toml\"\n [settings]\n timeout = 1000\n bootnode = false\n provider = \"kubernetes\"\n backchannel = false\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"base-example.json\"\n {\n \"settings\": {\n \"timeout\": 1000,\n \"bootnode\": false,\n \"provider\": \"kubernetes\",\n \"backchannel\": false,\n \"...\": {}\n },\n \"...\": {}\n }\n\n ```"} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 10, "depth": 3, "title": "Relay Chain Configuration", "anchor": "relay-chain-configuration", "start_char": 16964, "end_char": 28518, "estimated_token_count": 2794, "token_estimator": "heuristic-v1", "text": "### Relay Chain Configuration\n\nYou can use the `relaychain` keyword to define further parameters for the relay chain at start-up. The available keys are:\n\n- **`default_command?`** ++\"string\"++: The default command to run. Defaults to `polkadot`.\n- **`default_image?`** ++\"string\"++: The default Docker image to use.\n- **`default_resources?`** ++\"Resources\"++: Represents the resource limits/reservations the nodes need by default. Only available on Kubernetes.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`default_db_snapshot?`** ++\"string\"++: The default database snapshot to use.\n- **`default_prometheus_prefix`** ++\"string\"++: A parameter for customizing the metric's prefix. Defaults to `substrate`.\n- **`default_substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`default_keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n- **`chain`** ++\"string\"++: The chain name.\n- **`chain_spec_path?`** ++\"string\"++: Path to the chain spec file. Should be the plain version to allow customizations.\n- **`chain_spec_command?`** ++\"string\"++: Command to generate the chain spec. It can't be used in combination with `chain_spec_path`.\n- **`default_args?`** ++\"string[]\"++: An array of arguments to use as default to pass to the command.\n- **`default_overrides?`** ++\"Override[]\"++: An array of overrides to upload to the node.\n\n ??? child \"`Override` interface definition\"\n ```js\n export interface Override {\n local_path: string;\n remote_name: string;\n } \n ```\n\n- **`random_nominators_count?`** ++\"number\"++: If set and the stacking pallet is enabled, Zombienet will generate the input quantity of nominators and inject them into the genesis.\n- **`max_nominations`** ++\"number\"++: The max number of nominations allowed by a nominator. Should match the value set in the runtime. Defaults to `24`.\n- **`nodes?`** ++\"Node[]\"++: An array of nodes to spawn. It is further defined in the [Node Configuration](#node-configuration) section.\n- **`node_groups?`** ++\"NodeGroup[]\"++: An array of node groups to spawn. It is further defined in the [Node Group Configuration](#node-group-configuration) section.\n- **`total_node_in_group?`** ++\"number\"++: The total number of nodes in the group. Defaults to `1`.\n- **`genesis`** ++\"JSON\"++: The genesis configuration.\n- **`default_delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\n#### Node Configuration\n\nOne specific key capable of receiving more subkeys is the `nodes` key. This key is used to define further parameters for the nodes. The available keys:\n\n- **`name`** ++\"string\"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`).\n- **`image?`** ++\"string\"++: Override default Docker image to use for this node.\n- **`command?`** ++\"string\"++: Override default command to run.\n- **`command_with_args?`** ++\"string\"++: Override default command and arguments.\n- **`args?`** ++\"string[]\"++: Arguments to be passed to the command.\n- **`env?`** ++\"envVars[]\"++: Environment variables to set in the container.\n\n ??? child \"`envVars` interface definition\"\n ```js\n export interface EnvVars {\n name: string;\n value: string;\n }\n ```\n\n- **`prometheus_prefix?`** ++\"string\"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`.\n- **`db_snapshot?`** ++\"string\"++: Database snapshot to use.\n- **`substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`resources?`** ++\"Resources\"++: Represent the resources limits/reservations needed by the node.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n- **`validator`** ++\"boolean\"++: Pass the `--validator` flag to the command. Defaults to `true`.\n- **`invulnerable`** ++\"boolean\"++: If true, add the node to invulnerables in the chain spec. Defaults to `false`.\n- **`balance`** ++\"number\"++: Balance to set in balances for node's account. Defaults to `2000000000000`.\n- **`bootnodes?`** ++\"string[]\"++: Array of bootnodes to use.\n- **`add_to_bootnodes?`** ++\"boolean\"++: Add this node to the bootnode list. Defaults to `false`.\n- **`ws_port?`** ++\"number\"++: WS port to use.\n- **`rpc_port?`** ++\"number\"++: RPC port to use.\n- **`prometheus_port?`** ++\"number\"++: Prometheus port to use.\n- **`p2p_cert_hash?`** ++\"string\"++: Libp2p certhash to use with webRTC transport.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\nThe following configuration file defines a minimal example for the relay chain, including the `nodes` key:\n\n=== \"TOML\"\n\n ```toml title=\"relaychain-example-nodes.toml\"\n [relaychain]\n default_command = \"polkadot\"\n default_image = \"polkadot-debug:master\"\n chain = \"rococo-local\"\n chain_spec_path = \"INSERT_PATH_TO_CHAIN_SPEC\"\n default_args = [\"--chain\", \"rococo-local\"]\n\n [[relaychain.nodes]]\n name = \"alice\"\n validator = true\n balance = 1000000000000\n\n [[relaychain.nodes]]\n name = \"bob\"\n validator = true\n balance = 1000000000000\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"relaychain-example-nodes.json\"\n {\n \"relaychain\": {\n \"default_command\": \"polkadot\",\n \"default_image\": \"polkadot-debug:master\",\n \"chain\": \"rococo-local\",\n \"chain_spec_path\": \"INSERT_PATH_TO_CHAIN-SPEC.JSON\",\n \"default_args\": [\"--chain\", \"rococo-local\"],\n \"nodes\": [\n {\n \"name\": \"alice\",\n \"validator\": true,\n \"balance\": 1000000000000\n },\n {\n \"name\": \"bob\",\n \"validator\": true,\n \"balance\": 1000000000000\n }\n ]\n }\n }\n\n ```\n\n#### Node Group Configuration\n\nThe `node_groups` key defines further parameters for the node groups. The available keys are:\n\n- **`name`** ++\"string\"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`).\n- **`image?`** ++\"string\"++: Override default Docker image to use for this node.\n- **`command?`** ++\"string\"++: Override default command to run.\n- **`args?`** ++\"string[]\"++: Arguments to be passed to the command.\n- **`env?`** ++\"envVars[]\"++: Environment variables to set in the container.\n \n ??? child \"`envVars` interface definition\"\n ```js\n export interface EnvVars {\n name: string;\n value: string;\n }\n ```\n\n- **`overrides?`** ++\"Override[]\"++: Array of overrides definitions.\n\n ??? child \"`Override` interface definition\"\n ```js\n export interface Override {\n local_path: string;\n remote_name: string;\n }\n ```\n\n- **`prometheus_prefix?`** ++\"string\"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`.\n- **`db_snapshot?`** ++\"string\"++: Database snapshot to use.\n- **`substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`resources?`** ++\"Resources\"++: Represent the resources limits/reservations needed by the node.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n- **`count`** ++\"number | string\"++: Number of nodes to launch for this group.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\nThe following configuration file defines a minimal example for the relay chain, including the `node_groups` key:\n\n=== \"TOML\"\n\n ```toml title=\"relaychain-example-node-groups.toml\"\n [relaychain]\n default_command = \"polkadot\"\n default_image = \"polkadot-debug:master\"\n chain = \"rococo-local\"\n chain_spec_path = \"INSERT_PATH_TO_CHAIN_SPEC\"\n default_args = [\"--chain\", \"rococo-local\"]\n\n [[relaychain.node_groups]]\n name = \"group-1\"\n count = 2\n image = \"polkadot-debug:master\"\n command = \"polkadot\"\n args = [\"--chain\", \"rococo-local\"]\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"relaychain-example-node-groups.json\"\n {\n \"relaychain\": {\n \"default_command\": \"polkadot\",\n \"default_image\": \"polkadot-debug:master\",\n \"chain\": \"rococo-local\",\n \"chain_spec_path\": \"INSERT_PATH_TO_CHAIN-SPEC.JSON\",\n \"default_args\": [\"--chain\", \"rococo-local\"],\n \"node_groups\": [\n {\n \"name\": \"group-1\",\n \"count\": 2,\n \"image\": \"polkadot-debug:master\",\n \"command\": \"polkadot\",\n \"args\": [\"--chain\", \"rococo-local\"]\n }\n ],\n \"...\": {}\n },\n \"...\": {}\n }\n\n ```"} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 11, "depth": 3, "title": "Parachain Configuration", "anchor": "parachain-configuration", "start_char": 28518, "end_char": 39691, "estimated_token_count": 2716, "token_estimator": "heuristic-v1", "text": "### Parachain Configuration\n\nThe `parachain` keyword defines further parameters for the parachain. The available keys are:\n\n- **`id`** ++\"number\"++: The id to assign to this parachain. Must be unique.\n- **`chain?`** ++\"string\"++: The chain name.\n- **`force_decorator?`** ++\"string\"++: Force the use of a specific decorator.\n- **`genesis?`** ++\"JSON\"++: The genesis configuration.\n- **`balance?`** ++\"number\"++: Balance to set in balances for parachain's account.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\n- **`add_to_genesis?`** ++\"boolean\"++: Flag to add parachain to genesis or register in runtime. Defaults to `true`.\n- **`register_para?`** ++\"boolean\"++: Flag to specify whether the para should be registered. The `add_to_genesis` flag must be set to false for this flag to have any effect. Defaults to `true`.\n- **`onboard_as_parachain?`** ++\"boolean\"++: Flag to specify whether the para should be onboarded as a parachain, rather than remaining a parathread. Defaults to `true`.\n- **`genesis_wasm_path?`** ++\"string\"++: Path to the Wasm file to use.\n- **`genesis_wasm_generator?`** ++\"string\"++: Command to generate the Wasm file.\n- **`genesis_state_path?`** ++\"string\"++: Path to the state file to use.\n- **`genesis_state_generator?`** ++\"string\"++: Command to generate the state file.\n- **`chain_spec_path?`** ++\"string\"++: Path to the chain spec file.\n- **`chain_spec_command?`** ++\"string\"++: Command to generate the chain spec.\n- **`cumulus_based?`** ++\"boolean\"++: Flag to use cumulus command generation. Defaults to `true`.\n- **`bootnodes?`** ++\"string[]\"++: Array of bootnodes to use.\n- **`prometheus_prefix?`** ++\"string\"++: Parameter for customizing the metric's prefix for all parachain nodes/collators. Defaults to `substrate`.\n- **`collator?`** ++\"Collator\"++: Further defined in the [Collator Configuration](#collator-configuration) section.\n- **`collator_groups?`** ++\"CollatorGroup[]\"++: An array of collator groups to spawn. It is further defined in the [Collator Groups Configuration](#collator-groups-configuration) section.\n \nFor example, the following configuration file defines a minimal example for the parachain:\n\n=== \"TOML\"\n\n ```toml title=\"parachain-example.toml\"\n [parachain]\n id = 100\n add_to_genesis = true\n cumulus_based = true\n genesis_wasm_path = \"INSERT_PATH_TO_WASM\"\n genesis_state_path = \"INSERT_PATH_TO_STATE\"\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"parachain-example.json\"\n {\n \"parachain\": {\n \"id\": 100,\n \"add_to_genesis\": true,\n \"cumulus_based\": true,\n \"genesis_wasm_path\": \"INSERT_PATH_TO_WASM\",\n \"genesis_state_path\": \"INSERT_PATH_TO_STATE\",\n \"...\": {}\n },\n \"...\": {}\n }\n\n ```\n\n#### Collator Configuration\n\nOne specific key capable of receiving more subkeys is the `collator` key. This key defines further parameters for the nodes. The available keys are:\n\n- **`name`** ++\"string\"++: Name of the collator. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`).\n- **`image?`** ++\"string\"++: Image to use for the collator.\n- **`command_with_args?`** ++\"string\"++: Overrides both command and arguments for the collator.\n- **`validator`** ++\"boolean\"++: Pass the `--validator` flag to the command. Defaults to `true`.\n- **`invulnerable`** ++\"boolean\"++: If true, add the collator to invulnerables in the chain spec. Defaults to `false`.\n- **`balance`** ++\"number\"++: Balance to set in balances for collator's account. Defaults to `2000000000000`.\n- **`bootnodes?`** ++\"string[]\"++: Array of bootnodes to use.\n- **`add_to_bootnodes?`** ++\"boolean\"++: Add this collator to the bootnode list. Defaults to `false`.\n- **`ws_port?`** ++\"number\"++: WS port to use.\n- **`rpc_port?`** ++\"number\"++: RPC port to use.\n- **`prometheus_port?`** ++\"number\"++: Prometheus port to use.\n- **`p2p_port?`** ++\"number\"++: P2P port to use.\n- **`p2p_cert_hash?`** ++\"string\"++: Libp2p certhash to use with webRTC transport.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\n- **`command?`** ++\"string\"++: Override default command to run.\n- **`args?`** ++\"string[]\"++: Arguments to be passed to the command.\n- **`env?`** ++\"envVars[]\"++: Environment variables to set in the container.\n\n ??? child \"`envVars` interface definition\"\n ```js\n export interface EnvVars {\n name: string;\n value: string;\n }\n ```\n\n- **`overrides?`** ++\"Override[]\"++: Array of overrides definitions.\n\n ??? child \"`Override` interface definition\"\n ```js\n export interface Override {\n local_path: string;\n remote_name: string;\n }\n ```\n\n- **`prometheus_prefix?`** ++\"string\"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`.\n- **`db_snapshot?`** ++\"string\"++: Database snapshot to use.\n- **`substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`resources?`** ++\"Resources\"++: Represent the resources limits/reservations needed by the node.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n\nThe configuration file below defines a minimal example for the collator:\n\n=== \"TOML\"\n\n ```toml title=\"collator-example.toml\"\n [parachain]\n id = 100\n add_to_genesis = true\n cumulus_based = true\n genesis_wasm_path = \"INSERT_PATH_TO_WASM\"\n genesis_state_path = \"INSERT_PATH_TO_STATE\"\n\n [[parachain.collators]]\n name = \"alice\"\n image = \"polkadot-parachain\"\n command = \"polkadot-parachain\"\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"collator-example.json\"\n {\n \"parachain\": {\n \"id\": 100,\n \"add_to_genesis\": true,\n \"cumulus_based\": true,\n \"genesis_wasm_path\": \"INSERT_PATH_TO_WASM\",\n \"genesis_state_path\": \"INSERT_PATH_TO_STATE\",\n \"collators\": [\n {\n \"name\": \"alice\",\n \"image\": \"polkadot-parachain\",\n \"command\": \"polkadot-parachain\",\n \"...\": {}\n }\n ]\n },\n \"...\": {}\n }\n\n ```\n\n#### Collator Groups Configuration\n\nThe `collator_groups` key defines further parameters for the collator groups. The available keys are:\n\n- **`name`** ++\"string\"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`).\n- **`image?`** ++\"string\"++: Override default Docker image to use for this node.\n- **`command?`** ++\"string\"++: Override default command to run.\n- **`args?`** ++\"string[]\"++: Arguments to be passed to the command.\n- **`env?`** ++\"envVars[]\"++: Environment variables to set in the container.\n\n ??? child \"`envVars` interface definition\"\n ```js\n export interface EnvVars {\n name: string;\n value: string;\n }\n ```\n\n- **`overrides?`** ++\"Override[]\"++: Array of overrides definitions.\n\n ??? child \"`Override` interface definition\"\n ```js\n export interface Override {\n local_path: string;\n remote_name: string;\n }\n ```\n\n- **`prometheus_prefix?`** ++\"string\"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`.\n- **`db_snapshot?`** ++\"string\"++: Database snapshot to use.\n- **`substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`resources?`** ++\"Resources\"++: Represent the resources limits/reservations needed by the node.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n- **`count`** ++\"number | string\"++: Number of nodes to launch for this group.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\nFor instance, the configuration file below defines a minimal example for the collator groups:\n\n=== \"TOML\"\n\n ```toml title=\"collator-groups-example.toml\"\n [parachain]\n id = 100\n add_to_genesis = true\n cumulus_based = true\n genesis_wasm_path = \"INSERT_PATH_TO_WASM\"\n genesis_state_path = \"INSERT_PATH_TO_STATE\"\n\n [[parachain.collator_groups]]\n name = \"group-1\"\n count = 2\n image = \"polkadot-parachain\"\n command = \"polkadot-parachain\"\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"collator-groups-example.json\"\n {\n \"parachain\": {\n \"id\": 100,\n \"add_to_genesis\": true,\n \"cumulus_based\": true,\n \"genesis_wasm_path\": \"INSERT_PATH_TO_WASM\",\n \"genesis_state_path\": \"INSERT_PATH_TO_STATE\",\n \"collator_groups\": [\n {\n \"name\": \"group-1\",\n \"count\": 2,\n \"image\": \"polkadot-parachain\",\n \"command\": \"polkadot-parachain\",\n \"...\": {}\n }\n ]\n },\n \"...\": {}\n }\n\n ```"} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 12, "depth": 3, "title": "XCM Configuration", "anchor": "xcm-configuration", "start_char": 39691, "end_char": 40622, "estimated_token_count": 206, "token_estimator": "heuristic-v1", "text": "### XCM Configuration\n\nYou can use the `hrmp_channels` keyword to define further parameters for the XCM channels at start-up. The available keys are:\n\n- **`hrmp_channels`** ++\"HrmpChannelsConfig[]\"++: Array of Horizontal Relay-routed Message Passing (HRMP) channel configurations.\n\n ??? child \"`HrmpChannelsConfig` interface definition\"\n ```js\n export interface HrmpChannelsConfig {\n sender: number;\n recipient: number;\n max_capacity: number;\n max_message_size: number;\n }\n ```\n Each of the `HrmpChannelsConfig` keys are defined as follows:\n\n - **`sender` ++\"number\"++**: Parachain ID of the sender.\n - **`recipient` ++\"number\"++**: Parachain ID of the recipient.\n - **`max_capacity` ++\"number\"++**: Maximum capacity of the HRMP channel.\n - **`max_message_size` ++\"number\"++**: Maximum message size allowed in the HRMP channel."} -{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Get Started", "index": 13, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 40622, "end_char": 41636, "estimated_token_count": 254, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
    \n\n- External __Zombienet Support__\n\n ---\n\n [Parity Technologies](https://www.parity.io/){target=\\_blank} has designed and developed this framework, now maintained by the Zombienet team. \n\n For further support and information, refer to the following contact points:\n\n [:octicons-arrow-right-24: Zombienet repository](https://github.com/paritytech/zombienet){target=\\_blank}\n\n [:octicons-arrow-right-24: Element public channel](https://matrix.to/#/!FWyuEyNvIFygLnWNMh:parity.io?via=parity.io&via=matrix.org&via=web3.foundation){target=\\_blank}\n\n\n- Tutorial __Spawn a Basic Chain with Zombienet__\n\n ---\n\n Learn to spawn, connect to and monitor a basic blockchain network with Zombienet, using customizable configurations for streamlined development and debugging.\n\n [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/spawn-basic-chain/)\n\n
    "} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 0, "depth": 2, "title": "Authority", "anchor": "authority", "start_char": 416, "end_char": 897, "estimated_token_count": 119, "token_estimator": "heuristic-v1", "text": "## Authority\n\nThe role in a blockchain that can participate in consensus mechanisms. \n\n- **[GRANDPA](#grandpa)**: The authorities vote on chains they consider final.\n- **[Blind Assignment of Blockchain Extension](#blind-assignment-of-blockchain-extension-babe) (BABE)**: The authorities are also [block authors](#block-author).\n\nAuthority sets can be used as a basis for consensus mechanisms such as the [Nominated Proof of Stake (NPoS)](#nominated-proof-of-stake-npos) protocol."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 1, "depth": 2, "title": "Authority Round (Aura)", "anchor": "authority-round-aura", "start_char": 897, "end_char": 1416, "estimated_token_count": 118, "token_estimator": "heuristic-v1", "text": "## Authority Round (Aura)\n\nA deterministic [consensus](#consensus) protocol where block production is limited to a rotating list of [authorities](#authority) that take turns creating blocks. In authority round (Aura) consensus, most online authorities are assumed to be honest. It is often used in combination with [GRANDPA](#grandpa) as a [hybrid consensus](#hybrid-consensus) protocol.\n\nLearn more by reading the official [Aura consensus algorithm](https://openethereum.github.io/Aura){target=\\_blank} wiki article."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 2, "depth": 2, "title": "Blind Assignment of Blockchain Extension (BABE)", "anchor": "blind-assignment-of-blockchain-extension-babe", "start_char": 1416, "end_char": 1930, "estimated_token_count": 124, "token_estimator": "heuristic-v1", "text": "## Blind Assignment of Blockchain Extension (BABE)\n\nA [block authoring](#block-author) protocol similar to [Aura](#authority-round-aura), except [authorities](#authority) win [slots](#slot) based on a Verifiable Random Function (VRF) instead of the round-robin selection method. The winning authority can select a chain and submit a new block.\n\nLearn more by reading the official Web3 Foundation [BABE research document](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 3, "depth": 2, "title": "Block Author", "anchor": "block-author", "start_char": 1930, "end_char": 2099, "estimated_token_count": 35, "token_estimator": "heuristic-v1", "text": "## Block Author\n\nThe node responsible for the creation of a block, also called _block producers_. In a Proof of Work (PoW) blockchain, these nodes are called _miners_."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 4, "depth": 2, "title": "Byzantine Fault Tolerance (BFT)", "anchor": "byzantine-fault-tolerance-bft", "start_char": 2099, "end_char": 2527, "estimated_token_count": 79, "token_estimator": "heuristic-v1", "text": "## Byzantine Fault Tolerance (BFT)\n\nThe ability of a distributed computer network to remain operational if a certain proportion of its nodes or [authorities](#authority) are defective or behaving maliciously. A distributed network is typically considered Byzantine fault tolerant if it can remain functional, with up to one-third of nodes assumed to be defective, offline, actively malicious, and part of a coordinated attack."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 5, "depth": 3, "title": "Byzantine Failure", "anchor": "byzantine-failure", "start_char": 2527, "end_char": 2667, "estimated_token_count": 26, "token_estimator": "heuristic-v1", "text": "### Byzantine Failure\n\nThe loss of a network service due to node failures that exceed the proportion of nodes required to reach consensus."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 6, "depth": 3, "title": "Practical Byzantine Fault Tolerance (pBFT)", "anchor": "practical-byzantine-fault-tolerance-pbft", "start_char": 2667, "end_char": 3007, "estimated_token_count": 71, "token_estimator": "heuristic-v1", "text": "### Practical Byzantine Fault Tolerance (pBFT)\n\nAn early approach to Byzantine fault tolerance (BFT), practical Byzantine fault tolerance (pBFT) systems tolerate Byzantine behavior from up to one-third of participants.\n\nThe communication overhead for such systems is `O(n²)`, where `n` is the number of nodes (participants) in the system."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 7, "depth": 3, "title": "Preimage", "anchor": "preimage", "start_char": 3007, "end_char": 3284, "estimated_token_count": 74, "token_estimator": "heuristic-v1", "text": "### Preimage\n\nA preimage is the data that is input into a hash function to calculate a hash. Since a hash function is a [one-way function](https://en.wikipedia.org/wiki/One-way_function){target=\\_blank}, the output, the hash, cannot be used to reveal the input, the preimage."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 8, "depth": 2, "title": "Call", "anchor": "call", "start_char": 3284, "end_char": 3561, "estimated_token_count": 56, "token_estimator": "heuristic-v1", "text": "## Call\n\nIn the context of pallets containing functions to be dispatched to the runtime, `Call` is an enumeration data type that describes the functions that can be dispatched with one variant per pallet. A `Call` represents a [dispatch](#dispatchable) data structure object."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 9, "depth": 2, "title": "Chain Specification", "anchor": "chain-specification", "start_char": 3561, "end_char": 4014, "estimated_token_count": 84, "token_estimator": "heuristic-v1", "text": "## Chain Specification \n\nA chain specification file defines the properties required to run a node in an active or new Polkadot SDK-built network. It often contains the initial genesis runtime code, network properties (such as the network's name), the initial state for some pallets, and the boot node list. The chain specification file makes it easy to use a single Polkadot SDK codebase as the foundation for multiple independently configured chains."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 10, "depth": 2, "title": "Collator", "anchor": "collator", "start_char": 4014, "end_char": 4353, "estimated_token_count": 98, "token_estimator": "heuristic-v1", "text": "## Collator\n\nAn [author](#block-author) of a [parachain](#parachain) network.\nThey aren't [authorities](#authority) in themselves, as they require a [relay chain](#relay-chain) to coordinate [consensus](#consensus).\n\nMore details are found on the [Polkadot Collator Wiki](https://wiki.polkadot.com/learn/learn-collator/){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 11, "depth": 2, "title": "Collective", "anchor": "collective", "start_char": 4353, "end_char": 4593, "estimated_token_count": 54, "token_estimator": "heuristic-v1", "text": "## Collective\n\nMost often used to refer to an instance of the Collective pallet on Polkadot SDK-based networks such as [Kusama](#kusama) or [Polkadot](#polkadot) if the Collective pallet is part of the FRAME-based runtime for the network."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 12, "depth": 2, "title": "Consensus", "anchor": "consensus", "start_char": 4593, "end_char": 4984, "estimated_token_count": 86, "token_estimator": "heuristic-v1", "text": "## Consensus\n\nConsensus is the process blockchain nodes use to agree on a chain's canonical fork. It is composed of [authorship](#block-author), finality, and [fork-choice rule](#fork-choice-rulestrategy). In the Polkadot ecosystem, these three components are usually separate and the term consensus often refers specifically to authorship.\n\nSee also [hybrid consensus](#hybrid-consensus)."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 13, "depth": 2, "title": "Consensus Algorithm", "anchor": "consensus-algorithm", "start_char": 4984, "end_char": 5546, "estimated_token_count": 120, "token_estimator": "heuristic-v1", "text": "## Consensus Algorithm\n\nEnsures a set of [actors](#authority)—who don't necessarily trust each other—can reach an agreement about the state as the result of some computation. Most consensus algorithms assume that up to one-third of the actors or nodes can be [Byzantine fault tolerant](#byzantine-fault-tolerance-bft).\n\nConsensus algorithms are generally concerned with ensuring two properties:\n\n- **Safety**: Indicating that all honest nodes eventually agreed on the state of the chain.\n- **Liveness**: Indicating the ability of the chain to keep progressing."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 14, "depth": 2, "title": "Consensus Engine", "anchor": "consensus-engine", "start_char": 5546, "end_char": 5885, "estimated_token_count": 77, "token_estimator": "heuristic-v1", "text": "## Consensus Engine\n\nThe node subsystem responsible for consensus tasks.\n\nFor detailed information about the consensus strategies of the [Polkadot](#polkadot) network, see the [Polkadot Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\\_blank} blog series.\n\nSee also [hybrid consensus](#hybrid-consensus)."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 15, "depth": 2, "title": "Coretime", "anchor": "coretime", "start_char": 5885, "end_char": 6685, "estimated_token_count": 177, "token_estimator": "heuristic-v1", "text": "## Coretime\n\nThe time allocated for utilizing a core, measured in relay chain blocks. There are two types of coretime: *on-demand* and *bulk*.\n\nOn-demand coretime refers to coretime acquired through bidding in near real-time for the validation of a single parachain block on one of the cores reserved specifically for on-demand orders. They are available as an on-demand coretime pool. Set of cores that are available on-demand. Cores reserved through bulk coretime could also be made available in the on-demand coretime pool, in parts or in entirety.\n\nBulk coretime is a fixed duration of continuous coretime represented by an NFT that can be split, shared, or resold. It is managed by the [Broker pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_broker/index.html){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 16, "depth": 2, "title": "Development Phrase", "anchor": "development-phrase", "start_char": 6685, "end_char": 7343, "estimated_token_count": 157, "token_estimator": "heuristic-v1", "text": "## Development Phrase\n\nA [mnemonic phrase](https://en.wikipedia.org/wiki/Mnemonic#For_numerical_sequences_and_mathematical_operations){target=\\_blank} that is intentionally made public.\n\nWell-known development accounts, such as Alice, Bob, Charlie, Dave, Eve, and Ferdie, are generated from the same secret phrase:\n\n```\nbottom drive obey lake curtain smoke basket hold race lonely fit walk\n```\n\nMany tools in the Polkadot SDK ecosystem, such as [`subkey`](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/bin/utils/subkey){target=\\_blank}, allow you to implicitly specify an account using a derivation path such as `//Alice`."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 17, "depth": 2, "title": "Digest", "anchor": "digest", "start_char": 7343, "end_char": 7655, "estimated_token_count": 66, "token_estimator": "heuristic-v1", "text": "## Digest\n\nAn extensible field of the [block header](#header) that encodes information needed by several actors in a blockchain network, including:\n\n- [Light clients](#light-client) for chain synchronization.\n- Consensus engines for block verification.\n- The runtime itself, in the case of pre-runtime digests."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 18, "depth": 2, "title": "Dispatchable", "anchor": "dispatchable", "start_char": 7655, "end_char": 7953, "estimated_token_count": 62, "token_estimator": "heuristic-v1", "text": "## Dispatchable\n\nFunction objects that act as the entry points in FRAME [pallets](#pallet). Internal or external entities can call them to interact with the blockchain’s state. They are a core aspect of the runtime logic, handling [transactions](#transaction) and other state-changing operations."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 19, "depth": 2, "title": "Events", "anchor": "events", "start_char": 7953, "end_char": 8385, "estimated_token_count": 90, "token_estimator": "heuristic-v1", "text": "## Events\n\nA means of recording that some particular [state](#state) transition happened.\n\nIn the context of [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities), events are composable data types that each [pallet](#pallet) can individually define. Events in FRAME are implemented as a set of transient storage items inspected immediately after a block has been executed and reset during block initialization."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 20, "depth": 2, "title": "Executor", "anchor": "executor", "start_char": 8385, "end_char": 9021, "estimated_token_count": 134, "token_estimator": "heuristic-v1", "text": "## Executor\n\nA means of executing a function call in a given [runtime](#runtime) with a set of dependencies.\nThere are two orchestration engines in Polkadot SDK, _WebAssembly_ and _native_.\n\n- The _native executor_ uses a natively compiled runtime embedded in the node to execute calls. This is a performance optimization available to up-to-date nodes.\n\n- The _WebAssembly executor_ uses a [Wasm](#webassembly-wasm) binary and a Wasm interpreter to execute calls. The binary is guaranteed to be up-to-date regardless of the version of the blockchain node because it is persisted in the [state](#state) of the Polkadot SDK-based chain."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 21, "depth": 2, "title": "Existential Deposit", "anchor": "existential-deposit", "start_char": 9021, "end_char": 9761, "estimated_token_count": 179, "token_estimator": "heuristic-v1", "text": "## Existential Deposit\n\nThe minimum balance an account is allowed to have in the [Balances pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/index.html){target=\\_blank}. Accounts cannot be created with a balance less than the existential deposit amount. \n\nIf an account balance drops below this amount, the Balances pallet uses [a FRAME System API](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.dec_ref){target=\\_blank} to drop its references to that account.\n\nIf the Balances pallet reference to an account is dropped, the account can be [reaped](https://paritytech.github.io/substrate/master/frame_system/pallet/struct.Pallet.html#method.allow_death){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 22, "depth": 2, "title": "Extrinsic", "anchor": "extrinsic", "start_char": 9761, "end_char": 10377, "estimated_token_count": 130, "token_estimator": "heuristic-v1", "text": "## Extrinsic\n\nA general term for data that originates outside the runtime, is included in a block, and leads to some action. This includes user-initiated transactions and inherent transactions placed into the block by the block builder.\n\nIt is a SCALE-encoded array typically consisting of a version number, signature, and varying data types indicating the resulting runtime function to be called. Extrinsics can take two forms: [inherents](#inherent-transactions) and [transactions](#transaction). \n\nFor more technical details, see the [Polkadot spec](https://spec.polkadot.network/id-extrinsics){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 23, "depth": 2, "title": "Fork Choice Rule/Strategy", "anchor": "fork-choice-rulestrategy", "start_char": 10377, "end_char": 10723, "estimated_token_count": 79, "token_estimator": "heuristic-v1", "text": "## Fork Choice Rule/Strategy\n\nA fork choice rule or strategy helps determine which chain is valid when reconciling several network forks. A common fork choice rule is the [longest chain](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/struct.LongestChain.html){target=\\_blank}, in which the chain with the most blocks is selected."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 24, "depth": 2, "title": "FRAME (Framework for Runtime Aggregation of Modularized Entities)", "anchor": "frame-framework-for-runtime-aggregation-of-modularized-entities", "start_char": 10723, "end_char": 11169, "estimated_token_count": 97, "token_estimator": "heuristic-v1", "text": "## FRAME (Framework for Runtime Aggregation of Modularized Entities)\n\nEnables developers to create blockchain [runtime](#runtime) environments from a modular set of components called [pallets](#pallet). It utilizes a set of procedural macros to construct runtimes.\n\n[Visit the Polkadot SDK docs for more details on FRAME.](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank}"} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 25, "depth": 2, "title": "Full Node", "anchor": "full-node", "start_char": 11169, "end_char": 11448, "estimated_token_count": 48, "token_estimator": "heuristic-v1", "text": "## Full Node\n\nA node that prunes historical states, keeping only recently finalized block states to reduce storage needs. Full nodes provide current chain state access and allow direct submission and validation of [extrinsics](#extrinsic), maintaining network decentralization."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 26, "depth": 2, "title": "Genesis Configuration", "anchor": "genesis-configuration", "start_char": 11448, "end_char": 11783, "estimated_token_count": 63, "token_estimator": "heuristic-v1", "text": "## Genesis Configuration\n\nA mechanism for specifying the initial state of a blockchain. By convention, this initial state or first block is commonly referred to as the genesis state or genesis block. The genesis configuration for Polkadot SDK-based chains is accomplished by way of a [chain specification](#chain-specification) file."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 27, "depth": 2, "title": "GRANDPA", "anchor": "grandpa", "start_char": 11783, "end_char": 12139, "estimated_token_count": 101, "token_estimator": "heuristic-v1", "text": "## GRANDPA\n\nA deterministic finality mechanism for blockchains that is implemented in the [Rust](https://www.rust-lang.org/){target=\\_blank} programming language.\n\nThe [formal specification](https://github.com/w3f/consensus/blob/master/pdf/grandpa-old.pdf){target=\\_blank} is maintained by the [Web3 Foundation](https://web3.foundation/){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 28, "depth": 2, "title": "Header", "anchor": "header", "start_char": 12139, "end_char": 12379, "estimated_token_count": 44, "token_estimator": "heuristic-v1", "text": "## Header\n\nA structure that aggregates the information used to summarize a block. Primarily, it consists of cryptographic information used by [light clients](#light-client) to get minimally secure but very efficient chain synchronization."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 29, "depth": 2, "title": "Hybrid Consensus", "anchor": "hybrid-consensus", "start_char": 12379, "end_char": 12793, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "## Hybrid Consensus\n\nA blockchain consensus protocol that consists of independent or loosely coupled mechanisms for [block production](#block-author) and finality.\n\nHybrid consensus allows the chain to grow as fast as probabilistic consensus protocols, such as [Aura](#authority-round-aura), while maintaining the same level of security as deterministic finality consensus protocols, such as [GRANDPA](#grandpa)."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 30, "depth": 2, "title": "Inherent Transactions", "anchor": "inherent-transactions", "start_char": 12793, "end_char": 13259, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "## Inherent Transactions\n\nA special type of unsigned transaction, referred to as _inherents_, that enables a block authoring node to insert information that doesn't require validation directly into a block.\n\nOnly the block-authoring node that calls the inherent transaction function can insert data into its block. In general, validators assume the data inserted using an inherent transaction is valid and reasonable even if it can't be deterministically verified."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 31, "depth": 2, "title": "JSON-RPC", "anchor": "json-rpc", "start_char": 13259, "end_char": 13600, "estimated_token_count": 77, "token_estimator": "heuristic-v1", "text": "## JSON-RPC\n\nA stateless, lightweight remote procedure call protocol encoded in JavaScript Object Notation (JSON). JSON-RPC provides a standard way to call functions on a remote system by using JSON.\n\nFor Polkadot SDK, this protocol is implemented through the [Parity JSON-RPC](https://github.com/paritytech/jsonrpc){target=\\_blank} crate."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 32, "depth": 2, "title": "Keystore", "anchor": "keystore", "start_char": 13600, "end_char": 13685, "estimated_token_count": 16, "token_estimator": "heuristic-v1", "text": "## Keystore\n\nA subsystem for managing keys for the purpose of producing new blocks."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 33, "depth": 2, "title": "Kusama", "anchor": "kusama", "start_char": 13685, "end_char": 14379, "estimated_token_count": 174, "token_estimator": "heuristic-v1", "text": "## Kusama\n\n[Kusama](https://kusama.network/){target=\\_blank} is a Polkadot SDK-based blockchain that implements a design similar to the [Polkadot](#polkadot) network.\n\nKusama is a [canary](https://en.wiktionary.org/wiki/canary_in_a_coal_mine){target=\\_blank} network and is referred to as [Polkadot's \"wild cousin.\"](https://wiki.polkadot.com/learn/learn-comparisons-kusama/){target=\\_blank}.\n\nAs a canary network, Kusama is expected to be more stable than a test network like [Westend](#westend) but less stable than a production network like [Polkadot](#polkadot). Kusama is controlled by its network participants and is intended to be stable enough to encourage meaningful experimentation."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 34, "depth": 2, "title": "libp2p", "anchor": "libp2p", "start_char": 14379, "end_char": 14655, "estimated_token_count": 67, "token_estimator": "heuristic-v1", "text": "## libp2p\n\nA peer-to-peer networking stack that allows the use of many transport mechanisms, including WebSockets (usable in a web browser).\n\nPolkadot SDK uses the [Rust implementation](https://github.com/libp2p/rust-libp2p){target=\\_blank} of the `libp2p` networking stack."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 35, "depth": 2, "title": "Light Client", "anchor": "light-client", "start_char": 14655, "end_char": 14993, "estimated_token_count": 77, "token_estimator": "heuristic-v1", "text": "## Light Client\n\nA type of blockchain node that doesn't store the [chain state](#state) or produce blocks.\n\nA light client can verify cryptographic primitives and provides a [remote procedure call (RPC)](https://en.wikipedia.org/wiki/Remote_procedure_call){target=\\_blank} server, enabling blockchain users to interact with the network."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 36, "depth": 2, "title": "Metadata", "anchor": "metadata", "start_char": 14993, "end_char": 15189, "estimated_token_count": 34, "token_estimator": "heuristic-v1", "text": "## Metadata\n\nData that provides information about one or more aspects of a system.\nThe metadata that exposes information about a Polkadot SDK blockchain enables you to interact with that system."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 37, "depth": 2, "title": "Nominated Proof of Stake (NPoS)", "anchor": "nominated-proof-of-stake-npos", "start_char": 15189, "end_char": 15416, "estimated_token_count": 51, "token_estimator": "heuristic-v1", "text": "## Nominated Proof of Stake (NPoS)\n\nA method for determining [validators](#validator) or _[authorities](#authority)_ based on a willingness to commit their stake to the proper functioning of one or more block-producing nodes."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 38, "depth": 2, "title": "Oracle", "anchor": "oracle", "start_char": 15416, "end_char": 15653, "estimated_token_count": 42, "token_estimator": "heuristic-v1", "text": "## Oracle\n\nAn entity that connects a blockchain to a non-blockchain data source. Oracles enable the blockchain to access and act upon information from existing data sources and incorporate data from non-blockchain systems and services."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 39, "depth": 2, "title": "Origin", "anchor": "origin", "start_char": 15653, "end_char": 16143, "estimated_token_count": 126, "token_estimator": "heuristic-v1", "text": "## Origin\n\nA [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitive that identifies the source of a [dispatched](#dispatchable) function call into the [runtime](#runtime). The FRAME System pallet defines three built-in [origins](#origin). As a [pallet](#pallet) developer, you can also define custom origins, such as those defined by the [Collective pallet](https://paritytech.github.io/substrate/master/pallet_collective/enum.RawOrigin.html){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 40, "depth": 2, "title": "Pallet", "anchor": "pallet", "start_char": 16143, "end_char": 16434, "estimated_token_count": 75, "token_estimator": "heuristic-v1", "text": "## Pallet\n\nA module that can be used to extend the capabilities of a [FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities)-based [runtime](#runtime).\nPallets bundle domain-specific logic with runtime primitives like [events](#events) and [storage items](#storage-item)."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 41, "depth": 2, "title": "Parachain", "anchor": "parachain", "start_char": 16434, "end_char": 16690, "estimated_token_count": 66, "token_estimator": "heuristic-v1", "text": "## Parachain\n\nA parachain is a blockchain that derives shared infrastructure and security from a _[relay chain](#relay-chain)_.\nYou can learn more about parachains on the [Polkadot Wiki](https://wiki.polkadot.com/learn/learn-parachains/){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 42, "depth": 2, "title": "Paseo", "anchor": "paseo", "start_char": 16690, "end_char": 17144, "estimated_token_count": 95, "token_estimator": "heuristic-v1", "text": "## Paseo\n\nPaseo TestNet provisions testing on Polkadot's \"production\" runtime, which means less chance of feature or code mismatch when developing parachain apps. Specifically, after the [Polkadot Technical fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\\_blank} proposes a runtime upgrade for Polkadot, this TestNet is updated, giving a period where the TestNet will be ahead of Polkadot to allow for testing."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 43, "depth": 2, "title": "Polkadot", "anchor": "polkadot", "start_char": 17144, "end_char": 17445, "estimated_token_count": 71, "token_estimator": "heuristic-v1", "text": "## Polkadot\n\nThe [Polkadot network](https://polkadot.com/){target=\\_blank} is a blockchain that serves as the central hub of a heterogeneous blockchain network. It serves the role of the [relay chain](#relay-chain) and provides shared infrastructure and security to support [parachains](#parachain)."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 44, "depth": 2, "title": "Polkadot Cloud", "anchor": "polkadot-cloud", "start_char": 17445, "end_char": 18083, "estimated_token_count": 97, "token_estimator": "heuristic-v1", "text": "## Polkadot Cloud\n\nPolkadot Cloud is a platform for deploying resilient, customizable and scalable Web3 applications through Polkadot's functionality. It encompasses the wider Polkadot network infrastructure and security layer where parachains operate. The platform enables users to launch Ethereum-compatible chains, build specialized blockchains, and flexibly manage computing resources through on-demand or bulk coretime purchases. Initially launched with basic parachain functionality, Polkadot Cloud has evolved to offer enhanced flexibility with features like coretime, elastic scaling, and async backing for improved performance."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 45, "depth": 2, "title": "Polkadot Hub", "anchor": "polkadot-hub", "start_char": 18083, "end_char": 18491, "estimated_token_count": 68, "token_estimator": "heuristic-v1", "text": "## Polkadot Hub\n\nPolkadot Hub is a Layer 1 platform that serves as the primary entry point to the Polkadot ecosystem, providing essential functionality without requiring parachain deployment. It offers core services including smart contracts, identity management, staking, governance, and interoperability with other ecosystems, making it simple and fast for both builders and users to get started in Web3."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 46, "depth": 2, "title": "PolkaVM", "anchor": "polkavm", "start_char": 18491, "end_char": 18774, "estimated_token_count": 50, "token_estimator": "heuristic-v1", "text": "## PolkaVM\n\nPolkaVM is a custom virtual machine optimized for performance, leveraging a RISC-V-based architecture to support Solidity and any language that compiles to RISC-V. It is specifically designed for the Polkadot ecosystem, enabling smart contract deployment and execution."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 47, "depth": 2, "title": "Relay Chain", "anchor": "relay-chain", "start_char": 18774, "end_char": 19090, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "## Relay Chain\n\nRelay chains are blockchains that provide shared infrastructure and security to the [parachains](#parachain) in the network. In addition to providing [consensus](#consensus) capabilities, relay chains allow parachains to communicate and exchange digital assets without needing to trust one another."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 48, "depth": 2, "title": "Rococo", "anchor": "rococo", "start_char": 19090, "end_char": 19342, "estimated_token_count": 54, "token_estimator": "heuristic-v1", "text": "## Rococo\n\nA [parachain](#parachain) test network for the Polkadot network. The [Rococo](#rococo) network is a Polkadot SDK-based blockchain with an October 14, 2024 deprecation date. Development teams are encouraged to use the Paseo TestNet instead."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 49, "depth": 2, "title": "Runtime", "anchor": "runtime", "start_char": 19342, "end_char": 19679, "estimated_token_count": 73, "token_estimator": "heuristic-v1", "text": "## Runtime\n\nThe runtime represents the [state transition function](#state-transition-function-stf) for a blockchain. In Polkadot SDK, the runtime is stored as a [Wasm](#webassembly-wasm) binary in the chain state. The Runtime is stored under a unique state key and can be modified during the execution of the state transition function."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 50, "depth": 2, "title": "Slot", "anchor": "slot", "start_char": 19679, "end_char": 19959, "estimated_token_count": 79, "token_estimator": "heuristic-v1", "text": "## Slot\n\nA fixed, equal interval of time used by consensus engines such as [Aura](#authority-round-aura) and [BABE](#blind-assignment-of-blockchain-extension-babe). In each slot, a subset of [authorities](#authority) is permitted, or obliged, to [author](#block-author) a block."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 51, "depth": 2, "title": "Sovereign Account", "anchor": "sovereign-account", "start_char": 19959, "end_char": 20461, "estimated_token_count": 91, "token_estimator": "heuristic-v1", "text": "## Sovereign Account\n\nThe unique account identifier for each chain in the relay chain ecosystem. It is often used in cross-consensus (XCM) interactions to sign XCM messages sent to the relay chain or other chains in the ecosystem.\n\nThe sovereign account for each chain is a root-level account that can only be accessed using the Sudo pallet or through governance. The account identifier is calculated by concatenating the Blake2 hash of a specific text string and the registered parachain identifier."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 52, "depth": 2, "title": "SS58 Address Format", "anchor": "ss58-address-format", "start_char": 20461, "end_char": 21014, "estimated_token_count": 128, "token_estimator": "heuristic-v1", "text": "## SS58 Address Format\n\nA public key address based on the Bitcoin [`Base-58-check`](https://en.bitcoin.it/wiki/Base58Check_encoding){target=\\_blank} encoding. Each Polkadot SDK SS58 address uses a `base-58` encoded value to identify a specific account on a specific Polkadot SDK-based chain\n\nThe [canonical `ss58-registry`](https://github.com/paritytech/ss58-registry){target=\\_blank} provides additional details about the address format used by different Polkadot SDK-based chains, including the network prefix and website used for different networks"} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 53, "depth": 2, "title": "State Transition Function (STF)", "anchor": "state-transition-function-stf", "start_char": 21014, "end_char": 21243, "estimated_token_count": 46, "token_estimator": "heuristic-v1", "text": "## State Transition Function (STF)\n\nThe logic of a blockchain that determines how the state changes when a block is processed. In Polkadot SDK, the state transition function is effectively equivalent to the [runtime](#runtime)."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 54, "depth": 2, "title": "Storage Item", "anchor": "storage-item", "start_char": 21243, "end_char": 21606, "estimated_token_count": 92, "token_estimator": "heuristic-v1", "text": "## Storage Item\n\n[FRAME](#frame-framework-for-runtime-aggregation-of-modularized-entities) primitives that provide type-safe data persistence capabilities to the [runtime](#runtime).\nLearn more in the [storage items](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/index.html){target=\\_blank} reference document in the Polkadot SDK."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 55, "depth": 2, "title": "Substrate", "anchor": "substrate", "start_char": 21606, "end_char": 21888, "estimated_token_count": 73, "token_estimator": "heuristic-v1", "text": "## Substrate\n\nA flexible framework for building modular, efficient, and upgradeable blockchains. Substrate is written in the [Rust](https://www.rust-lang.org/){target=\\_blank} programming language and is maintained by [Parity Technologies](https://www.parity.io/){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 56, "depth": 2, "title": "Transaction", "anchor": "transaction", "start_char": 21888, "end_char": 22179, "estimated_token_count": 66, "token_estimator": "heuristic-v1", "text": "## Transaction\n\nAn [extrinsic](#extrinsic) that includes a signature that can be used to verify the account authorizing it inherently or via [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\\_blank}."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 57, "depth": 2, "title": "Transaction Era", "anchor": "transaction-era", "start_char": 22179, "end_char": 22458, "estimated_token_count": 51, "token_estimator": "heuristic-v1", "text": "## Transaction Era\n\nA definable period expressed as a range of block numbers during which a transaction can be included in a block.\nTransaction eras are used to protect against transaction replay attacks if an account is reaped and its replay-protecting nonce is reset to zero."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 58, "depth": 2, "title": "Trie (Patricia Merkle Tree)", "anchor": "trie-patricia-merkle-tree", "start_char": 22458, "end_char": 23204, "estimated_token_count": 155, "token_estimator": "heuristic-v1", "text": "## Trie (Patricia Merkle Tree)\n\nA data structure used to represent sets of key-value pairs and enables the items in the data set to be stored and retrieved using a cryptographic hash. Because incremental changes to the data set result in a new hash, retrieving data is efficient even if the data set is very large. With this data structure, you can also prove whether the data set includes any particular key-value pair without access to the entire data set.\n\nIn Polkadot SDK-based blockchains, state is stored in a trie data structure that supports the efficient creation of incremental digests. This trie is exposed to the [runtime](#runtime) as [a simple key/value map](#storage-item) where both keys and values can be arbitrary byte arrays."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 59, "depth": 2, "title": "Validator", "anchor": "validator", "start_char": 23204, "end_char": 23407, "estimated_token_count": 34, "token_estimator": "heuristic-v1", "text": "## Validator\n\nA validator is a node that participates in the consensus mechanism of the network. Its roles include block production, transaction validation, network integrity, and security maintenance."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 60, "depth": 2, "title": "WebAssembly (Wasm)", "anchor": "webassembly-wasm", "start_char": 23407, "end_char": 23870, "estimated_token_count": 113, "token_estimator": "heuristic-v1", "text": "## WebAssembly (Wasm)\n\nAn execution architecture that allows for the efficient, platform-neutral expression of\ndeterministic, machine-executable logic.\n\n[Wasm](https://webassembly.org/){target=\\_blank} can be compiled from many languages, including\nthe [Rust](https://www.rust-lang.org/){target=\\_blank} programming language. Polkadot SDK-based chains use a Wasm binary to provide portable [runtimes](#runtime) that can be included as part of the chain's state."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 61, "depth": 2, "title": "Weight", "anchor": "weight", "start_char": 23870, "end_char": 24596, "estimated_token_count": 133, "token_estimator": "heuristic-v1", "text": "## Weight\n\nA convention used in Polkadot SDK-based blockchains to measure and manage the time it takes to validate a block.\nPolkadot SDK defines one unit of weight as one picosecond of execution time on reference hardware.\n\nThe maximum block weight should be equivalent to one-third of the target block time with an allocation of one-third each for:\n\n- Block construction\n- Network propagation\n- Import and verification\n\nBy defining weights, you can trade-off the number of transactions per second and the hardware required to maintain the target block time appropriate for your use case. Weights are defined in the runtime, meaning you can tune them using runtime updates to keep up with hardware and software improvements."} -{"page_id": "reference-glossary", "page_title": "Glossary", "index": 62, "depth": 2, "title": "Westend", "anchor": "westend", "start_char": 24596, "end_char": 24739, "estimated_token_count": 32, "token_estimator": "heuristic-v1", "text": "## Westend\n\nWestend is a Parity-maintained, Polkadot SDK-based blockchain that serves as a test network for the [Polkadot](#polkadot) network."} -{"page_id": "reference-governance-origins-tracks", "page_title": "Origins and Tracks", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 22, "end_char": 833, "estimated_token_count": 128, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot's OpenGov system empowers decentralized decision-making and active community participation by tailoring the governance process to the impact of proposed changes. Through a system of origins and tracks, OpenGov ensures that every referendum receives the appropriate scrutiny, balancing security, inclusivity, and efficiency.\n\nThis guide will help you understand the role of origins in classifying proposals by privilege and priority. You will learn how tracks guide proposals through tailored stages like voting, confirmation, and enactment and how to select the correct origin for your referendum to align with community expectations and network governance.\n\nOrigins and tracks are vital in streamlining the governance workflow and maintaining Polkadot's resilience and adaptability."} -{"page_id": "reference-governance-origins-tracks", "page_title": "Origins and Tracks", "index": 1, "depth": 2, "title": "Origins", "anchor": "origins", "start_char": 833, "end_char": 1886, "estimated_token_count": 200, "token_estimator": "heuristic-v1", "text": "## Origins\n\nOrigins are the foundation of Polkadot's OpenGov governance system. They categorize proposals by privilege and define their decision-making rules. Each origin corresponds to a specific level of importance and risk, guiding how referendums progress through the governance process.\n\n- High-privilege origins like Root Origin govern critical network changes, such as core software upgrades.\n- Lower-privilege origins like Small Spender handle minor requests, such as community project funding under 10,000 DOT.\n\nProposers select an origin based on the nature of their referendum. Origins determine parameters like approval thresholds, required deposits, and timeframes for voting and confirmation. Each origin is paired with a track, which acts as a roadmap for the proposal's lifecycle, including preparation, voting, and enactment.\n\nFor a detailed list of origins and their associated parameters, see the [Polkadot OpenGov Origins](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/){target=\\_blank} entry in the Polkadot Wiki."} -{"page_id": "reference-governance-origins-tracks", "page_title": "Origins and Tracks", "index": 2, "depth": 2, "title": "Tracks", "anchor": "tracks", "start_char": 1886, "end_char": 2836, "estimated_token_count": 175, "token_estimator": "heuristic-v1", "text": "## Tracks\n\nTracks define a referendum's journey from submission to enactment, tailoring governance parameters to the impact of proposed changes. Each track operates independently and includes several key stages:\n\n- **Preparation**: Time for community discussion before voting begins.\n- **Voting**: Period for token holders to cast their votes.\n- **Decision**: Finalization of results and determination of the proposal's outcome.\n- **Confirmation**: Period to verify sustained community support before enactment.\n- **Enactment**: Final waiting period before the proposal takes effect.\n\nTracks customize these stages with parameters like decision deposit requirements, voting durations, and approval thresholds, ensuring proposals from each origin receive the required scrutiny and process. For example, a runtime upgrade in the Root Origin track will have longer timeframes and stricter thresholds than a treasury request in the Small Spender track."} -{"page_id": "reference-governance-origins-tracks", "page_title": "Origins and Tracks", "index": 3, "depth": 2, "title": "Additional Resources", "anchor": "additional-resources", "start_char": 2836, "end_char": 3333, "estimated_token_count": 128, "token_estimator": "heuristic-v1", "text": "## Additional Resources\n\n- For a list of origins and tracks for Polkadot and Kusama, including associated parameters, see the [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#origins-and-tracks-info){target=\\_blank} entry in the Polkadot Wiki.\n\n- For a deeper dive into the approval and support system, see the [Approval and Support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\\_blank} entry of the Polkadot Wiki."} -{"page_id": "reference-governance", "page_title": "On-Chain Governance Overview", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 24, "end_char": 852, "estimated_token_count": 133, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot’s governance system exemplifies decentralized decision-making, empowering its community of stakeholders to shape the network’s future through active participation. The latest evolution, OpenGov, builds on Polkadot’s foundation by providing a more inclusive and efficient governance model.\n\nThis guide will explain the principles and structure of OpenGov and walk you through its key components, such as Origins, Tracks, and Delegation. You will learn about improvements over earlier governance systems, including streamlined voting processes and enhanced stakeholder participation.\n\nWith OpenGov, Polkadot achieves a flexible, scalable, and democratic governance framework that allows multiple proposals to proceed simultaneously, ensuring the network evolves in alignment with its community's needs."} -{"page_id": "reference-governance", "page_title": "On-Chain Governance Overview", "index": 1, "depth": 2, "title": "Governance Evolution", "anchor": "governance-evolution", "start_char": 852, "end_char": 1816, "estimated_token_count": 198, "token_estimator": "heuristic-v1", "text": "## Governance Evolution\n\nPolkadot’s governance journey began with [Governance V1](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#governance-summary){target=\\_blank}, a system that proved effective in managing treasury funds and protocol upgrades. However, it faced limitations, such as:\n\n- Slow voting cycles, causing delays in decision-making.\n- Inflexibility in handling multiple referendums, restricting scalability.\n\nTo address these challenges, Polkadot introduced OpenGov, a governance model designed for greater inclusivity, efficiency, and scalability. OpenGov replaces the centralized structures of Governance V1, such as the Council and Technical Committee, with a fully decentralized and dynamic framework.\n\nFor a full comparison of the historic and current governance models, visit the [Gov1 vs. Polkadot OpenGov](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#gov1-vs-polkadot-opengov){target=\\_blank} section of the Polkadot Wiki."} -{"page_id": "reference-governance", "page_title": "On-Chain Governance Overview", "index": 2, "depth": 2, "title": "OpenGov Key Features", "anchor": "opengov-key-features", "start_char": 1816, "end_char": 2574, "estimated_token_count": 139, "token_estimator": "heuristic-v1", "text": "## OpenGov Key Features\n\nOpenGov transforms Polkadot’s governance into a decentralized, stakeholder-driven model, eliminating centralized decision-making bodies like the Council. Key enhancements include:\n\n- **Decentralization**: Shifts all decision-making power to the public, ensuring a more democratic process.\n- **Enhanced delegation**: Allows users to delegate their votes to trusted experts across specific governance tracks.\n- **Simultaneous referendums**: Multiple proposals can progress at once, enabling faster decision-making.\n- **Polkadot Technical Fellowship**: A broad, community-driven group replacing the centralized Technical Committee.\n\nThis new system ensures Polkadot governance remains agile and inclusive, even as the ecosystem grows."} -{"page_id": "reference-governance", "page_title": "On-Chain Governance Overview", "index": 3, "depth": 2, "title": "Origins and Tracks", "anchor": "origins-and-tracks", "start_char": 2574, "end_char": 3654, "estimated_token_count": 248, "token_estimator": "heuristic-v1", "text": "## Origins and Tracks\n\nIn OpenGov, origins and tracks are central to managing proposals and votes.\n\n- **Origin**: Determines the authority level of a proposal (e.g., Treasury, Root) which decides the track of all referendums from that origin.\n- **Track**: Define the procedural flow of a proposal, such as voting duration, approval thresholds, and enactment timelines.\n\nDevelopers must be aware that referendums from different origins and tracks will take varying amounts of time to reach approval and enactment. The [Polkadot Technical Fellowship](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\\_blank} has the option to shorten this timeline by whitelisting a proposal and allowing it to be enacted through the [Whitelist Caller](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#whitelisted-caller){target=\\_blank} origin.\n\nVisit [Origins and Tracks Info](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#origins-and-tracks){target=\\_blank} for details on current origins and tracks, associated terminology, and parameters."} -{"page_id": "reference-governance", "page_title": "On-Chain Governance Overview", "index": 4, "depth": 2, "title": "Referendums", "anchor": "referendums", "start_char": 3654, "end_char": 4505, "estimated_token_count": 178, "token_estimator": "heuristic-v1", "text": "## Referendums\n\nIn OpenGov, anyone can submit a referendum, fostering an open and participatory system. The timeline for a referendum depends on the privilege level of the origin with more significant changes offering more time for community voting and participation before enactment. \n\nThe timeline for an individual referendum includes four distinct periods:\n\n- **Lead-in**: A minimum amount of time to allow for community participation, available room in the origin, and payment of the decision deposit. Voting is open during this period.\n- **Decision**: Voting continues.\n- **Confirmation**: Referendum must meet [approval and support](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#approval-and-support){target=\\_blank} criteria during entire period to avoid rejection.\n- **Enactment**: Changes approved by the referendum are executed."} -{"page_id": "reference-governance", "page_title": "On-Chain Governance Overview", "index": 5, "depth": 3, "title": "Vote on Referendums", "anchor": "vote-on-referendums", "start_char": 4505, "end_char": 5146, "estimated_token_count": 133, "token_estimator": "heuristic-v1", "text": "### Vote on Referendums\n\nVoters can vote with their tokens on each referendum. Polkadot uses a voluntary token locking mechanism, called conviction voting, as a way for voters to increase their voting power. A token holder signals they have a stronger preference for approving a proposal based upon their willingness to lock up tokens. Longer voluntary token locks are seen as a signal of continual approval and translate to increased voting weight.\n\nSee [Voting on a Referendum](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\\_blank} for a deeper look at conviction voting and related token locks."} -{"page_id": "reference-governance", "page_title": "On-Chain Governance Overview", "index": 6, "depth": 3, "title": "Delegate Voting Power", "anchor": "delegate-voting-power", "start_char": 5146, "end_char": 5929, "estimated_token_count": 168, "token_estimator": "heuristic-v1", "text": "### Delegate Voting Power\n\nThe OpenGov system also supports multi-role delegations, allowing token holders to assign their voting power on different tracks to entities with expertise in those areas. \n\nFor example, if a token holder lacks the technical knowledge to evaluate proposals on the [Root track](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#root){target=\\_blank}, they can delegate their voting power for that track to an expert they trust to vote in the best interest of the network. This ensures informed decision-making across tracks while maintaining flexibility for token holders.\n\nVisit [Multirole Delegation](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#multirole-delegation){target=\\_blank} for more details on delegating voting power."} -{"page_id": "reference-governance", "page_title": "On-Chain Governance Overview", "index": 7, "depth": 3, "title": "Cancel a Referendum", "anchor": "cancel-a-referendum", "start_char": 5929, "end_char": 6702, "estimated_token_count": 184, "token_estimator": "heuristic-v1", "text": "### Cancel a Referendum\n\nPolkadot OpenGov has two origins for rejecting ongoing referendums: \n\n- [**Referendum Canceller**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-canceller){target=\\_blank}: Cancels an active referendum when non-malicious errors occur and refunds the deposits to the originators.\n- [**Referendum Killer**](https://wiki.polkadot.com/learn/learn-polkadot-opengov-origins/#referendum-killer){target=\\_blank}: Used for urgent, malicious cases this origin instantly terminates an active referendum and slashes deposits.\n\nSee [Cancelling, Killing, and Blacklisting](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#cancelling-killing--blacklisting){target=\\_blank} for additional information on rejecting referendums."} -{"page_id": "reference-governance", "page_title": "On-Chain Governance Overview", "index": 8, "depth": 2, "title": "Additional Resources", "anchor": "additional-resources", "start_char": 6702, "end_char": 7493, "estimated_token_count": 230, "token_estimator": "heuristic-v1", "text": "## Additional Resources\n\n- **[Democracy pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/democracy/src){target=\\_blank}**: Handles administration of general stakeholder voting.\n- **[Gov2: Polkadot’s Next Generation of Decentralised Governance](https://medium.com/polkadot-network/gov2-polkadots-next-generation-of-decentralised-governance-4d9ef657d11b){target=\\_blank}**: Medium article by Gavin Wood.\n- **[Polkadot Direction](https://matrix.to/#/#Polkadot-Direction:parity.io){target=\\_blank}**: Matrix Element client.\n- **[Polkassembly](https://polkadot.polkassembly.io/){target=\\_blank}**: OpenGov dashboard and UI.\n- **[Polkadot.js Apps Governance](https://polkadot.js.org/apps/#/referenda){target=\\_blank}**: Overview of active referendums."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 12, "end_char": 597, "estimated_token_count": 101, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nAccounts are essential for managing identity, transactions, and governance on the network in the Polkadot SDK. Understanding these components is critical for seamless development and operation on the network, whether you're building or interacting with Polkadot-based chains.\n\nThis page will guide you through the essential aspects of accounts, including their data structure, balance types, reference counters, and address formats. You’ll learn how accounts are managed within the runtime, how balances are categorized, and how addresses are encoded and validated."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 1, "depth": 2, "title": "Account Data Structure", "anchor": "account-data-structure", "start_char": 597, "end_char": 862, "estimated_token_count": 42, "token_estimator": "heuristic-v1", "text": "## Account Data Structure\n\nAccounts are foundational to any blockchain, and the Polkadot SDK provides a flexible management system. This section explains how the Polkadot SDK defines accounts and manages their lifecycle through data structures within the runtime."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 2, "depth": 3, "title": "Account", "anchor": "account", "start_char": 862, "end_char": 3162, "estimated_token_count": 569, "token_estimator": "heuristic-v1", "text": "### Account\n\nThe [`Account` data type](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/type.Account.html){target=\\_blank} is a storage map within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\\_blank} that links an account ID to its corresponding data. This structure is fundamental for mapping account-related information within the chain.\n\nThe code snippet below shows how accounts are defined:\n\n```rs\n /// The full account information for a particular account ID.\n \t#[pallet::storage]\n \t#[pallet::getter(fn account)]\n \tpub type Account = StorageMap<\n \t\t_,\n \t\tBlake2_128Concat,\n \t\tT::AccountId,\n \t\tAccountInfo,\n \t\tValueQuery,\n \t>;\n```\n\nThe preceding code block defines a storage map named `Account`. The `StorageMap` is a type of on-chain storage that maps keys to values. In the `Account` map, the key is an account ID, and the value is the account's information. Here, `T` represents the generic parameter for the runtime configuration, which is defined by the pallet's configuration trait (`Config`).\n\nThe `StorageMap` consists of the following parameters:\n\n- **`_`**: Used in macro expansion and acts as a placeholder for the storage prefix type. Tells the macro to insert the default prefix during expansion.\n- **`Blake2_128Concat`**: The hashing function applied to keys in the storage map.\n- **`T: :AccountId`**: Represents the key type, which corresponds to the account’s unique ID.\n- **`AccountInfo`**: The value type stored in the map. For each account ID, the map stores an `AccountInfo` struct containing:\n\n - **`T::Nonce`**: A nonce for the account, which is incremented with each transaction to ensure transaction uniqueness.\n - **`T: :AccountData`**: Custom account data defined by the runtime configuration, which could include balances, locked funds, or other relevant information.\n \n- **`ValueQuery`**: Defines how queries to the storage map behave when no value is found; returns a default value instead of `None`.\n\nFor a detailed explanation of storage maps, see the [`StorageMap`](https://paritytech.github.io/polkadot-sdk/master/frame_support/storage/types/struct.StorageMap.html){target=\\_blank} entry in the Rust docs."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 3, "depth": 3, "title": "Account Info", "anchor": "account-info", "start_char": 3162, "end_char": 5825, "estimated_token_count": 617, "token_estimator": "heuristic-v1", "text": "### Account Info\n\nThe `AccountInfo` structure is another key element within the [System pallet](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/lib.rs.html){target=\\_blank}, providing more granular details about each account's state. This structure tracks vital data, such as the number of transactions and the account’s relationships with other modules.\n\n```rs\n/// Information of an account.\n#[derive(Clone, Eq, PartialEq, Default, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)]\npub struct AccountInfo {\n\t/// The number of transactions this account has sent.\n\tpub nonce: Nonce,\n\t/// The number of other modules that currently depend on this account's existence. The account\n\t/// cannot be reaped until this is zero.\n\tpub consumers: RefCount,\n\t/// The number of other modules that allow this account to exist. The account may not be reaped\n\t/// until this and `sufficients` are both zero.\n\tpub providers: RefCount,\n\t/// The number of modules that allow this account to exist for their own purposes only. The\n\t/// account may not be reaped until this and `providers` are both zero.\n\tpub sufficients: RefCount,\n\t/// The additional data that belongs to this account. Used to store the balance(s) in a lot of\n\t/// chains.\n\tpub data: AccountData,\n}\n```\n\nThe `AccountInfo` structure includes the following components:\n\n- **`nonce`**: Tracks the number of transactions initiated by the account, which ensures transaction uniqueness and prevents replay attacks.\n- **`consumers`**: Counts how many other modules or pallets rely on this account’s existence. The account cannot be removed from the chain (reaped) until this count reaches zero.\n- **`providers`**: Tracks how many modules permit this account’s existence. An account can only be reaped once both `providers` and `sufficients` are zero.\n- **`sufficients`**: Represents the number of modules that allow the account to exist for internal purposes, independent of any other modules.\n- **`AccountData`**: A flexible data structure that can be customized in the runtime configuration, usually containing balances or other user-specific data.\n\nThis structure helps manage an account's state and prevents its premature removal while it is still referenced by other on-chain data or modules. The [`AccountInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.AccountInfo.html){target=\\_blank} structure can vary as long as it satisfies the trait bounds defined by the `AccountData` associated type in the [`frame-system::pallet::Config`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/trait.Config.html){target=\\_blank} trait."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 4, "depth": 3, "title": "Account Reference Counters", "anchor": "account-reference-counters", "start_char": 5825, "end_char": 10918, "estimated_token_count": 1040, "token_estimator": "heuristic-v1", "text": "### Account Reference Counters\n\nPolkadot SDK uses reference counters to track an account’s dependencies across different runtime modules. These counters ensure that accounts remain active while data is associated with them.\n\nThe reference counters include:\n\n- **`consumers`**: Prevents account removal while other pallets still rely on the account.\n- **`providers`**: Ensures an account is active before other pallets store data related to it.\n- **`sufficients`**: Indicates the account’s independence, ensuring it can exist even without a native token balance, such as when holding sufficient alternative assets.\n\n#### Providers Reference Counters\n\nThe `providers` counter ensures that an account is ready to be depended upon by other runtime modules. For example, it is incremented when an account has a balance above the existential deposit, which marks the account as active.\n\nThe system requires this reference counter to be greater than zero for the `consumers` counter to be incremented, ensuring the account is stable before any dependencies are added.\n\n#### Consumers Reference Counters\n\nThe `consumers` counter ensures that the account cannot be reaped until all references to it across the runtime have been removed. This check prevents the accidental deletion of accounts that still have active on-chain data.\n\nIt is the user’s responsibility to clear out any data from other runtime modules if they wish to remove their account and reclaim their existential deposit.\n\n#### Sufficients Reference Counter\n\nThe `sufficients` counter tracks accounts that can exist independently without relying on a native account balance. This is useful for accounts holding other types of assets, like tokens, without needing a minimum balance in the native token.\n\nFor instance, the [Assets pallet](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\\_blank}, may increment this counter for an account holding sufficient tokens.\n\n#### Account Deactivation\n\nIn Polkadot SDK-based chains, an account is deactivated when its reference counters (such as `providers`, `consumers`, and `sufficient`) reach zero. These counters ensure the account remains active as long as other runtime modules or pallets reference it.\n\nWhen all dependencies are cleared and the counters drop to zero, the account becomes deactivated and may be removed from the chain (reaped). This is particularly important in Polkadot SDK-based blockchains, where accounts with balances below the existential deposit threshold are pruned from storage to conserve state resources.\n\nEach pallet that references an account has cleanup functions that decrement these counters when the pallet no longer depends on the account. Once these counters reach zero, the account is marked for deactivation.\n\n#### Updating Counters\n\nThe Polkadot SDK provides runtime developers with various methods to manage account lifecycle events, such as deactivation or incrementing reference counters. These methods ensure that accounts cannot be reaped while still in use.\n\nThe following helper functions manage these counters:\n\n- **`inc_consumers()`**: Increments the `consumer` reference counter for an account, signaling that another pallet depends on it.\n- **`dec_consumers()`**: Decrements the `consumer` reference counter, signaling that a pallet no longer relies on the account.\n- **`inc_providers()`**: Increments the `provider` reference counter, ensuring the account remains active.\n- **`dec_providers()`**: Decrements the `provider` reference counter, allowing for account deactivation when no longer in use.\n- **`inc_sufficients()`**: Increments the `sufficient` reference counter for accounts that hold sufficient assets.\n- **`dec_sufficients()`**: Decrements the `sufficient` reference counter.\n\nTo ensure proper account cleanup and lifecycle management, a corresponding decrement should be made for each increment action.\n\nThe `System` pallet offers three query functions to assist developers in tracking account states:\n\n- **[`can_inc_consumer()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_inc_consumer){target=\\_blank}**: Checks if the account can safely increment the consumer reference.\n- **[`can_dec_provider()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.can_dec_provider){target=\\_blank}**: Ensures that no consumers exist before allowing the decrement of the provider counter.\n- **[`is_provider_required()`](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html#method.is_provider_required){target=\\_blank}**: Verifies whether the account still has any active consumer references.\n\nThis modular and flexible system of reference counters tightly controls the lifecycle of accounts in Polkadot SDK-based blockchains, preventing the accidental removal or retention of unneeded accounts. You can refer to the [System pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/frame_system/pallet/struct.Pallet.html){target=\\_blank} for more details."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 5, "depth": 2, "title": "Account Balance Types", "anchor": "account-balance-types", "start_char": 10918, "end_char": 12838, "estimated_token_count": 465, "token_estimator": "heuristic-v1", "text": "## Account Balance Types\n\nIn the Polkadot ecosystem, account balances are categorized into different types based on how the funds are utilized and their availability. These balance types determine the actions that can be performed, such as transferring tokens, paying transaction fees, or participating in governance activities. Understanding these balance types helps developers manage user accounts and implement balance-dependent logic.\n\n!!! note \"A more efficient distribution of account balance types is in development\"\n Soon, pallets in the Polkadot SDK will implement the [`Fungible` trait](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\\_blank} (see the [tracking issue](https://github.com/paritytech/polkadot-sdk/issues/226){target=\\_blank} for more details). For example, the [`transaction-storage`](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_storage/index.html){target=\\_blank} pallet changed the implementation of the [`Currency`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/currency/index.html){target=\\_blank} trait (see the [Refactor transaction storage pallet to use fungible traits](https://github.com/paritytech/polkadot-sdk/pull/1800){target=\\_blank} PR for further details):\n\n ```rust\n type BalanceOf = <::Currency as Currency<::AccountId>>::Balance;\n ```\n \n To the [`Fungible`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/tokens/fungible/index.html){target=\\_blank} trait:\n\n ```rust\n type BalanceOf = <::Currency as FnInspect<::AccountId>>::Balance;\n ```\n \n This update will enable more efficient use of account balances, allowing the free balance to be utilized for on-chain activities such as setting proxies and managing identities."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 6, "depth": 3, "title": "Balance Types", "anchor": "balance-types", "start_char": 12838, "end_char": 15313, "estimated_token_count": 601, "token_estimator": "heuristic-v1", "text": "### Balance Types\n\nThe five main balance types are:\n\n- **Free balance**: Represents the total tokens available to the account for any on-chain activity, including staking, governance, and voting. However, it may not be fully spendable or transferrable if portions of it are locked or reserved.\n- **Locked balance**: Portions of the free balance that cannot be spent or transferred because they are tied up in specific activities like [staking](https://wiki.polkadot.com/learn/learn-staking/#nominating-validators){target=\\_blank}, [vesting](https://wiki.polkadot.com/learn/learn-guides-transfers/#vested-transfers-with-the-polkadot-js-ui){target=\\_blank}, or participating in [governance](https://wiki.polkadot.com/learn/learn-polkadot-opengov/#voting-on-a-referendum){target=\\_blank}. While the tokens remain part of the free balance, they are non-transferable for the duration of the lock.\n- **Reserved balance**: Funds locked by specific system actions, such as setting up an [identity](https://wiki.polkadot.com/learn/learn-identity/){target=\\_blank}, creating [proxies](https://wiki.polkadot.com/learn/learn-proxies/){target=\\_blank}, or submitting [deposits for governance proposals](https://wiki.polkadot.com/learn/learn-guides-polkadot-opengov/#claiming-opengov-deposits){target=\\_blank}. These tokens are not part of the free balance and cannot be spent unless they are unreserved.\n- **Spendable balance**: The portion of the free balance that is available for immediate spending or transfers. It is calculated by subtracting the maximum of locked or reserved amounts from the free balance, ensuring that existential deposit limits are met.\n- **Untouchable balance**: Funds that cannot be directly spent or transferred but may still be utilized for on-chain activities, such as governance participation or staking. These tokens are typically tied to certain actions or locked for a specific period.\n\nThe spendable balance is calculated as follows:\n\n```text\nspendable = free - max(locked - reserved, ED)\n```\n\nHere, `free`, `locked`, and `reserved` are defined above. The `ED` represents the [existential deposit](https://wiki.polkadot.com/learn/learn-accounts/#existential-deposit-and-reaping){target=\\_blank}, the minimum balance required to keep an account active and prevent it from being reaped. You may find you can't see all balance types when looking at your account via a wallet. Wallet providers often display only spendable, locked, and reserved balances."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 7, "depth": 3, "title": "Locks", "anchor": "locks", "start_char": 15313, "end_char": 17490, "estimated_token_count": 458, "token_estimator": "heuristic-v1", "text": "### Locks\n\nLocks are applied to an account's free balance, preventing that portion from being spent or transferred. Locks are automatically placed when an account participates in specific on-chain activities, such as staking or governance. Although multiple locks may be applied simultaneously, they do not stack. Instead, the largest lock determines the total amount of locked tokens.\n\nLocks follow these basic rules:\n\n- If different locks apply to varying amounts, the largest lock amount takes precedence.\n- If multiple locks apply to the same amount, the lock with the longest duration governs when the balance can be unlocked.\n\n#### Locks Example\n\nConsider an example where an account has 80 DOT locked for both staking and governance purposes like so:\n\n- 80 DOT is staked with a 28-day lock period.\n- 24 DOT is locked for governance with a 1x conviction and a 7-day lock period.\n- 4 DOT is locked for governance with a 6x conviction and a 224-day lock period.\n\nIn this case, the total locked amount is 80 DOT because only the largest lock (80 DOT from staking) governs the locked balance. These 80 DOT will be released at different times based on the lock durations. In this example, the 24 DOT locked for governance will be released first since the shortest lock period is seven days. The 80 DOT stake with a 28-day lock period is released next. Now, all that remains locked is the 4 DOT for governance. After 224 days, all 80 DOT (minus the existential deposit) will be free and transferable.\n\n![Illustration of Lock Example](/images/reference/parachains/accounts/accounts-01.webp)\n\n#### Edge Cases for Locks\n\nIn scenarios where multiple convictions and lock periods are active, the lock duration and amount are determined by the longest period and largest amount. For example, if you delegate with different convictions and attempt to undelegate during an active lock period, the lock may be extended for the full amount of tokens. For a detailed discussion on edge case lock behavior, see this [Stack Exchange post](https://substrate.stackexchange.com/questions/5067/delegating-and-undelegating-during-the-lock-period-extends-it-for-the-initial-am){target=\\_blank}."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 8, "depth": 3, "title": "Balance Types on Polkadot.js", "anchor": "balance-types-on-polkadotjs", "start_char": 17490, "end_char": 20529, "estimated_token_count": 603, "token_estimator": "heuristic-v1", "text": "### Balance Types on Polkadot.js\n\nPolkadot.js provides a user-friendly interface for managing and visualizing various account balances on Polkadot and Kusama networks. When interacting with Polkadot.js, you will encounter multiple balance types that are critical for understanding how your funds are distributed and restricted. This section explains how different balances are displayed in the Polkadot.js UI and what each type represents.\n\n![](/images/reference/parachains/accounts/accounts-02.webp)\n\nThe most common balance types displayed on Polkadot.js are:\n\n- **Total balance**: The total number of tokens available in the account. This includes all tokens, whether they are transferable, locked, reserved, or vested. However, the total balance does not always reflect what can be spent immediately. In this example, the total balance is 0.6274 KSM.\n\n- **Transferable balance**: Shows how many tokens are immediately available for transfer. It is calculated by subtracting the locked and reserved balances from the total balance. For example, if an account has a total balance of 0.6274 KSM and a transferable balance of 0.0106 KSM, only the latter amount can be sent or spent freely.\n\n- **Vested balance**: Tokens that allocated to the account but released according to a specific schedule. Vested tokens remain locked and cannot be transferred until fully vested. For example, an account with a vested balance of 0.2500 KSM means that this amount is owned but not yet transferable.\n\n- **Locked balance**: Tokens that are temporarily restricted from being transferred or spent. These locks typically result from participating in staking, governance, or vested transfers. In Polkadot.js, locked balances do not stack—only the largest lock is applied. For instance, if an account has 0.5500 KSM locked for governance and staking, the locked balance would display 0.5500 KSM, not the sum of all locked amounts.\n\n- **Reserved balance**: Refers to tokens locked for specific on-chain actions, such as setting an identity, creating a proxy, or making governance deposits. Reserved tokens are not part of the free balance, but can be freed by performing certain actions. For example, removing an identity would unreserve those funds.\n\n- **Bonded balance**: The tokens locked for staking purposes. Bonded tokens are not transferable until they are unbonded after the unbonding period.\n\n- **Redeemable balance**: The number of tokens that have completed the unbonding period and are ready to be unlocked and transferred again. For example, if an account has a redeemable balance of 0.1000 KSM, those tokens are now available for spending.\n\n- **Democracy balance**: Reflects the number of tokens locked for governance activities, such as voting on referenda. These tokens are locked for the duration of the governance action and are only released after the lock period ends.\n\nBy understanding these balance types and their implications, developers and users can better manage their funds and engage with on-chain activities more effectively."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 9, "depth": 2, "title": "Address Formats", "anchor": "address-formats", "start_char": 20529, "end_char": 20988, "estimated_token_count": 77, "token_estimator": "heuristic-v1", "text": "## Address Formats\n\nThe SS58 address format is a core component of the Polkadot SDK that enables accounts to be uniquely identified across Polkadot-based networks. This format is a modified version of Bitcoin's Base58Check encoding, specifically designed to accommodate the multi-chain nature of the Polkadot ecosystem. SS58 encoding allows each chain to define its own set of addresses while maintaining compatibility and checksum validation for security."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 10, "depth": 3, "title": "Basic Format", "anchor": "basic-format", "start_char": 20988, "end_char": 22230, "estimated_token_count": 295, "token_estimator": "heuristic-v1", "text": "### Basic Format\n\nSS58 addresses consist of three main components:\n\n```text\nbase58encode(concat(,
    , ))\n```\n\n- **Address type**: A byte or set of bytes that define the network (or chain) for which the address is intended. This ensures that addresses are unique across different Polkadot SDK-based chains.\n- **Address**: The public key of the account encoded as bytes.\n- **Checksum**: A hash-based checksum which ensures that addresses are valid and unaltered. The checksum is derived from the concatenated address type and address components, ensuring integrity.\n\nThe encoding process transforms the concatenated components into a Base58 string, providing a compact and human-readable format that avoids easily confused characters (e.g., zero '0', capital 'O', lowercase 'l'). This encoding function ([`encode`](https://docs.rs/bs58/latest/bs58/fn.encode.html){target=\\_blank}) is implemented exactly as defined in Bitcoin and IPFS specifications, using the same alphabet as both implementations.\n\nFor more details about the SS58 address format implementation, see the [`Ss58Codec`](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Ss58Codec.html){target=\\_blank} trait in the Rust Docs."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 11, "depth": 3, "title": "Address Type", "anchor": "address-type", "start_char": 22230, "end_char": 23165, "estimated_token_count": 203, "token_estimator": "heuristic-v1", "text": "### Address Type\n\nThe address type defines how an address is interpreted and to which network it belongs. Polkadot SDK uses different prefixes to distinguish between various chains and address formats:\n\n- **Address types `0-63`**: Simple addresses, commonly used for network identifiers.\n- **Address types `64-127`**: Full addresses that support a wider range of network identifiers.\n- **Address types `128-255`**: Reserved for future address format extensions.\n\nFor example, Polkadot’s main network uses an address type of 0, while Kusama uses 2. This ensures that addresses can be used without confusion between networks.\n\nThe address type is always encoded as part of the SS58 address, making it easy to quickly identify the network. Refer to the [SS58 registry](https://github.com/paritytech/ss58-registry){target=\\_blank} for the canonical listing of all address type identifiers and how they map to Polkadot SDK-based networks."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 12, "depth": 3, "title": "Address Length", "anchor": "address-length", "start_char": 23165, "end_char": 24359, "estimated_token_count": 268, "token_estimator": "heuristic-v1", "text": "### Address Length\n\nSS58 addresses can have different lengths depending on the specific format. Address lengths range from as short as 3 to 35 bytes, depending on the complexity of the address and network requirements. This flexibility allows SS58 addresses to adapt to different chains while providing a secure encoding mechanism.\n\n| Total | Type | Raw account | Checksum |\n|-------|------|-------------|----------|\n| 3 | 1 | 1 | 1 |\n| 4 | 1 | 2 | 1 |\n| 5 | 1 | 2 | 2 |\n| 6 | 1 | 4 | 1 |\n| 7 | 1 | 4 | 2 |\n| 8 | 1 | 4 | 3 |\n| 9 | 1 | 4 | 4 |\n| 10 | 1 | 8 | 1 |\n| 11 | 1 | 8 | 2 |\n| 12 | 1 | 8 | 3 |\n| 13 | 1 | 8 | 4 |\n| 14 | 1 | 8 | 5 |\n| 15 | 1 | 8 | 6 |\n| 16 | 1 | 8 | 7 |\n| 17 | 1 | 8 | 8 |\n| 35 | 1 | 32 | 2 |\n\nSS58 addresses also support different payload sizes, allowing a flexible range of account identifiers."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 13, "depth": 3, "title": "Checksum Types", "anchor": "checksum-types", "start_char": 24359, "end_char": 24824, "estimated_token_count": 94, "token_estimator": "heuristic-v1", "text": "### Checksum Types\n\nA checksum is applied to validate SS58 addresses. Polkadot SDK uses a Blake2b-512 hash function to calculate the checksum, which is appended to the address before encoding. The checksum length can vary depending on the address format (e.g., 1-byte, 2-byte, or longer), providing varying levels of validation strength.\n\nThe checksum ensures that an address is not modified or corrupted, adding an extra layer of security for account management."} -{"page_id": "reference-parachains-accounts", "page_title": "Polkadot SDK Accounts", "index": 14, "depth": 3, "title": "Validating Addresses", "anchor": "validating-addresses", "start_char": 24824, "end_char": 29604, "estimated_token_count": 1074, "token_estimator": "heuristic-v1", "text": "### Validating Addresses\n\nSS58 addresses can be validated using the subkey command-line interface or the Polkadot.js API. These tools help ensure an address is correctly formatted and valid for the intended network. The following sections will provide an overview of how validation works with these tools.\n\n#### Using Subkey\n\n[Subkey](https://paritytech.github.io/polkadot-sdk/master/subkey/index.html){target=\\_blank} is a CLI tool provided by Polkadot SDK for generating and managing keys. It can inspect and validate SS58 addresses.\n\nThe `inspect` command gets a public key and an SS58 address from the provided secret URI. The basic syntax for the `subkey inspect` command is:\n\n```bash\nsubkey inspect [flags] [options] uri\n```\n\nFor the `uri` command-line argument, you can specify the secret seed phrase, a hex-encoded private key, or an SS58 address. If the input is a valid address, the `subkey` program displays the corresponding hex-encoded public key, account identifier, and SS58 addresses.\n\nFor example, to inspect the public keys derived from a secret seed phrase, you can run a command similar to the following:\n\n```bash\nsubkey inspect \"caution juice atom organ advance problem want pledge someone senior holiday very\"\n```\n\nThe command displays output similar to the following:\n\n
    \n subkey inspect \"caution juice atom organ advance problem want pledge someone senior holiday very\"\n Secret phrase `caution juice atom organ advance problem want pledge someone senior holiday very` is account:\n Secret seed: 0xc8fa03532fb22ee1f7f6908b9c02b4e72483f0dbd66e4cd456b8f34c6230b849\n Public key (hex): 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746\n Public key (SS58): 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR\n Account ID: 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746\n SS58 Address: 5Gv8YYFu8H1btvmrJy9FjjAWfb99wrhV3uhPFoNEr918utyR\n
    \n\nThe `subkey` program assumes an address is based on a public/private key pair. If you inspect an address, the command returns the 32-byte account identifier.\n\nHowever, not all addresses in Polkadot SDK-based networks are based on keys.\n\nDepending on the command-line options you specify and the input you provided, the command output might also display the network for which the address has been encoded. For example:\n\n```bash\nsubkey inspect \"12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU\"\n```\n\nThe command displays output similar to the following:\n\n
    \n subkey inspect \"12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU\"\n Public Key URI `12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU` is account:\n Network ID/Version: polkadot\n Public key (hex): 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a\n Account ID: 0x46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a\n Public key (SS58): 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU\n SS58 Address: 12bzRJfh7arnnfPPUZHeJUaE62QLEwhK48QnH9LXeK2m1iZU\n
    \n\n#### Using Polkadot.js API\n\nTo verify an address in JavaScript or TypeScript projects, you can use the functions built into the [Polkadot.js API](https://polkadot.js.org/docs/){target=\\_blank}. For example:\n\n```js\n// Import Polkadot.js API dependencies\nconst { decodeAddress, encodeAddress } = require('@polkadot/keyring');\nconst { hexToU8a, isHex } = require('@polkadot/util');\n\n// Specify an address to test.\nconst address = 'INSERT_ADDRESS_TO_TEST';\n\n// Check address\nconst isValidSubstrateAddress = () => {\n try {\n encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address));\n\n return true;\n } catch (error) {\n return false;\n }\n};\n\n// Query result\nconst isValid = isValidSubstrateAddress();\nconsole.log(isValid);\n\n```\n\nIf the function returns `true`, the specified address is a valid address.\n\n#### Other SS58 Implementations\n\nSupport for encoding and decoding Polkadot SDK SS58 addresses has been implemented in several other languages and libraries.\n\n- **Crystal**: [`wyhaines/base58.cr`](https://github.com/wyhaines/base58.cr){target=\\_blank}\n- **Go**: [`itering/subscan-plugin`](https://github.com/itering/subscan-plugin){target=\\_blank}\n- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\\_blank}\n- **TypeScript**: [`subsquid/squid-sdk`](https://github.com/subsquid/squid-sdk){target=\\_blank}"} -{"page_id": "reference-parachains-blocks-transactions-fees-blocks", "page_title": "Blocks", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 10, "end_char": 693, "estimated_token_count": 126, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nIn the Polkadot SDK, blocks are fundamental to the functioning of the blockchain, serving as containers for [transactions](/reference/parachains/blocks-transactions-fees/transactions/){target=\\_blank} and changes to the chain's state. Blocks consist of headers and an array of transactions, ensuring the integrity and validity of operations on the network. This guide explores the essential components of a block, the process of block production, and how blocks are validated and imported across the network. By understanding these concepts, developers can better grasp how blockchains maintain security, consistency, and performance within the Polkadot ecosystem."} -{"page_id": "reference-parachains-blocks-transactions-fees-blocks", "page_title": "Blocks", "index": 1, "depth": 2, "title": "What is a Block?", "anchor": "what-is-a-block", "start_char": 693, "end_char": 1830, "estimated_token_count": 226, "token_estimator": "heuristic-v1", "text": "## What is a Block?\n\nIn the Polkadot SDK, a block is a fundamental unit that encapsulates both the header and an array of transactions. The block header includes critical metadata to ensure the integrity and sequence of the blockchain. Here's a breakdown of its components:\n\n- **Block height**: Indicates the number of blocks created in the chain so far.\n- **Parent hash**: The hash of the previous block, providing a link to maintain the blockchain's immutability.\n- **Transaction root**: Cryptographic digest summarizing all transactions in the block.\n- **State root**: A cryptographic digest representing the post-execution state.\n- **Digest**: Additional information that can be attached to a block, such as consensus-related messages.\n\nEach transaction is part of a series that is executed according to the runtime's rules. The transaction root is a cryptographic digest of this series, which prevents alterations and enables succinct verification by light clients. This verification process allows light clients to confirm whether a transaction exists in a block with only the block header, avoiding downloading the entire block."} -{"page_id": "reference-parachains-blocks-transactions-fees-blocks", "page_title": "Blocks", "index": 2, "depth": 2, "title": "Block Production", "anchor": "block-production", "start_char": 1830, "end_char": 2154, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "## Block Production\n\nWhen an authoring node is authorized to create a new block, it selects transactions from the transaction queue based on priority. This step, known as block production, relies heavily on the executive module to manage the initialization and finalization of blocks. The process is summarized as follows:"} -{"page_id": "reference-parachains-blocks-transactions-fees-blocks", "page_title": "Blocks", "index": 3, "depth": 3, "title": "Initialize Block", "anchor": "initialize-block", "start_char": 2154, "end_char": 3023, "estimated_token_count": 199, "token_estimator": "heuristic-v1", "text": "### Initialize Block\n\nThe block initialization process begins with a series of function calls that prepare the block for transaction execution:\n\n1. **Call `on_initialize`**: The executive module calls the [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\\_blank} hook from the system pallet and other runtime pallets to prepare for the block's transactions.\n2. **Coordinate runtime calls**: Coordinates function calls in the order defined by the transaction queue.\n3. **Verify information**: Once [`on_initialize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_initialize){target=\\_blank} functions are executed, the executive module checks the parent hash in the block header and the trie root to verify information is consistent."} -{"page_id": "reference-parachains-blocks-transactions-fees-blocks", "page_title": "Blocks", "index": 4, "depth": 3, "title": "Finalize Block", "anchor": "finalize-block", "start_char": 3023, "end_char": 3897, "estimated_token_count": 209, "token_estimator": "heuristic-v1", "text": "### Finalize Block\n\nOnce transactions are processed, the block must be finalized before being broadcast to the network. The finalization steps are as follows:\n\n1. **Call `on_finalize`**: The executive module calls the [`on_finalize`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_finalize){target=\\_blank} hooks in each pallet to ensure any remaining state updates or checks are completed before the block is sealed and published.\n2. **Verify information**: The block's digest and storage root in the header are checked against the initialized block to ensure consistency.\n3. **Call `on_idle`**: The [`on_idle`](https://paritytech.github.io/polkadot-sdk/master/frame_support/traits/trait.Hooks.html#method.on_idle){target=\\_blank} hook is triggered to process any remaining tasks using the leftover weight from the block."} -{"page_id": "reference-parachains-blocks-transactions-fees-blocks", "page_title": "Blocks", "index": 5, "depth": 2, "title": "Block Authoring and Import", "anchor": "block-authoring-and-import", "start_char": 3897, "end_char": 4399, "estimated_token_count": 113, "token_estimator": "heuristic-v1", "text": "## Block Authoring and Import\n\nOnce the block is finalized, it is gossiped to other nodes in the network. Nodes follow this procedure:\n\n1. **Receive transactions**: The authoring node collects transactions from the network.\n2. **Validate**: Transactions are checked for validity.\n3. **Queue**: Valid transactions are placed in the transaction pool for execution.\n4. **Execute**: State changes are made as the transactions are executed.\n5. **Publish**: The finalized block is broadcast to the network."} -{"page_id": "reference-parachains-blocks-transactions-fees-blocks", "page_title": "Blocks", "index": 6, "depth": 3, "title": "Block Import Queue", "anchor": "block-import-queue", "start_char": 4399, "end_char": 6005, "estimated_token_count": 401, "token_estimator": "heuristic-v1", "text": "### Block Import Queue\n\nAfter a block is published, other nodes on the network can import it into their chain state. The block import queue is part of the outer node in every Polkadot SDK-based node and ensures incoming blocks are valid before adding them to the node's state.\n\nIn most cases, you don't need to know details about how transactions are gossiped or how other nodes on the network import blocks. The following traits are relevant, however, if you plan to write any custom consensus logic or want a deeper dive into the block import queue:\n\n- **[`ImportQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.ImportQueue.html){target=\\_blank}**: The trait that defines the block import queue.\n- **[`Link`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Link.html){target=\\_blank}**: The trait that defines the link between the block import queue and the network.\n- **[`BasicQueue`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/struct.BasicQueue.html){target=\\_blank}**: A basic implementation of the block import queue.\n- **[`Verifier`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/import_queue/trait.Verifier.html){target=\\_blank}**: The trait that defines the block verifier.\n- **[`BlockImport`](https://paritytech.github.io/polkadot-sdk/master/sc_consensus/block_import/trait.BlockImport.html){target=\\_blank}**: The trait that defines the block import process.\n\nThese traits govern how blocks are validated and imported across the network, ensuring consistency and security."} -{"page_id": "reference-parachains-blocks-transactions-fees-blocks", "page_title": "Blocks", "index": 7, "depth": 2, "title": "Additional Resources", "anchor": "additional-resources", "start_char": 6005, "end_char": 6252, "estimated_token_count": 64, "token_estimator": "heuristic-v1", "text": "## Additional Resources\n\nTo learn more about the block structure in the Polkadot SDK runtime, see the [`Block` reference](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.Block.html){target=\\_blank} entry in the Rust Docs."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 0, "depth": 2, "title": "Introductions", "anchor": "introductions", "start_char": 33, "end_char": 2267, "estimated_token_count": 408, "token_estimator": "heuristic-v1", "text": "## Introductions\n\nWhen transactions are executed, or data is stored on-chain, the activity changes the chain's state and consumes blockchain resources. Because the resources available to a blockchain are limited, managing how operations on-chain consume them is important. In addition to being limited in practical terms, such as storage capacity, blockchain resources represent a potential attack vector for malicious users. For example, a malicious user might attempt to overload the network with messages to stop the network from producing new blocks. To protect blockchain resources from being drained or overloaded, you need to manage how they are made available and how they are consumed. The resources to be aware of include:\n\n- Memory usage\n- Storage input and output\n- Computation\n- Transaction and block size\n- State database size\n\nThe Polkadot SDK provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource. Two of the most important mechanisms available to block authors are weights and transaction fees.\n\n[Weights](/reference/glossary/#weight){target=\\_blank} manage the time it takes to validate a block and characterize the time it takes to execute the calls in the block's body. By controlling the execution time a block can consume, weights set limits on storage input, output, and computation.\n\nSome of the weight allowed for a block is consumed as part of the block's initialization and finalization. The weight might also be used to execute mandatory inherent extrinsic calls. To help ensure blocks don’t consume too much execution time and prevent malicious users from overloading the system with unnecessary calls, weights are combined with transaction fees.\n\n[Transaction fees](/reference/parachains/blocks-transactions-fees/transactions/#transaction-fees){target=\\_blank} provide an economic incentive to limit execution time, computation, and the number of calls required to perform operations. Transaction fees are also used to make the blockchain economically sustainable because they are typically applied to transactions initiated by users and deducted before a transaction request is executed."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 1, "depth": 2, "title": "How Fees are Calculated", "anchor": "how-fees-are-calculated", "start_char": 2267, "end_char": 3592, "estimated_token_count": 287, "token_estimator": "heuristic-v1", "text": "## How Fees are Calculated\n\nThe final fee for a transaction is calculated using the following parameters:\n\n- **`base fee`**: This is the minimum amount a user pays for a transaction. It is declared a base weight in the runtime and converted to a fee using the [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\\_blank} conversion.\n- **`weight fee`**: A fee proportional to the execution time (input and output and computation) that a transaction consumes.\n- **`length fee`**: A fee proportional to the encoded length of the transaction.\n- **`tip`**: An optional tip to increase the transaction’s priority, giving it a higher chance to be included in the transaction queue.\n\nThe base fee and proportional weight and length fees constitute the inclusion fee. The inclusion fee is the minimum fee that must be available for a transaction to be included in a block.\n\n```text\ninclusion fee = base fee + weight fee + length fee\n```\n\nTransaction fees are withdrawn before the transaction is executed. After the transaction is executed, the weight can be adjusted to reflect the resources used. If a transaction uses fewer resources than expected, the transaction fee is corrected, and the adjusted transaction fee is deposited."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 2, "depth": 2, "title": "Using the Transaction Payment Pallet", "anchor": "using-the-transaction-payment-pallet", "start_char": 3592, "end_char": 4931, "estimated_token_count": 309, "token_estimator": "heuristic-v1", "text": "## Using the Transaction Payment Pallet\n\nThe [Transaction Payment pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/transaction-payment){target=\\_blank} provides the basic logic for calculating the inclusion fee. You can also use the Transaction Payment pallet to:\n\n- Convert a weight value into a deductible fee based on a currency type using [`Config::WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\\_blank}.\n- Update the fee for the next block by defining a multiplier based on the chain’s final state at the end of the previous block using [`Config::FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\\_blank}.\n- Manage the withdrawal, refund, and deposit of transaction fees using [`Config::OnChargeTransaction`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.OnChargeTransaction){target=\\_blank}.\n\nYou can learn more about these configuration traits in the [Transaction Payment documentation](https://paritytech.github.io/polkadot-sdk/master/pallet_transaction_payment/index.html){target=\\_blank}."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 3, "depth": 3, "title": "Understanding the Inclusion Fee", "anchor": "understanding-the-inclusion-fee", "start_char": 4931, "end_char": 6255, "estimated_token_count": 278, "token_estimator": "heuristic-v1", "text": "### Understanding the Inclusion Fee\n\nThe formula for calculating the inclusion fee is as follows:\n\n```text\ninclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee]\n```\n\nAnd then, for calculating the final fee:\n\n```text\nfinal_fee = inclusion_fee + tip\n```\n\nIn the first formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the network’s congestion.\n\n- The `base_fee` derived from the base weight covers inclusion overhead like signature verification.\n- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic.\n- The `weight_fee` fee is calculated using two parameters:\n - The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics.\n - The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity.\n\nTo convert the weight to `Currency`, the runtime must define a `WeightToFee` struct that implements a conversion function, [`Convert`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/struct.Pallet.html#method.weight_to_fee){target=\\_blank}.\n\nNote that the extrinsic sender is charged the inclusion fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 4, "depth": 3, "title": "Accounts with an Insufficient Balance", "anchor": "accounts-with-an-insufficient-balance", "start_char": 6255, "end_char": 6816, "estimated_token_count": 104, "token_estimator": "heuristic-v1", "text": "### Accounts with an Insufficient Balance\n\nIf an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum existential deposit—then you should ensure the transaction is canceled so that no fee is deducted and the transaction does not begin execution.\n\nThe Polkadot SDK doesn't enforce this rollback behavior. However, this scenario would be rare because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 5, "depth": 3, "title": "Fee Multipliers", "anchor": "fee-multipliers", "start_char": 6816, "end_char": 8034, "estimated_token_count": 260, "token_estimator": "heuristic-v1", "text": "### Fee Multipliers\n\nThe inclusion fee formula always results in the same fee for the same input. However, weight can be dynamic and—based on how [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\\_blank} is defined—the final fee can include some degree of variability.\nThe Transaction Payment pallet provides the [`FeeMultiplierUpdate`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate){target=\\_blank} configurable parameter to account for this variability.\n\nThe Polkadot network inspires the default update function and implements a targeted adjustment in which a target saturation level of block weight is defined. If the previous block is more saturated, the fees increase slightly. Similarly, if the last block has fewer transactions than the target, fees are decreased by a small amount. For more information about fee multiplier adjustments, see the [Web3 Research Page](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\\_blank}."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 6, "depth": 2, "title": "Transactions with Special Requirements", "anchor": "transactions-with-special-requirements", "start_char": 8034, "end_char": 9446, "estimated_token_count": 277, "token_estimator": "heuristic-v1", "text": "## Transactions with Special Requirements\n\nInclusion fees must be computable before execution and can only represent fixed logic. Some transactions warrant limiting resources with other strategies. For example:\n\n- Bonds are a type of fee that might be returned or slashed after some on-chain event. For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior.\n- Deposits are fees that might be returned later. For example, you might require users to pay a deposit to execute an operation that uses storage. The user’s deposit could be returned if a subsequent operation frees up storage.\n- Burn operations are used to pay for a transaction based on its internal logic. For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased state size.\n- Limits enable you to enforce constant or configurable limits on specific operations. For example, the default [Staking pallet](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/substrate/frame/staking){target=\\_blank} only allows nominators to nominate 16 validators to limit the complexity of the validator election process.\n\nIt is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 7, "depth": 2, "title": "Default Weight Annotations", "anchor": "default-weight-annotations", "start_char": 9446, "end_char": 10104, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "## Default Weight Annotations\n\nAll dispatchable functions in the Polkadot SDK must specify a weight. The way of doing that is using the annotation-based system that lets you combine fixed values for database read/write weight and/or fixed values based on benchmarks. The most basic example would look like this:\n\n```rust\n#[pallet::weight(100_000)]\nfn my_dispatchable() {\n // ...\n}\n```\n\nNote that the [`ExtrinsicBaseWeight`](https://crates.parity.io/frame_support/weights/constants/struct.ExtrinsicBaseWeight.html){target=\\_blank} is automatically added to the declared weight to account for the costs of simply including an empty extrinsic into a block."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 8, "depth": 3, "title": "Weights and Database Read/Write Operations", "anchor": "weights-and-database-readwrite-operations", "start_char": 10104, "end_char": 11244, "estimated_token_count": 264, "token_estimator": "heuristic-v1", "text": "### Weights and Database Read/Write Operations\n\nTo make weight annotations independent of the deployed database backend, they are defined as a constant and then used in the annotations when expressing database accesses performed by the dispatchable:\n\n```rust\n#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)]\nfn my_dispatchable() {\n // ...\n}\n```\n\nThis dispatchable allows one database to read and two to write, in addition to other things that add the additional 20,000. Database access is generally every time a value declared inside the [`#[pallet::storage]`](https://paritytech.github.io/polkadot-sdk/master/frame_support/pallet_macros/attr.storage.html){target=\\_blank} block is accessed. However, unique accesses are counted because after a value is accessed, it is cached, and reaccessing it does not result in a database operation. That is:\n\n- Multiple reads of the exact value count as one read.\n- Multiple writes of the exact value count as one write.\n- Multiple reads of the same value, followed by a write to that value, count as one read and one write.\n- A write followed by a read-only counts as one write."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 9, "depth": 3, "title": "Dispatch Classes", "anchor": "dispatch-classes", "start_char": 11244, "end_char": 13982, "estimated_token_count": 571, "token_estimator": "heuristic-v1", "text": "### Dispatch Classes\n\nDispatches are broken into three classes:\n\n- Normal\n- Operational\n- Mandatory\n\nIf a dispatch is not defined as `Operational` or `Mandatory` in the weight annotation, the dispatch is identified as `Normal` by default. You can specify that the dispatchable uses another class like this:\n\n```rust\n#[pallet::dispatch((DispatchClass::Operational))]\nfn my_dispatchable() {\n // ...\n}\n```\n\nThis tuple notation also allows you to specify a final argument determining whether the user is charged based on the annotated weight. If you don't specify otherwise, `Pays::Yes` is assumed:\n\n```rust\n#[pallet::dispatch(DispatchClass::Normal, Pays::No)]\nfn my_dispatchable() {\n // ...\n}\n```\n\n#### Normal Dispatches\n\nDispatches in this class represent normal user-triggered transactions. These types of dispatches only consume a portion of a block's total weight limit. For information about the maximum portion of a block that can be consumed for normal dispatches, see [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\\_blank}. Normal dispatches are sent to the transaction pool.\n\n#### Operational Dispatches\n\nUnlike normal dispatches, which represent the usage of network capabilities, operational dispatches are those that provide network capabilities. Operational dispatches can consume the entire weight limit of a block. They are not bound by the [`AvailableBlockRatio`](https://paritytech.github.io/polkadot-sdk/master/frame_system/limits/struct.BlockLength.html){target=\\_blank}. Dispatches in this class are given maximum priority and are exempt from paying the [`length_fee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/){target=\\_blank}.\n\n#### Mandatory Dispatches\n\nMandatory dispatches are included in a block even if they cause the block to surpass its weight limit. You can only use the mandatory dispatch class for inherent transactions that the block author submits. This dispatch class is intended to represent functions in the block validation process. Because these dispatches are always included in a block regardless of the function weight, the validation process must prevent malicious nodes from abusing the function to craft valid but impossibly heavy blocks. You can typically accomplish this by ensuring that:\n\n- The operation performed is always light.\n- The operation can only be included in a block once.\n\nTo make it more difficult for malicious nodes to abuse mandatory dispatches, they cannot be included in blocks that return errors. This dispatch class serves the assumption that it is better to allow an overweight block to be created than not to allow any block to be created at all."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 10, "depth": 3, "title": "Dynamic Weights", "anchor": "dynamic-weights", "start_char": 13982, "end_char": 14529, "estimated_token_count": 132, "token_estimator": "heuristic-v1", "text": "### Dynamic Weights\n\nIn addition to purely fixed weights and constants, the weight calculation can consider the input arguments of a dispatchable. The weight should be trivially computable from the input arguments with some basic arithmetic:\n\n```rust\nuse frame_support:: {\n dispatch:: {\n DispatchClass::Normal,\n Pays::Yes,\n },\n weights::Weight,\n};\n\n#[pallet::weight(FunctionOf(\n |args: (&Vec,)| args.0.len().saturating_mul(10_000),\n )\n]\nfn handle_users(origin, calls: Vec) {\n // Do something per user\n}\n```"} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 11, "depth": 2, "title": "Post Dispatch Weight Correction", "anchor": "post-dispatch-weight-correction", "start_char": 14529, "end_char": 15153, "estimated_token_count": 131, "token_estimator": "heuristic-v1", "text": "## Post Dispatch Weight Correction\n\nDepending on the execution logic, a dispatchable function might consume less weight than was prescribed pre-dispatch. To correct weight, the function declares a different return type and returns its actual weight:\n\n```rust\n#[pallet::weight(10_000 + 500_000_000)]\nfn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo {\n let was_heavy = do_calculation(input);\n\n if (was_heavy) {\n // None means \"no correction\" from the weight annotation.\n Ok(None.into())\n } else {\n // Return the actual weight consumed.\n Ok(Some(10_000).into())\n }\n}\n```"} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 12, "depth": 2, "title": "Custom Fees", "anchor": "custom-fees", "start_char": 15153, "end_char": 15269, "estimated_token_count": 20, "token_estimator": "heuristic-v1", "text": "## Custom Fees\n\nYou can also define custom fee systems through custom weight functions or inclusion fee functions."} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 13, "depth": 3, "title": "Custom Weights", "anchor": "custom-weights", "start_char": 15269, "end_char": 19797, "estimated_token_count": 1044, "token_estimator": "heuristic-v1", "text": "### Custom Weights\n\nInstead of using the default weight annotations, you can create a custom weight calculation type using the weights module. The custom weight calculation type must implement the following traits:\n\n- [`WeighData`](https://crates.parity.io/frame_support/weights/trait.WeighData.html){target=\\_blank} to determine the weight of the dispatch.\n- [`ClassifyDispatch`](https://crates.parity.io/frame_support/weights/trait.ClassifyDispatch.html){target=\\_blank} to determine the class of the dispatch.\n- [`PaysFee`](https://crates.parity.io/frame_support/weights/trait.PaysFee.html){target=\\_blank} to determine whether the sender of the dispatch pays fees.\n \nThe Polkadot SDK then bundles the output information of the three traits into the [`DispatchInfo`](https://paritytech.github.io/polkadot-sdk/master/frame_support/dispatch/struct.DispatchInfo.html){target=\\_blank} struct and provides it by implementing the [`GetDispatchInfo`](https://docs.rs/frame-support/latest/frame_support/dispatch/trait.GetDispatchInfo.html){target=\\_blank} for all `Call` variants and opaque extrinsic types. This is used internally by the System and Executive modules.\n\n`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over T, which gets resolved into the tuple of all dispatch arguments except for the origin. The following example illustrates a struct that calculates the weight as `m * len(args)`, where `m` is a given multiplier and args is the concatenated tuple of all dispatch arguments. In this example, the dispatch class is `Operational` if the transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length exceeds 10 bytes.\n\n```rust\nstruct LenWeight(u32);\nimpl WeighData for LenWeight {\n fn weigh_data(&self, target: T) -> Weight {\n let multiplier = self.0;\n let encoded_len = target.encode().len() as u32;\n multiplier * encoded_len\n }\n}\n\nimpl ClassifyDispatch for LenWeight {\n fn classify_dispatch(&self, target: T) -> DispatchClass {\n let encoded_len = target.encode().len() as u32;\n if encoded_len > 100 {\n DispatchClass::Operational\n } else {\n DispatchClass::Normal\n }\n }\n}\n\nimpl PaysFee {\n fn pays_fee(&self, target: T) -> Pays {\n let encoded_len = target.encode().len() as u32;\n if encoded_len > 10 {\n Pays::Yes\n } else {\n Pays::No\n }\n }\n}\n```\n\nA weight calculator function can also be coerced to the final type of the argument instead of defining it as a vague type that can be encoded. The code would roughly look like this:\n\n```rust\nstruct CustomWeight;\nimpl WeighData<(&u32, &u64)> for CustomWeight {\n fn weigh_data(&self, target: (&u32, &u64)) -> Weight {\n ...\n }\n}\n\n// given a dispatch:\n#[pallet::call]\nimpl, I: 'static> Pallet {\n #[pallet::weight(CustomWeight)]\n fn foo(a: u32, b: u64) { ... }\n}\n```\n\nIn this example, the `CustomWeight` can only be used in conjunction with a dispatch with a particular signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because there aren't any assumptions about ``.\n\n#### Custom Inclusion Fee\n\nThe following example illustrates how to customize your inclusion fee. You must configure the appropriate associated types in the respective module.\n\n```rust\n// Assume this is the balance type\ntype Balance = u64;\n\n// Assume we want all the weights to have a `100 + 2 * w` conversion to fees\nstruct CustomWeightToFee;\nimpl WeightToFee for CustomWeightToFee {\n fn convert(w: Weight) -> Balance {\n let a = Balance::from(100);\n let b = Balance::from(2);\n let w = Balance::from(w);\n a + b * w\n }\n}\n\nparameter_types! {\n pub const ExtrinsicBaseWeight: Weight = 10_000_000;\n}\n\nimpl frame_system::Config for Runtime {\n type ExtrinsicBaseWeight = ExtrinsicBaseWeight;\n}\n\nparameter_types! {\n pub const TransactionByteFee: Balance = 10;\n}\n\nimpl transaction_payment::Config {\n type TransactionByteFee = TransactionByteFee;\n type WeightToFee = CustomWeightToFee;\n type FeeMultiplierUpdate = TargetedFeeAdjustment;\n}\n\nstruct TargetedFeeAdjustment(sp_std::marker::PhantomData);\nimpl> WeightToFee for TargetedFeeAdjustment {\n fn convert(multiplier: Fixed128) -> Fixed128 {\n // Don't change anything. Put any fee update info here.\n multiplier\n }\n}\n```"} -{"page_id": "reference-parachains-blocks-transactions-fees-fees", "page_title": "Transactions Weights and Fees", "index": 14, "depth": 2, "title": "Additional Resources", "anchor": "additional-resources", "start_char": 19797, "end_char": 20800, "estimated_token_count": 233, "token_estimator": "heuristic-v1", "text": "## Additional Resources\n\nYou now know the weight system, how it affects transaction fee computation, and how to specify weights for your dispatchable calls. The next step is determining the correct weight for your dispatchable operations. You can use Substrate benchmarking functions and frame-benchmarking calls to test your functions with different parameters and empirically determine the proper weight in their worst-case scenarios.\n\n- [Benchmark](/parachains/customize-runtime/pallet-development/benchmark-pallet/)\n- [`SignedExtension`](https://paritytech.github.io/polkadot-sdk/master/sp_runtime/traits/trait.SignedExtension.html){target=\\_blank}\n- [Custom weights for the Example pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/examples/basic/src/weights.rs){target=\\_blank}\n- [Web3 Foundation Research](https://research.web3.foundation/Polkadot/overview/token-economics#relay-chain-transaction-fees-and-per-block-transaction-limits){target=\\_blank}"} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 16, "end_char": 655, "estimated_token_count": 108, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nTransactions are essential components of blockchain networks, enabling state changes and the execution of key operations. In the Polkadot SDK, transactions, often called extrinsics, come in multiple forms, including signed, unsigned, and inherent transactions.\n\nThis guide walks you through the different transaction types and how they're formatted, validated, and processed within the Polkadot ecosystem. You'll also learn how to customize transaction formats and construct transactions for FRAME-based runtimes, ensuring a complete understanding of how transactions are built and executed in Polkadot SDK-based chains."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 1, "depth": 2, "title": "What Is a Transaction?", "anchor": "what-is-a-transaction", "start_char": 655, "end_char": 1674, "estimated_token_count": 193, "token_estimator": "heuristic-v1", "text": "## What Is a Transaction?\n\nIn the Polkadot SDK, transactions represent operations that modify the chain's state, bundled into blocks for execution. The term extrinsic is often used to refer to any data that originates outside the runtime and is included in the chain. While other blockchain systems typically refer to these operations as \"transactions,\" the Polkadot SDK adopts the broader term \"extrinsic\" to capture the wide variety of data types that can be added to a block.\n\nThere are three primary types of transactions (extrinsics) in the Polkadot SDK:\n\n- **Signed transactions**: Signed by the submitting account, often carrying transaction fees.\n- **Unsigned transactions**: Submitted without a signature, often requiring custom validation logic.\n- **Inherent transactions**: Typically inserted directly into blocks by block authoring nodes, without gossiping between peers.\n\nEach type serves a distinct purpose, and understanding when and how to use each is key to efficiently working with the Polkadot SDK."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 2, "depth": 3, "title": "Signed Transactions", "anchor": "signed-transactions", "start_char": 1674, "end_char": 2838, "estimated_token_count": 221, "token_estimator": "heuristic-v1", "text": "### Signed Transactions\n\nSigned transactions require an account's signature and typically involve submitting a request to execute a runtime call. The signature serves as a form of cryptographic proof that the sender has authorized the action, using their private key. These transactions often involve a transaction fee to cover the cost of execution and incentivize block producers.\n\nSigned transactions are the most common type of transaction and are integral to user-driven actions, such as token transfers. For instance, when you transfer tokens from one account to another, the sending account must sign the transaction to authorize the operation.\n\nFor example, the [`pallet_balances::Call::transfer_allow_death`](https://paritytech.github.io/polkadot-sdk/master/pallet_balances/pallet/struct.Pallet.html#method.transfer_allow_death){target=\\_blank} extrinsic in the Balances pallet allows you to transfer tokens. Since your account initiates this transaction, your account key is used to sign it. You'll also be responsible for paying the associated transaction fee, with the option to include an additional tip to incentivize faster inclusion in the block."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 3, "depth": 3, "title": "Unsigned Transactions", "anchor": "unsigned-transactions", "start_char": 2838, "end_char": 4091, "estimated_token_count": 235, "token_estimator": "heuristic-v1", "text": "### Unsigned Transactions\n\nUnsigned transactions do not require a signature or account-specific data from the sender. Unlike signed transactions, they do not come with any form of economic deterrent, such as fees, which makes them susceptible to spam or replay attacks. Custom validation logic must be implemented to mitigate these risks and ensure these transactions are secure.\n\nUnsigned transactions typically involve scenarios where including a fee or signature is unnecessary or counterproductive. However, due to the absence of fees, they require careful validation to protect the network. For example, [`pallet_im_online::Call::heartbeat`](https://paritytech.github.io/polkadot-sdk/master/pallet_im_online/pallet/struct.Pallet.html#method.heartbeat){target=\\_blank} extrinsic allows validators to send a heartbeat signal, indicating they are active. Since only validators can make this call, the logic embedded in the transaction ensures that the sender is a validator, making the need for a signature or fee redundant.\n\nUnsigned transactions are more resource-intensive than signed ones because custom validation is required, but they play a crucial role in certain operational scenarios, especially when regular user accounts aren't involved."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 4, "depth": 3, "title": "Inherent Transactions", "anchor": "inherent-transactions", "start_char": 4091, "end_char": 5815, "estimated_token_count": 327, "token_estimator": "heuristic-v1", "text": "### Inherent Transactions\n\nInherent transactions are a specialized type of unsigned transaction that is used primarily for block authoring. Unlike signed or other unsigned transactions, inherent transactions are added directly by block producers and are not broadcasted to the network or stored in the transaction queue. They don't require signatures or the usual validation steps and are generally used to insert system-critical data directly into blocks.\n\nA key example of an inherent transaction is inserting a timestamp into each block. The [`pallet_timestamp::Call::now`](https://paritytech.github.io/polkadot-sdk/master/pallet_timestamp/pallet/struct.Pallet.html#method.now-1){target=\\_blank} extrinsic allows block authors to include the current time in the block they are producing. Since the block producer adds this information, there is no need for transaction validation, like signature verification. The validation in this case is done indirectly by the validators, who check whether the timestamp is within an acceptable range before finalizing the block.\n\nAnother example is the [`paras_inherent::Call::enter`](https://paritytech.github.io/polkadot-sdk/master/polkadot_runtime_parachains/paras_inherent/pallet/struct.Pallet.html#method.enter){target=\\_blank} extrinsic, which enables parachain collator nodes to send validation data to the relay chain. This inherent transaction ensures that the necessary parachain data is included in each block without the overhead of gossiped transactions.\n\nInherent transactions serve a critical role in block authoring by allowing important operational data to be added directly to the chain without needing the validation processes required for standard transactions."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 5, "depth": 2, "title": "Transaction Formats", "anchor": "transaction-formats", "start_char": 5815, "end_char": 6164, "estimated_token_count": 58, "token_estimator": "heuristic-v1", "text": "## Transaction Formats\n\nUnderstanding the structure of signed and unsigned transactions is crucial for developers building on Polkadot SDK-based chains. Whether you're optimizing transaction processing, customizing formats, or interacting with the transaction pool, knowing the format of extrinsics, Polkadot's term for transactions, is essential."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 6, "depth": 3, "title": "Types of Transaction Formats", "anchor": "types-of-transaction-formats", "start_char": 6164, "end_char": 7058, "estimated_token_count": 163, "token_estimator": "heuristic-v1", "text": "### Types of Transaction Formats\n\nIn Polkadot SDK-based chains, extrinsics can fall into three main categories:\n\n- **Unchecked extrinsics**: Typically used for signed transactions that require validation. They contain a signature and additional data, such as a nonce and information for fee calculation. Unchecked extrinsics are named as such because they require validation checks before being accepted into the transaction pool.\n- **Checked extrinsics**: Typically used for inherent extrinsics (unsigned transactions); these don't require signature verification. Instead, they carry information such as where the extrinsic originates and any additional data required for the block authoring process.\n- **Opaque extrinsics**: Used when the format of an extrinsic is not yet fully committed or finalized. They are still decodable, but their structure can be flexible depending on the context."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 7, "depth": 3, "title": "Signed Transaction Data Structure", "anchor": "signed-transaction-data-structure", "start_char": 7058, "end_char": 8020, "estimated_token_count": 195, "token_estimator": "heuristic-v1", "text": "### Signed Transaction Data Structure\n\nA signed transaction typically includes the following components:\n\n- **Signature**: Verifies the authenticity of the transaction sender.\n- **Call**: The actual function or method call the transaction is requesting (for example, transferring funds).\n- **Nonce**: Tracks the number of prior transactions sent from the account, helping to prevent replay attacks.\n- **Tip**: An optional incentive to prioritize the transaction in block inclusion.\n- **Additional data**: Includes details such as spec version, block hash, and genesis hash to ensure the transaction is valid within the correct runtime and chain context.\n\nHere's a simplified breakdown of how signed transactions are typically constructed in a Polkadot SDK runtime:\n\n``` code\n + + \n```\n\nEach part of the signed transaction has a purpose, ensuring the transaction's authenticity and context within the blockchain."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 8, "depth": 3, "title": "Signed Extensions", "anchor": "signed-extensions", "start_char": 8020, "end_char": 10654, "estimated_token_count": 610, "token_estimator": "heuristic-v1", "text": "### Signed Extensions\n\nPolkadot SDK also provides the concept of [signed extensions](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/signed_extensions/index.html){target=\\_blank}, which allow developers to extend extrinsics with additional data or validation logic before they are included in a block. The [`SignedExtension`](https://paritytech.github.io/try-runtime-cli/sp_runtime/traits/trait.SignedExtension.html){target=\\_blank} set helps enforce custom rules or protections, such as ensuring the transaction's validity or calculating priority.\n\nThe transaction queue regularly calls signed extensions to verify a transaction's validity before placing it in the ready queue. This safeguard ensures transactions won't fail in a block. Signed extensions are commonly used to enforce validation logic and protect the transaction pool from spam and replay attacks.\n\nIn FRAME, a signed extension can hold any of the following types by default:\n\n- **[`AccountId`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/types_common/type.AccountId.html){target=\\_blank}**: To encode the sender's identity.\n- **[`Call`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Call){target=\\_blank}**: To encode the pallet call to be dispatched. This data is used to calculate transaction fees.\n- **[`AdditionalSigned`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.AdditionalSigned){target=\\_blank}**: To handle any additional data to go into the signed payload allowing you to attach any custom logic prior to dispatching a transaction.\n- **[`Pre`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/traits/trait.SignedExtension.html#associatedtype.Pre){target=\\_blank}**: To encode the information that can be passed from before a call is dispatched to after it gets dispatched.\n\nSigned extensions can enforce checks like:\n\n- **[`CheckSpecVersion`](https://paritytech.github.io/polkadot-sdk/master/src/frame_system/extensions/check_spec_version.rs.html){target=\\_blank}**: Ensures the transaction is compatible with the runtime's current version.\n- **[`CheckWeight`](https://paritytech.github.io/polkadot-sdk/master/frame_system/struct.CheckWeight.html){target=\\_blank}**: Calculates the weight (or computational cost) of the transaction, ensuring the block doesn't exceed the maximum allowed weight.\n\nThese extensions are critical in the transaction lifecycle, ensuring that only valid and prioritized transactions are processed."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 9, "depth": 2, "title": "Transaction Construction", "anchor": "transaction-construction", "start_char": 10654, "end_char": 10991, "estimated_token_count": 56, "token_estimator": "heuristic-v1", "text": "## Transaction Construction\n\nBuilding transactions in the Polkadot SDK involves constructing a payload that can be verified, signed, and submitted for inclusion in a block. Each runtime in the Polkadot SDK has its own rules for validating and executing transactions, but there are common patterns for constructing a signed transaction."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 10, "depth": 3, "title": "Construct a Signed Transaction", "anchor": "construct-a-signed-transaction", "start_char": 10991, "end_char": 12900, "estimated_token_count": 404, "token_estimator": "heuristic-v1", "text": "### Construct a Signed Transaction\n\nA signed transaction in the Polkadot SDK includes various pieces of data to ensure security, prevent replay attacks, and prioritize processing. Here's an overview of how to construct one:\n\n1. **Construct the unsigned payload**: Gather the necessary information for the call, including:\n\n - **Pallet index**: Identifies the pallet where the runtime function resides.\n - **Function index**: Specifies the particular function to call in the pallet.\n - **Parameters**: Any additional arguments required by the function call.\n\n2. **Create a signing payload**: Once the unsigned payload is ready, additional data must be included:\n\n - **Transaction nonce**: Unique identifier to prevent replay attacks.\n - **Era information**: Defines how long the transaction is valid before it's dropped from the pool.\n - **Block hash**: Ensures the transaction doesn't execute on the wrong chain or fork.\n\n3. **Sign the payload**: Using the sender's private key, sign the payload to ensure that the transaction can only be executed by the account holder.\n4. **Serialize the signed payload**: Once signed, the transaction must be serialized into a binary format, ensuring the data is compact and easy to transmit over the network.\n5. **Submit the serialized transaction**: Finally, submit the serialized transaction to the network, where it will enter the transaction pool and wait for processing by an authoring node.\n\nThe following is an example of how a signed transaction might look:\n\n``` rust\nnode_runtime::UncheckedExtrinsic::new_signed(\n function.clone(), // some call\n sp_runtime::AccountId32::from(sender.public()).into(), // some sending account\n node_runtime::Signature::Sr25519(signature.clone()), // the account's signature\n extra.clone(), // the signed extensions\n)\n```"} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 11, "depth": 3, "title": "Transaction Encoding", "anchor": "transaction-encoding", "start_char": 12900, "end_char": 13898, "estimated_token_count": 225, "token_estimator": "heuristic-v1", "text": "### Transaction Encoding\n\nBefore a transaction is sent to the network, it is serialized and encoded using a structured encoding process that ensures consistency and prevents tampering:\n\n- **`[1]`**: Compact encoded length in bytes of the entire transaction.\n- **`[2]`**: A u8 containing 1 byte to indicate whether the transaction is signed or unsigned (1 bit) and the encoded transaction version ID (7 bits).\n- **`[3]`**: If signed, this field contains an account ID, an SR25519 signature, and some extra data.\n- **`[4]`**: Encoded call data, including pallet and function indices and any required arguments.\n\nThis encoded format ensures consistency and efficiency in processing transactions across the network. By adhering to this format, applications can construct valid transactions and pass them to the network for execution.\n\nTo learn more about how compact encoding works using SCALE, see the [SCALE Codec](https://github.com/paritytech/parity-scale-codec){target=\\_blank} README on GitHub."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 12, "depth": 3, "title": "Customize Transaction Construction", "anchor": "customize-transaction-construction", "start_char": 13898, "end_char": 14538, "estimated_token_count": 112, "token_estimator": "heuristic-v1", "text": "### Customize Transaction Construction\n\nAlthough the basic steps for constructing transactions are consistent across Polkadot SDK-based chains, developers can customize transaction formats and validation rules. For example:\n\n- **Custom pallets**: You can define new pallets with custom function calls, each with its own parameters and validation logic.\n- **Signed extensions**: Developers can implement custom extensions that modify how transactions are prioritized, validated, or included in blocks.\n\nBy leveraging Polkadot SDK's modular design, developers can create highly specialized transaction logic tailored to their chain's needs."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 13, "depth": 2, "title": "Lifecycle of a Transaction", "anchor": "lifecycle-of-a-transaction", "start_char": 14538, "end_char": 15016, "estimated_token_count": 81, "token_estimator": "heuristic-v1", "text": "## Lifecycle of a Transaction\n\nIn the Polkadot SDK, transactions are often referred to as extrinsics because the data in transactions originates outside of the runtime. These transactions contain data that initiates changes to the chain state. The most common type of extrinsic is a signed transaction, which is cryptographically verified and typically incurs a fee. This section focuses on how signed transactions are processed, validated, and ultimately included in a block."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 14, "depth": 3, "title": "Define Transaction Properties", "anchor": "define-transaction-properties", "start_char": 15016, "end_char": 15747, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "### Define Transaction Properties\n\nThe Polkadot SDK runtime defines key transaction properties, such as:\n\n- **Transaction validity**: Ensures the transaction meets all runtime requirements.\n- **Signed or unsigned**: Identifies whether a transaction needs to be signed by an account.\n- **State changes**: Determines how the transaction modifies the state of the chain.\n\nPallets, which compose the runtime's logic, define the specific transactions that your chain supports. When a user submits a transaction, such as a token transfer, it becomes a signed transaction, verified by the user's account signature. If the account has enough funds to cover fees, the transaction is executed, and the chain's state is updated accordingly."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 15, "depth": 3, "title": "Process on a Block Authoring Node", "anchor": "process-on-a-block-authoring-node", "start_char": 15747, "end_char": 16444, "estimated_token_count": 135, "token_estimator": "heuristic-v1", "text": "### Process on a Block Authoring Node\n\nIn Polkadot SDK-based networks, some nodes are authorized to author blocks. These nodes validate and process transactions. When a transaction is sent to a node that can produce blocks, it undergoes a lifecycle that involves several stages, including validation and execution. Non-authoring nodes gossip the transaction across the network until an authoring node receives it. The following diagram illustrates the lifecycle of a transaction that's submitted to a network and processed by an authoring node.\n\n![Transaction lifecycle diagram](/images/reference/parachains/blocks-transactions-fees/transactions/transactions-01.webp){ style=\"background:white\" }"} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 16, "depth": 3, "title": "Validate and Queue", "anchor": "validate-and-queue", "start_char": 16444, "end_char": 18688, "estimated_token_count": 436, "token_estimator": "heuristic-v1", "text": "### Validate and Queue\n\nOnce a transaction reaches an authoring node, it undergoes an initial validation process to ensure it meets specific conditions defined in the runtime. This validation includes checks for:\n\n- **Correct nonce**: Ensures the transaction is sequentially valid for the account.\n- **Sufficient funds**: Confirms the account can cover any associated transaction fees.\n- **Signature validity**: Verifies that the sender's signature matches the transaction data.\n\nAfter these checks, valid transactions are placed in the transaction pool, where they are queued for inclusion in a block. The transaction pool regularly re-validates queued transactions to ensure they remain valid before being processed. To reach consensus, two-thirds of the nodes must agree on the order of the transactions executed and the resulting state change. Transactions are validated and queued on the local node in a transaction pool to prepare for consensus.\n\n#### Transaction Pool\n\nThe transaction pool is responsible for managing valid transactions. It ensures that only transactions that pass initial validity checks are queued. Transactions that fail validation, expire, or become invalid for other reasons are removed from the pool.\n\nThe transaction pool organizes transactions into two queues:\n\n- **Ready queue**: Transactions that are valid and ready to be included in a block.\n- **Future queue**: Transactions that are not yet valid but could be in the future, such as transactions with a nonce too high for the current state.\n\nDetails on how the transaction pool validates transactions, including fee and signature handling, can be found in the [`validate_transaction`](https://paritytech.github.io/polkadot-sdk/master/sp_transaction_pool/runtime_api/trait.TaggedTransactionQueue.html#method.validate_transaction){target=\\_blank} method.\n\n#### Invalid Transactions\n\nIf a transaction is invalid, for example, due to an invalid signature or insufficient funds, it is rejected and won't be added to the block. Invalid transactions might be rejected for reasons such as:\n\n- The transaction has already been included in a block.\n- The transaction's signature does not match the sender.\n- The transaction is too large to fit in the current block."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 17, "depth": 3, "title": "Transaction Ordering and Priority", "anchor": "transaction-ordering-and-priority", "start_char": 18688, "end_char": 19326, "estimated_token_count": 128, "token_estimator": "heuristic-v1", "text": "### Transaction Ordering and Priority\n\nWhen a node is selected as the next block author, it prioritizes transactions based on weight, length, and tip amount. The goal is to fill the block with high-priority transactions without exceeding its maximum size or computational limits. Transactions are ordered as follows:\n\n- **Inherents first**: Inherent transactions, such as block timestamp updates, are always placed first.\n- **Nonce-based ordering**: Transactions from the same account are ordered by their nonce.\n- **Fee-based ordering**: Among transactions with the same nonce or priority level, those with higher fees are prioritized."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 18, "depth": 3, "title": "Transaction Execution", "anchor": "transaction-execution", "start_char": 19326, "end_char": 19943, "estimated_token_count": 114, "token_estimator": "heuristic-v1", "text": "### Transaction Execution\n\nOnce a block author selects transactions from the pool, the transactions are executed in priority order. As each transaction is processed, the state changes are written directly to the chain's storage. It's important to note that these changes are not cached, meaning a failed transaction won't revert earlier state changes, which could leave the block in an inconsistent state.\n\nEvents are also written to storage. Runtime logic should not emit an event before performing the associated actions. If the associated transaction fails after the event was emitted, the event will not revert."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 19, "depth": 2, "title": "Transaction Mortality", "anchor": "transaction-mortality", "start_char": 19943, "end_char": 21474, "estimated_token_count": 279, "token_estimator": "heuristic-v1", "text": "## Transaction Mortality\n\nTransactions in the network can be configured as either mortal (with expiration) or immortal (without expiration). Every transaction payload contains a block checkpoint (reference block number and hash) and an era/validity period that determines how many blocks after the checkpoint the transaction remains valid.\n\nWhen a transaction is submitted, the network validates it against these parameters. If the transaction is not included in a block within the specified validity window, it is automatically removed from the transaction queue.\n\n- **Mortal transactions**: Have a finite lifespan and will expire after a specified number of blocks. For example, a transaction with a block checkpoint of 1000 and a validity period of 64 blocks will be valid from blocks 1000 to 1064.\n\n- **Immortal transactions**: Never expire and remain valid indefinitely. To create an immortal transaction, set the block checkpoint to 0 (genesis block), use the genesis hash as a reference, and set the validity period to 0.\n\nHowever, immortal transactions pose significant security risks through replay attacks. If an account is reaped (balance drops to zero, account removed) and later re-funded, malicious actors can replay old immortal transactions.\n\nThe blockchain maintains only a limited number of prior block hashes for reference validation, called `BlockHashCount`. If your validity period exceeds `BlockHashCount`, the effective validity period becomes the minimum of your specified period and the block hash count."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 20, "depth": 2, "title": "Unique Identifiers for Extrinsics", "anchor": "unique-identifiers-for-extrinsics", "start_char": 21474, "end_char": 23370, "estimated_token_count": 427, "token_estimator": "heuristic-v1", "text": "## Unique Identifiers for Extrinsics\n\nTransaction hashes are **not unique identifiers** in Polkadot SDK-based chains.\n\nKey differences from traditional blockchains:\n\n- Transaction hashes serve only as fingerprints of transaction information.\n- Multiple valid transactions can share the same hash.\n- Hash uniqueness assumptions lead to serious issues.\n\nFor example, when an account is reaped (removed due to insufficient balance) and later recreated, it resets to nonce 0, allowing identical transactions to be valid at different points:\n\n| Block | Extrinsic Index | Hash | Origin | Nonce | Call | Result |\n|-------|----------------|------|-----------|-------|---------------------|-------------------------------|\n| 100 | 0 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Account A reaped |\n| 150 | 5 | 0x02 | Account B | 4 | Transfer 7 DOT to A | Account A created (nonce = 0) |\n| 200 | 2 | 0x01 | Account A | 0 | Transfer 5 DOT to B | Successful transaction |\n\nNotice that blocks 100 and 200 contain transactions with identical hashes (0x01) but are completely different, valid operations occurring at different times.\n\nAdditional complexity comes from Polkadot SDK's origin abstraction. Origins can represent collectives, governance bodies, or other non-account entities that don't maintain nonces like regular accounts and might dispatch identical calls multiple times with the same hash values. Each execution occurs in different chain states with different results.\n\nThe correct way to uniquely identify an extrinsic on a Polkadot SDK-based chain is to use the block ID (height or hash) and the extrinsic index. Since the Polkadot SDK defines blocks as headers plus ordered arrays of extrinsics, the index position within a canonical block provides guaranteed uniqueness."} -{"page_id": "reference-parachains-blocks-transactions-fees-transactions", "page_title": "Transactions", "index": 21, "depth": 2, "title": "Additional Resources", "anchor": "additional-resources", "start_char": 23370, "end_char": 23610, "estimated_token_count": 55, "token_estimator": "heuristic-v1", "text": "## Additional Resources\n\nFor a video overview of the lifecycle of transactions and the types of transactions that exist, see the [Transaction lifecycle](https://www.youtube.com/watch?v=3pfM0GOp02c){target=\\_blank} seminar from Parity Tech."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 14, "end_char": 612, "estimated_token_count": 94, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nUnderstanding and leveraging on-chain data is a fundamental aspect of blockchain development. Whether you're building frontend applications or backend systems, accessing and decoding runtime metadata is vital to interacting with the blockchain. This guide introduces you to the tools and processes for generating and retrieving metadata, explains its role in application development, and outlines the additional APIs available for interacting with a Polkadot node. By mastering these components, you can ensure seamless communication between your applications and the blockchain."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 1, "depth": 2, "title": "Application Development", "anchor": "application-development", "start_char": 612, "end_char": 1674, "estimated_token_count": 195, "token_estimator": "heuristic-v1", "text": "## Application Development\n\nYou might not be directly involved in building frontend applications as a blockchain developer. However, most applications that run on a blockchain require some form of frontend or user-facing client to enable users or other programs to access and modify the data that the blockchain stores. For example, you might develop a browser-based, mobile, or desktop application that allows users to submit transactions, post articles, view their assets, or track previous activity. The backend for that application is configured in the runtime logic for your blockchain, but the frontend client makes the runtime features accessible to your users.\n\nFor your custom chain to be useful to others, you'll need to provide a client application that allows users to view, interact with, or update information that the blockchain keeps track of. In this article, you'll learn how to expose information about your runtime so that client applications can use it, see examples of the information exposed, and explore tools and libraries that use it."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 2, "depth": 2, "title": "Understand Metadata", "anchor": "understand-metadata", "start_char": 1674, "end_char": 2274, "estimated_token_count": 112, "token_estimator": "heuristic-v1", "text": "## Understand Metadata\n\nPolkadot SDK-based blockchain networks are designed to expose their runtime information, allowing developers to learn granular details regarding pallets, RPC calls, and runtime APIs. The metadata also exposes their related documentation. The chain's metadata is [SCALE-encoded](/reference/parachains/data-encoding/){target=\\_blank}, allowing for the development of browser-based, mobile, or desktop applications to support the chain's runtime upgrades seamlessly. It is also possible to develop applications compatible with multiple Polkadot SDK-based chains simultaneously."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 3, "depth": 2, "title": "Expose Runtime Information as Metadata", "anchor": "expose-runtime-information-as-metadata", "start_char": 2274, "end_char": 3873, "estimated_token_count": 282, "token_estimator": "heuristic-v1", "text": "## Expose Runtime Information as Metadata\n\nTo interact with a node or the state of the blockchain, you need to know how to connect to the chain and access the exposed runtime features. This interaction involves a Remote Procedure Call (RPC) through a node endpoint address, commonly through a secure web socket connection.\n\nAn application developer typically needs to know the contents of the runtime logic, including the following details:\n\n- Version of the runtime the application is connecting to.\n- Supported APIs.\n- Implemented pallets.\n- Defined functions and corresponding type signatures.\n- Defined custom types.\n- Exposed parameters users can set.\n\nAs the Polkadot SDK is modular and provides a composable framework for building blockchains, there are limitless opportunities to customize the schema of properties. Each runtime can be configured with its properties, including function calls and types, which can be changed over time with runtime upgrades.\n\nThe Polkadot SDK enables you to generate the runtime metadata schema to capture information unique to a runtime. The metadata for a runtime describes the pallets in use and types defined for a specific runtime version. The metadata includes information about each pallet's storage items, functions, events, errors, and constants. The metadata also provides type definitions for any custom types included in the runtime.\n\nMetadata provides a complete inventory of a chain's runtime. It is key to enabling client applications to interact with the node, parse responses, and correctly format message payloads sent back to that chain."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 4, "depth": 2, "title": "Generate Metadata", "anchor": "generate-metadata", "start_char": 3873, "end_char": 5179, "estimated_token_count": 297, "token_estimator": "heuristic-v1", "text": "## Generate Metadata\n\nTo efficiently use the blockchain's networking resources and minimize the data transmitted over the network, the metadata schema is encoded using the [Parity SCALE Codec](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\\_blank}. This encoding is done automatically through the [`scale-info`](https://docs.rs/scale-info/latest/scale_info/){target=\\_blank}crate.\n\nAt a high level, generating the metadata involves the following steps:\n\n1. The pallets in the runtime logic expose callable functions, types, parameters, and documentation that need to be encoded in the metadata.\n2. The `scale-info` crate collects type information for the pallets in the runtime, builds a registry of the pallets that exist in a particular runtime, and the relevant types for each pallet in the registry. The type information is detailed enough to enable encoding and decoding for every type.\n3. The [`frame-metadata`](https://github.com/paritytech/frame-metadata){target=\\_blank} crate describes the structure of the runtime based on the registry provided by the `scale-info` crate.\n4. Nodes provide the RPC method `state_getMetadata` to return a complete description of all the types in the current runtime as a hex-encoded vector of SCALE-encoded bytes."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 5, "depth": 2, "title": "Retrieve Runtime Metadata", "anchor": "retrieve-runtime-metadata", "start_char": 5179, "end_char": 5695, "estimated_token_count": 98, "token_estimator": "heuristic-v1", "text": "## Retrieve Runtime Metadata\n\nThe type information provided by the metadata enables applications to communicate with nodes using different runtime versions and across chains that expose different calls, events, types, and storage items. The metadata also allows libraries to generate a substantial portion of the code needed to communicate with a given node, enabling libraries like [`subxt`](https://github.com/paritytech/subxt){target=\\_blank} to generate frontend interfaces that are specific to a target chain."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 6, "depth": 3, "title": "Use Polkadot.js", "anchor": "use-polkadotjs", "start_char": 5695, "end_char": 6146, "estimated_token_count": 131, "token_estimator": "heuristic-v1", "text": "### Use Polkadot.js\n\nVisit the [Polkadot.js Portal](https://polkadot.js.org/apps/#/rpc){target=\\_blank} and select the **Developer** dropdown in the top banner. Select **RPC Calls** to make the call to request metadata. Follow these steps to make the RPC call:\n\n1. Select **state** as the endpoint to call.\n2. Select **`getMetadata(at)`** as the method to call.\n3. Click **Submit RPC call** to submit the call and return the metadata in JSON format."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 7, "depth": 3, "title": "Use Curl", "anchor": "use-curl", "start_char": 6146, "end_char": 6460, "estimated_token_count": 95, "token_estimator": "heuristic-v1", "text": "### Use Curl \n\nYou can fetch the metadata for the network by calling the node's RPC endpoint. This request returns the metadata in bytes rather than human-readable JSON:\n\n```sh\ncurl -H \"Content-Type: application/json\" \\\n-d '{\"id\":1, \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\"}' \\\nhttps://rpc.polkadot.io\n\n```"} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 8, "depth": 3, "title": "Use Subxt", "anchor": "use-subxt", "start_char": 6460, "end_char": 6826, "estimated_token_count": 116, "token_estimator": "heuristic-v1", "text": "### Use Subxt\n\n[`subxt`](https://github.com/paritytech/subxt){target=\\_blank} may also be used to fetch the metadata of any data in a human-readable JSON format: \n\n```sh\nsubxt metadata --url wss://rpc.polkadot.io --format json > spec.json\n```\n\nAnother option is to use the [`subxt` explorer web UI](https://paritytech.github.io/subxt-explorer/#/){target=\\_blank}."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 9, "depth": 2, "title": "Client Applications and Metadata", "anchor": "client-applications-and-metadata", "start_char": 6826, "end_char": 7379, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "## Client Applications and Metadata\n\nThe metadata exposes the expected way to decode each type, meaning applications can send, retrieve, and process application information without manual encoding and decoding. Client applications must use the [SCALE codec library](https://github.com/paritytech/parity-scale-codec?tab=readme-ov-file#parity-scale-codec){target=\\_blank} to encode and decode RPC payloads to use the metadata. Client applications use the metadata to interact with the node, parse responses, and format message payloads sent to the node."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 10, "depth": 2, "title": "Metadata Format", "anchor": "metadata-format", "start_char": 7379, "end_char": 9561, "estimated_token_count": 466, "token_estimator": "heuristic-v1", "text": "## Metadata Format\n\nAlthough the SCALE-encoded bytes can be decoded using the `frame-metadata` and [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\\_blank} libraries, there are other tools, such as `subxt` and the Polkadot-JS API, that can convert the raw data to human-readable JSON format.\n\nThe types and type definitions included in the metadata returned by the `state_getMetadata` RPC call depend on the runtime's metadata version.\n\nIn general, the metadata includes the following information:\n\n- A constant identifying the file as containing metadata.\n- The version of the metadata format used in the runtime.\n- Type definitions for all types used in the runtime and generated by the `scale-info` crate.\n- Pallet information for the pallets included in the runtime in the order that they are defined in the `construct_runtime` macro.\n\n!!!tip \n Depending on the frontend library used (such as the [Polkadot API](https://papi.how/){target=\\_blank}), they may format the metadata differently than the raw format shown.\n\nThe following example illustrates a condensed and annotated section of metadata decoded and converted to JSON:\n\n```json\n[\n 1635018093,\n {\n \"V14\": {\n \"types\": {\n \"types\": [{}]\n },\n \"pallets\": [{}],\n \"extrinsic\": {\n \"ty\": 126,\n \"version\": 4,\n \"signed_extensions\": [{}]\n },\n \"ty\": 141\n }\n }\n]\n\n```\n\nThe constant `1635018093` is a magic number that identifies the file as a metadata file. The rest of the metadata is divided into the `types`, `pallets`, and `extrinsic` sections:\n\n- The `types` section contains an index of the types and information about each type's type signature.\n- The `pallets` section contains information about each pallet in the runtime.\n- The `extrinsic` section describes the type identifier and transaction format version that the runtime uses.\n\nDifferent extrinsic versions can have varying formats, especially when considering [signed transactions](/reference/parachains/blocks-transactions-fees/transactions/#signed-transactions){target=\\_blank}."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 11, "depth": 3, "title": "Pallets", "anchor": "pallets", "start_char": 9561, "end_char": 15081, "estimated_token_count": 986, "token_estimator": "heuristic-v1", "text": "### Pallets\n\nThe following is a condensed and annotated example of metadata for a single element in the `pallets` array (the [`sudo`](https://paritytech.github.io/polkadot-sdk/master/pallet_sudo/index.html){target=\\_blank} pallet):\n\n```json\n{\n \"name\": \"Sudo\",\n \"storage\": {\n \"prefix\": \"Sudo\",\n \"entries\": [\n {\n \"name\": \"Key\",\n \"modifier\": \"Optional\",\n \"ty\": {\n \"Plain\": 0\n },\n \"default\": [0],\n \"docs\": [\"The `AccountId` of the sudo key.\"]\n }\n ]\n },\n \"calls\": {\n \"ty\": 117\n },\n \"event\": {\n \"ty\": 42\n },\n \"constants\": [],\n \"error\": {\n \"ty\": 124\n },\n \"index\": 8\n}\n\n```\n\nEvery element metadata contains the name of the pallet it represents and information about its storage, calls, events, and errors. You can look up details about the definition of the calls, events, and errors by viewing the type index identifier. The type index identifier is the `u32` integer used to access the type information for that item. For example, the type index identifier for calls in the Sudo pallet is 117. If you view information for that type identifier in the `types` section of the metadata, it provides information about the available calls, including the documentation for each call.\n\nFor example, the following is a condensed excerpt of the calls for the Sudo pallet:\n\n```json\n{\n \"id\": 117,\n \"type\": {\n \"path\": [\"pallet_sudo\", \"pallet\", \"Call\"],\n \"params\": [\n {\n \"name\": \"T\",\n \"type\": null\n }\n ],\n \"def\": {\n \"variant\": {\n \"variants\": [\n {\n \"name\": \"sudo\",\n \"fields\": [\n {\n \"name\": \"call\",\n \"type\": 114,\n \"typeName\": \"Box<::RuntimeCall>\"\n }\n ],\n \"index\": 0,\n \"docs\": [\n \"Authenticates sudo key, dispatches a function call with `Root` origin\"\n ]\n },\n {\n \"name\": \"sudo_unchecked_weight\",\n \"fields\": [\n {\n \"name\": \"call\",\n \"type\": 114,\n \"typeName\": \"Box<::RuntimeCall>\"\n },\n {\n \"name\": \"weight\",\n \"type\": 8,\n \"typeName\": \"Weight\"\n }\n ],\n \"index\": 1,\n \"docs\": [\n \"Authenticates sudo key, dispatches a function call with `Root` origin\"\n ]\n },\n {\n \"name\": \"set_key\",\n \"fields\": [\n {\n \"name\": \"new\",\n \"type\": 103,\n \"typeName\": \"AccountIdLookupOf\"\n }\n ],\n \"index\": 2,\n \"docs\": [\n \"Authenticates current sudo key, sets the given AccountId (`new`) as the new sudo\"\n ]\n },\n {\n \"name\": \"sudo_as\",\n \"fields\": [\n {\n \"name\": \"who\",\n \"type\": 103,\n \"typeName\": \"AccountIdLookupOf\"\n },\n {\n \"name\": \"call\",\n \"type\": 114,\n \"typeName\": \"Box<::RuntimeCall>\"\n }\n ],\n \"index\": 3,\n \"docs\": [\n \"Authenticates sudo key, dispatches a function call with `Signed` origin from a given account\"\n ]\n }\n ]\n }\n }\n }\n}\n\n```\n\nFor each field, you can access type information and metadata for the following:\n\n- **Storage metadata**: Provides the information required to enable applications to get information for specific storage items.\n- **Call metadata**: Includes information about the runtime calls defined by the `#[pallet]` macro including call names, arguments and documentation.\n- **Event metadata**: Provides the metadata generated by the `#[pallet::event]` macro, including the name, arguments, and documentation for each pallet event.\n- **Constants metadata**: Provides metadata generated by the `#[pallet::constant]` macro, including the name, type, and hex-encoded value of the constant.\n- **Error metadata**: Provides metadata generated by the `#[pallet::error]` macro, including the name and documentation for each pallet error.\n\n!!!tip\n Type identifiers change from time to time, so you should avoid relying on specific type identifiers in your applications."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 12, "depth": 3, "title": "Extrinsic", "anchor": "extrinsic", "start_char": 15081, "end_char": 17205, "estimated_token_count": 384, "token_estimator": "heuristic-v1", "text": "### Extrinsic\n\nThe runtime generates extrinsic metadata and provides useful information about transaction format. When decoded, the metadata contains the transaction version and the list of signed extensions.\n\nFor example:\n\n```json\n{\n \"extrinsic\": {\n \"ty\": 126,\n \"version\": 4,\n \"signed_extensions\": [\n {\n \"identifier\": \"CheckNonZeroSender\",\n \"ty\": 132,\n \"additional_signed\": 41\n },\n {\n \"identifier\": \"CheckSpecVersion\",\n \"ty\": 133,\n \"additional_signed\": 4\n },\n {\n \"identifier\": \"CheckTxVersion\",\n \"ty\": 134,\n \"additional_signed\": 4\n },\n {\n \"identifier\": \"CheckGenesis\",\n \"ty\": 135,\n \"additional_signed\": 11\n },\n {\n \"identifier\": \"CheckMortality\",\n \"ty\": 136,\n \"additional_signed\": 11\n },\n {\n \"identifier\": \"CheckNonce\",\n \"ty\": 138,\n \"additional_signed\": 41\n },\n {\n \"identifier\": \"CheckWeight\",\n \"ty\": 139,\n \"additional_signed\": 41\n },\n {\n \"identifier\": \"ChargeTransactionPayment\",\n \"ty\": 140,\n \"additional_signed\": 41\n }\n ]\n },\n \"ty\": 141\n}\n\n```\n\nThe type system is [composite](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/reference_docs/frame_runtime_types/index.html){target=\\_blank}, meaning each type identifier contains a reference to a specific type or to another type identifier that provides information about the associated primitive types.\n\nFor example, you can encode the `BitVec` type, but to decode it properly, you must know the types used for the `Order` and `Store` types. To find type information for `Order` and `Store`, you can use the path in the decoded JSON to locate their type identifiers."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 13, "depth": 2, "title": "Included RPC APIs", "anchor": "included-rpc-apis", "start_char": 17205, "end_char": 18317, "estimated_token_count": 302, "token_estimator": "heuristic-v1", "text": "## Included RPC APIs\n\nA standard node comes with the following APIs to interact with a node:\n\n- **[`AuthorApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/author/trait.AuthorApiServer.html){target=\\_blank}**: Make calls into a full node, including authoring extrinsics and verifying session keys.\n- **[`ChainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/chain/trait.ChainApiServer.html){target=\\_blank}**: Retrieve block header and finality information.\n- **[`OffchainApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/offchain/trait.OffchainApiServer.html){target=\\_blank}**: Make RPC calls for off-chain workers.\n- **[`StateApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/state/trait.StateApiServer.html){target=\\_blank}**: Query information about on-chain state such as runtime version, storage items, and proofs.\n- **[`SystemApiServer`](https://paritytech.github.io/polkadot-sdk/master/sc_rpc/system/trait.SystemApiServer.html){target=\\_blank}**: Retrieve information about network state, such as connected peers and node roles."} -{"page_id": "reference-parachains-chain-data", "page_title": "Chain Data", "index": 14, "depth": 2, "title": "Additional Resources", "anchor": "additional-resources", "start_char": 18317, "end_char": 18650, "estimated_token_count": 101, "token_estimator": "heuristic-v1", "text": "## Additional Resources\n\nThe following tools can help you locate and decode metadata:\n\n- [Subxt Explorer](https://paritytech.github.io/subxt-explorer/#/){target=\\_blank}\n- [Metadata Portal 🌗](https://github.com/paritytech/metadata-portal){target=\\_blank}\n- [De[code] Sub[strate]](https://github.com/paritytech/desub){target=\\_blank}"} -{"page_id": "reference-parachains-consensus-elastic-scaling", "page_title": "Elastic Scaling", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 19, "end_char": 842, "estimated_token_count": 130, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot's architecture delivers scalability and security through its shared security model, where the relay chain coordinates and validates multiple parallel chains. \n\nElastic scaling enhances this architecture by allowing parachains to utilize multiple computational cores simultaneously, breaking the previous 1:1 relationship between parachain and relay chain blocks.\n\nThis technical advancement enables parachains to process multiple blocks within a single relay chain block, significantly increasing throughput capabilities. By leveraging [Agile Coretime](/polkadot-protocol/architecture/polkadot-chain/agile-coretime){target=\\_blank}, parachains can dynamically adjust their processing capacity based on demand, creating an efficient and responsive infrastructure for high-throughput applications."} -{"page_id": "reference-parachains-consensus-elastic-scaling", "page_title": "Elastic Scaling", "index": 1, "depth": 2, "title": "How Elastic Scaling Works", "anchor": "how-elastic-scaling-works", "start_char": 842, "end_char": 4212, "estimated_token_count": 710, "token_estimator": "heuristic-v1", "text": "## How Elastic Scaling Works\n\nElastic scaling enables parachains to process multiple blocks in parallel by utilizing additional cores on the relay chain. This section provides a technical analysis of the performance advantages and details of the implementation.\n\nConsider a parachain that needs to process four consecutive parablocks. With traditional single-core allocation, the validation process follows a strictly sequential pattern. Each parablock undergoes a two-phase process on the relay chain:\n\n1. **Backing phase**: Validators create and distribute validity statements.\n2. **Inclusion phase**: The parablock is included in the relay chain after availability verification.\n\nThroughout the following diagrams, specific notation is used to represent different components of the system:\n\n- **R1, R2, ...**: Relay chain blocks (produced at ~6-second intervals).\n- **P1, P2, ...**: Parachain blocks that need validation and inclusion.\n- **C1, C2, ...**: Cores on the relay chain.\n\nIn the single-core scenario (assuming a 6-second relay chain block time), processing four parablocks requires approximately 30 seconds:\n\n```mermaid\nsequenceDiagram\n participant R1 as R1\n participant R2 as R2\n participant R3 as R3\n participant R4 as R4\n participant R5 as R5\n \n Note over R1,R5: Single Core Scenario\n \n rect rgb(200, 220, 240)\n Note right of R1: Core C1\n R1->>R1: Back P1\n R2->>R2: Include P1\n R2->>R2: Back P2\n R3->>R3: Include P2\n R3->>R3: Back P3\n R4->>R4: Include P3\n R4->>R4: Back P4\n R5->>R5: Include P4\n end\n```\n\nWith elastic scaling utilizing two cores simultaneously, the same four parablocks can be processed in approximately 18 seconds:\n\n```mermaid\nsequenceDiagram\n participant R1 as R1\n participant R2 as R2\n participant R3 as R3\n participant R4 as R4\n participant R5 as R5\n \n Note over R1,R3: Multi-Core Scenario\n \n rect rgb(200, 220, 240)\n Note right of R1: Core C1\n R1->>R1: Back P1\n R2->>R2: Include P1\n R2->>R2: Back P2\n R3->>R3: Include P2\n end\n \n rect rgb(220, 200, 240)\n Note right of R1: Core C2\n R1->>R1: Back P3\n R2->>R2: Include P3\n R2->>R2: Back P4\n R3->>R3: Include P4\n end\n```\n\nTo help interpret the sequence diagrams above, note the following key elements:\n\n- The horizontal axis represents time progression through relay chain blocks (R1-R5).\n- Each colored rectangle shows processing on a specific core (C1 or C2).\n- In the single-core scenario, all blocks must be processed sequentially on one core.\n- In the multi-core scenario, blocks are processed in parallel across multiple cores, reducing total time.\n\nThe relay chain processes these multiple parablocks as independent validation units during the backing, availability, and approval phases. However, during inclusion, it verifies that their state roots align properly to maintain chain consistency.\n\nFrom an implementation perspective:\n\n- **Parachain side**: Collators must increase their block production rate to utilize multiple cores fully.\n- **Validation process**: Each core operates independently, but with coordinated state verification.\n- **Resource management**: Cores are dynamically allocated based on parachain requirements.\n- **State consistency**: While backed and processed in parallel, the parablocks maintain sequential state transitions."} -{"page_id": "reference-parachains-consensus-elastic-scaling", "page_title": "Elastic Scaling", "index": 2, "depth": 2, "title": "Benefits of Elastic Scaling", "anchor": "benefits-of-elastic-scaling", "start_char": 4212, "end_char": 6001, "estimated_token_count": 288, "token_estimator": "heuristic-v1", "text": "## Benefits of Elastic Scaling\n\n- **Increased throughput**: Multiple concurrent cores enable parachains to process transactions at multiples of their previous capacity. By allowing multiple parachain blocks to be validated within each relay chain block cycle, applications can achieve significantly higher transaction volumes.\n\n- **Lower latency**: Transaction finality improves substantially with multi-core processing. Parachains currently achieve 2-second latency with three cores, with projected improvements to 500ms using 12 cores, enabling near-real-time application responsiveness.\n\n- **Resource efficiency**: Applications acquire computational resources precisely matched to their needs, eliminating wasteful over-provisioning. Coretime can be purchased at granular intervals (blocks, hours, days), creating cost-effective operations, particularly for applications with variable transaction patterns.\n\n- **Scalable growth**: New applications can launch with minimal initial resource commitment and scale dynamically as adoption increases. This eliminates the traditional paradox of either over-allocating resources (increasing costs) or under-allocating (degrading performance) during growth phases.\n\n- **Workload distribution**: Parachains intelligently distribute workloads across cores during peak demand periods and release resources when traffic subsides. Paired with secondary coretime markets, this ensures maximum resource utilization across the entire network ecosystem.\n\n- **Reliable performance**: End-users experience reliable application performance regardless of network congestion levels. Applications maintain responsiveness even during traffic spikes, eliminating performance degradation that commonly impacts blockchain applications during high-demand periods."} -{"page_id": "reference-parachains-consensus-elastic-scaling", "page_title": "Elastic Scaling", "index": 3, "depth": 2, "title": "Use Cases", "anchor": "use-cases", "start_char": 6001, "end_char": 6369, "estimated_token_count": 54, "token_estimator": "heuristic-v1", "text": "## Use Cases\n\nElastic scaling enables applications to dynamically adjust their resource consumption based on real-time demand. This is especially valuable for decentralized applications where usage patterns can be highly variable. The following examples illustrate common scenarios where elastic scaling delivers significant performance and cost-efficiency benefits."} -{"page_id": "reference-parachains-consensus-elastic-scaling", "page_title": "Elastic Scaling", "index": 4, "depth": 3, "title": "Handling Sudden Traffic Spikes", "anchor": "handling-sudden-traffic-spikes", "start_char": 6369, "end_char": 6786, "estimated_token_count": 64, "token_estimator": "heuristic-v1", "text": "### Handling Sudden Traffic Spikes\n\nMany decentralized applications experience unpredictable, high-volume traffic bursts, especially in gaming, DeFi protocols, NFT auctions, messaging platforms, and social media. Elastic scaling allows these systems to acquire additional coretime during peak usage and release it during quieter periods, ensuring responsiveness without incurring constant high infrastructure costs."} -{"page_id": "reference-parachains-consensus-elastic-scaling", "page_title": "Elastic Scaling", "index": 5, "depth": 3, "title": "Supporting Early-Stage Growth", "anchor": "supporting-early-stage-growth", "start_char": 6786, "end_char": 7168, "estimated_token_count": 69, "token_estimator": "heuristic-v1", "text": "### Supporting Early-Stage Growth\n\nStartups and new projects often begin with uncertain or volatile demand. With elastic scaling, teams can launch with minimal compute resources (e.g., a single core) and gradually scale as adoption increases. This prevents overprovisioning and enables cost-efficient growth until the application is ready for more permanent or horizontal scaling."} -{"page_id": "reference-parachains-consensus-elastic-scaling", "page_title": "Elastic Scaling", "index": 6, "depth": 3, "title": "Scaling Massive IoT Networks", "anchor": "scaling-massive-iot-networks", "start_char": 7168, "end_char": 7556, "estimated_token_count": 67, "token_estimator": "heuristic-v1", "text": "### Scaling Massive IoT Networks\n\nInternet of Things (IoT) applications often involve processing data from millions of devices in real time. Elastic scaling supports this need by enabling high-throughput transaction processing as demand fluctuates. Combined with Polkadot’s shared security model, it provides a reliable and privacy-preserving foundation for large-scale IoT deployments."} -{"page_id": "reference-parachains-consensus-elastic-scaling", "page_title": "Elastic Scaling", "index": 7, "depth": 3, "title": "Powering Real-Time, Low-Latency Systems", "anchor": "powering-real-time-low-latency-systems", "start_char": 7556, "end_char": 7871, "estimated_token_count": 58, "token_estimator": "heuristic-v1", "text": "### Powering Real-Time, Low-Latency Systems\n\nApplications like payment processors, trading platforms, gaming engines, or real-time data feeds require fast, consistent performance. Elastic scaling can reduce execution latency during demand spikes, helping ensure low-latency, reliable service even under heavy load."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 16, "end_char": 525, "estimated_token_count": 73, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nCryptography forms the backbone of blockchain technology, providing the mathematical verifiability crucial for consensus systems, data integrity, and user security. While a deep understanding of the underlying mathematical processes isn't necessary for most blockchain developers, grasping the fundamental applications of cryptography is essential. This page comprehensively overviews cryptographic implementations used across Polkadot SDK-based chains and the broader blockchain ecosystem."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 1, "depth": 2, "title": "Hash Functions", "anchor": "hash-functions", "start_char": 525, "end_char": 1170, "estimated_token_count": 130, "token_estimator": "heuristic-v1", "text": "## Hash Functions\n\nHash functions are fundamental to blockchain technology, creating a unique digital fingerprint for any piece of data, including simple text, images, or any other form of file. They map input data of any size to a fixed-size output (typically 32 bytes) using complex mathematical operations. Hashing is used to verify data integrity, create digital signatures, and provide a secure way to store passwords. This form of mapping is known as the [\"pigeonhole principle,\"](https://en.wikipedia.org/wiki/Pigeonhole_principle){target=\\_blank} it is primarily implemented to efficiently and verifiably identify data from large sets."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 2, "depth": 3, "title": "Key Properties of Hash Functions", "anchor": "key-properties-of-hash-functions", "start_char": 1170, "end_char": 1720, "estimated_token_count": 138, "token_estimator": "heuristic-v1", "text": "### Key Properties of Hash Functions\n\n- **Deterministic**: The same input always produces the same output.\n- **Quick computation**: It's easy to calculate the hash value for any given input.\n- **Pre-image resistance**: It's infeasible to generate the input data from its hash.\n- **Small changes in input yield large changes in output**: Known as the [\"avalanche effect\"](https://en.wikipedia.org/wiki/Avalanche_effect){target=\\_blank}.\n- **Collision resistance**: The probabilities are extremely low to find two different inputs with the same hash."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 3, "depth": 3, "title": "Blake2", "anchor": "blake2", "start_char": 1720, "end_char": 2257, "estimated_token_count": 126, "token_estimator": "heuristic-v1", "text": "### Blake2\n\nThe Polkadot SDK utilizes Blake2, a state-of-the-art hashing method that offers:\n\n- Equal or greater security compared to [SHA-2](https://en.wikipedia.org/wiki/SHA-2){target=\\_blank}.\n- Significantly faster performance than other algorithms.\n\nThese properties make Blake2 ideal for blockchain systems, reducing sync times for new nodes and lowering the resources required for validation. For detailed technical specifications about Blake2, see the [official Blake2 paper](https://www.blake2.net/blake2.pdf){target=\\_blank}."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 4, "depth": 2, "title": "Types of Cryptography", "anchor": "types-of-cryptography", "start_char": 2257, "end_char": 2412, "estimated_token_count": 22, "token_estimator": "heuristic-v1", "text": "## Types of Cryptography\n\nThere are two different ways that cryptographic algorithms are implemented: symmetric cryptography and asymmetric cryptography."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 5, "depth": 3, "title": "Symmetric Cryptography", "anchor": "symmetric-cryptography", "start_char": 2412, "end_char": 3256, "estimated_token_count": 162, "token_estimator": "heuristic-v1", "text": "### Symmetric Cryptography\n\nSymmetric encryption is a branch of cryptography that isn't based on one-way functions, unlike asymmetric cryptography. It uses the same cryptographic key to encrypt plain text and decrypt the resulting ciphertext.\n\nSymmetric cryptography is a type of encryption that has been used throughout history, such as the Enigma Cipher and the Caesar Cipher. It is still widely used today and can be found in Web2 and Web3 applications alike. There is only one single key, and a recipient must also have access to it to access the contained information.\n\n#### Advantages {: #symmetric-advantages }\n\n- Fast and efficient for large amounts of data.\n- Requires less computational power.\n\n#### Disadvantages {: #symmetric-disadvantages }\n\n- Key distribution can be challenging.\n- Scalability issues in systems with many users."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 6, "depth": 3, "title": "Asymmetric Cryptography", "anchor": "asymmetric-cryptography", "start_char": 3256, "end_char": 4221, "estimated_token_count": 182, "token_estimator": "heuristic-v1", "text": "### Asymmetric Cryptography\n\nAsymmetric encryption is a type of cryptography that uses two different keys, known as a keypair: a public key, used to encrypt plain text, and a private counterpart, used to decrypt the ciphertext.\n\nThe public key encrypts a fixed-length message that can only be decrypted with the recipient's private key and, sometimes, a set password. The public key can be used to cryptographically verify that the corresponding private key was used to create a piece of data without compromising the private key, such as with digital signatures. This has obvious implications for identity, ownership, and properties and is used in many different protocols across Web2 and Web3.\n\n#### Advantages {: #asymmetric-advantages }\n\n- Solves the key distribution problem.\n- Enables digital signatures and secure key exchange.\n\n#### Disadvantages {: #asymmetric-disadvantages }\n\n- Slower than symmetric encryption.\n- Requires more computational resources."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 7, "depth": 3, "title": "Trade-offs and Compromises", "anchor": "trade-offs-and-compromises", "start_char": 4221, "end_char": 5014, "estimated_token_count": 143, "token_estimator": "heuristic-v1", "text": "### Trade-offs and Compromises\n\nSymmetric cryptography is faster and requires fewer bits in the key to achieve the same level of security that asymmetric cryptography provides. However, it requires a shared secret before communication can occur, which poses issues to its integrity and a potential compromise point. On the other hand, asymmetric cryptography doesn't require the secret to be shared ahead of time, allowing for far better end-user security.\n\nHybrid symmetric and asymmetric cryptography is often used to overcome the engineering issues of asymmetric cryptography, as it is slower and requires more bits in the key to achieve the same level of security. It encrypts a key and then uses the comparatively lightweight symmetric cipher to do the \"heavy lifting\" with the message."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 8, "depth": 2, "title": "Digital Signatures", "anchor": "digital-signatures", "start_char": 5014, "end_char": 6403, "estimated_token_count": 266, "token_estimator": "heuristic-v1", "text": "## Digital Signatures\n\nDigital signatures are a way of verifying the authenticity of a document or message using asymmetric keypairs. They are used to ensure that a sender or signer's document or message hasn't been tampered with in transit, and for recipients to verify that the data is accurate and from the expected sender.\n\nSigning digital signatures only requires a low-level understanding of mathematics and cryptography. For a conceptual example -- when signing a check, it is expected that it cannot be cashed multiple times. This isn't a feature of the signature system but rather the check serialization system. The bank will check that the serial number on the check hasn't already been used. Digital signatures essentially combine these two concepts, allowing the signature to provide the serialization via a unique cryptographic fingerprint that cannot be reproduced.\n\nUnlike pen-and-paper signatures, knowledge of a digital signature cannot be used to create other signatures. Digital signatures are often used in bureaucratic processes, as they are more secure than simply scanning in a signature and pasting it onto a document.\n\nPolkadot SDK provides multiple different cryptographic schemes and is generic so that it can support anything that implements the [`Pair` trait](https://paritytech.github.io/polkadot-sdk/master/sp_core/crypto/trait.Pair.html){target=\\_blank}."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 9, "depth": 3, "title": "Example of Creating a Digital Signature", "anchor": "example-of-creating-a-digital-signature", "start_char": 6403, "end_char": 6977, "estimated_token_count": 117, "token_estimator": "heuristic-v1", "text": "### Example of Creating a Digital Signature\n\nThe process of creating and verifying a digital signature involves several steps:\n\n1. The sender creates a hash of the message.\n2. The hash is encrypted using the sender's private key, creating the signature.\n3. The message and signature are sent to the recipient.\n4. The recipient decrypts the signature using the sender's public key.\n5. The recipient hashes the received message and compares it to the decrypted hash.\n\nIf the hashes match, the signature is valid, confirming the message's integrity and the sender's identity."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 10, "depth": 2, "title": "Elliptic Curve", "anchor": "elliptic-curve", "start_char": 6977, "end_char": 7869, "estimated_token_count": 170, "token_estimator": "heuristic-v1", "text": "## Elliptic Curve\n\nBlockchain technology requires the ability to have multiple keys creating a signature for block proposal and validation. To this end, Elliptic Curve Digital Signature Algorithm (ECDSA) and Schnorr signatures are two of the most commonly used methods. While ECDSA is a far simpler implementation, Schnorr signatures are more efficient when it comes to multi-signatures.\n\nSchnorr signatures bring some noticeable features over the ECDSA/EdDSA schemes:\n\n- It is better for hierarchical deterministic key derivations.\n- It allows for native multi-signature through [signature aggregation](https://bitcoincore.org/en/2017/03/23/schnorr-signature-aggregation/){target=\\_blank}.\n- It is generally more resistant to misuse.\n\nOne sacrifice that is made when using Schnorr signatures over ECDSA is that both require 64 bytes, but only ECDSA signatures communicate their public key."} -{"page_id": "reference-parachains-cryptography", "page_title": "Cryptography", "index": 11, "depth": 3, "title": "Various Implementations", "anchor": "various-implementations", "start_char": 7869, "end_char": 8860, "estimated_token_count": 268, "token_estimator": "heuristic-v1", "text": "### Various Implementations\n\n- **[ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm){target=\\_blank}**: Polkadot SDK provides an ECDSA signature scheme using the [secp256k1](https://en.bitcoin.it/wiki/Secp256k1){target=\\_blank} curve. This is the same cryptographic algorithm used to secure [Bitcoin](https://en.wikipedia.org/wiki/Bitcoin){target=\\_blank} and [Ethereum](https://en.wikipedia.org/wiki/Ethereum){target=\\_blank}.\n\n- **[Ed25519](https://en.wikipedia.org/wiki/EdDSA#Ed25519){target=\\_blank}**: An EdDSA signature scheme using [Curve25519](https://en.wikipedia.org/wiki/Curve25519){target=\\_blank}. It is carefully engineered at several levels of design and implementation to achieve very high speeds without compromising security.\n\n- **[SR25519](https://research.web3.foundation/Polkadot/security/keys/accounts-more){target=\\_blank}**: Based on the same underlying curve as Ed25519. However, it uses Schnorr signatures instead of the EdDSA scheme."} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 17, "end_char": 1595, "estimated_token_count": 332, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe Polkadot SDK uses a lightweight and efficient encoding/decoding mechanism to optimize data transmission across the network. This mechanism, known as the _SCALE_ codec, is used for serializing and deserializing data.\n\nThe SCALE codec enables communication between the runtime and the outer node. This mechanism is designed for high-performance, copy-free data encoding and decoding in resource-constrained environments like the Polkadot SDK [Wasm runtime](/develop/parachains/deployment/build-deterministic-runtime/#introduction){target=\\_blank}.\n\nIt is not self-describing, meaning the decoding context must fully know the encoded data types. \n\nParity's libraries utilize the [`parity-scale-codec`](https://github.com/paritytech/parity-scale-codec){target=\\_blank} crate (a Rust implementation of the SCALE codec) to handle encoding and decoding for interactions between RPCs and the runtime.\n\nThe `codec` mechanism is ideal for Polkadot SDK-based chains because:\n\n- It is lightweight compared to generic serialization frameworks like [`serde`](https://serde.rs/){target=\\_blank}, which add unnecessary bulk to binaries.\n- It doesn’t rely on Rust’s `libstd`, making it compatible with `no_std` environments like Wasm runtime.\n- It integrates seamlessly with Rust, allowing easy derivation of encoding and decoding logic for new types using `#[derive(Encode, Decode)]`.\n\nDefining a custom encoding scheme in the Polkadot SDK-based chains, rather than using an existing Rust codec library, is crucial for enabling cross-platform and multi-language support."} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 1, "depth": 2, "title": "SCALE Codec", "anchor": "scale-codec", "start_char": 1595, "end_char": 1798, "estimated_token_count": 63, "token_estimator": "heuristic-v1", "text": "## SCALE Codec\n\nThe codec is implemented using the following traits:\n\n- [`Encode`](#encode)\n- [`Decode`](#decode)\n- [`CompactAs`](#compactas)\n- [`HasCompact`](#hascompact)\n- [`EncodeLike`](#encodelike)"} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 2, "depth": 3, "title": "Encode", "anchor": "encode", "start_char": 1798, "end_char": 2875, "estimated_token_count": 291, "token_estimator": "heuristic-v1", "text": "### Encode\n\nThe [`Encode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Encode.html){target=\\_blank} trait handles data encoding into SCALE format and includes the following key functions:\n\n- **`size_hint(&self) -> usize`**: Estimates the number of bytes required for encoding to prevent multiple memory allocations. This should be inexpensive and avoid complex operations. Optional if the size isn’t known.\n- **`encode_to(&self, dest: &mut T)`**: Encodes the data, appending it to a destination buffer.\n- **`encode(&self) -> Vec`**: Encodes the data and returns it as a byte vector.\n- **`using_encoded R>(&self, f: F) -> R`**: Encodes the data and passes it to a closure, returning the result.\n- **`encoded_size(&self) -> usize`**: Calculates the encoded size. Should be used when the encoded data isn’t required.\n\n!!!tip\n For best performance, value types should override `using_encoded`, and allocating types should override `encode_to`. It's recommended to implement `size_hint` for all types where possible."} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 3, "depth": 3, "title": "Decode", "anchor": "decode", "start_char": 2875, "end_char": 3216, "estimated_token_count": 98, "token_estimator": "heuristic-v1", "text": "### Decode\n\nThe [`Decode`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.Decode.html){target=\\_blank} trait handles decoding SCALE-encoded data back into the appropriate types:\n\n- **`fn decode(value: &mut I) -> Result`**: Decodes data from the SCALE format, returning an error if decoding fails."} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 4, "depth": 3, "title": "CompactAs", "anchor": "compactas", "start_char": 3216, "end_char": 3566, "estimated_token_count": 109, "token_estimator": "heuristic-v1", "text": "### CompactAs\n\nThe [`CompactAs`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.CompactAs.html){target=\\_blank} trait wraps custom types for compact encoding:\n\n- **`encode_as(&self) -> &Self::As`**: Encodes the type as a compact type.\n- **`decode_from(_: Self::As) -> Result`**: decodes from a compact encoded type."} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 5, "depth": 3, "title": "HasCompact", "anchor": "hascompact", "start_char": 3566, "end_char": 3752, "estimated_token_count": 49, "token_estimator": "heuristic-v1", "text": "### HasCompact\n\nThe [`HasCompact`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.HasCompact.html){target=\\_blank} trait indicates a type supports compact encoding."} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 6, "depth": 3, "title": "EncodeLike", "anchor": "encodelike", "start_char": 3752, "end_char": 4038, "estimated_token_count": 69, "token_estimator": "heuristic-v1", "text": "### EncodeLike\n\nThe [`EncodeLike`](https://docs.rs/parity-scale-codec/latest/parity_scale_codec/trait.EncodeLike.html){target=\\_blank} trait is used to ensure multiple types that encode similarly are accepted by the same function. When using `derive`, it is automatically implemented."} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 7, "depth": 3, "title": "Data Types", "anchor": "data-types", "start_char": 4038, "end_char": 11053, "estimated_token_count": 1201, "token_estimator": "heuristic-v1", "text": "### Data Types\n\nThe table below outlines how the Rust implementation of the Parity SCALE codec encodes different data types.\n\n| Type | Description | Example SCALE Decoded Value | SCALE Encoded Value |\n|-------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|\n| Boolean | Boolean values are encoded using the least significant bit of a single byte. | `false` / `true` | `0x00` / `0x01` |\n| Compact/general integers | A \"compact\" or general integer encoding is sufficient for encoding large integers (up to 2^536) and is more efficient at encoding most values than the fixed-width version. | `unsigned integer 0` / `unsigned integer 1` / `unsigned integer 42` / `unsigned integer 69` / `unsigned integer 65535` / `BigInt(100000000000000)` | `0x00` / `0x04` / `0xa8` / `0x1501` / `0xfeff0300` / `0x0b00407a10f35a` |\n| Enumerations (tagged-unions) | A fixed number of variants, each mutually exclusive and potentially implying a further value or series of values. Encoded as the first byte identifying the index of the variant that the value is. Any further bytes are used to encode any data that the variant implies. Thus, no more than 256 variants are supported. | `Int(42)` and `Bool(true)` where `enum IntOrBool { Int(u8), Bool(bool) }` | `0x002a` and `0x0101` |\n| Fixed-width integers | Basic integers are encoded using a fixed-width little-endian (LE) format. | `signed 8-bit integer 69` / `unsigned 16-bit integer 42` / `unsigned 32-bit integer 16777215` | `0x45` / `0x2a00` / `0xffffff00` |\n| Options | One or zero values of a particular type. | `Some` / `None` | `0x01` followed by the encoded value / `0x00` |\n| Results | Results are commonly used enumerations which indicate whether certain operations were successful or unsuccessful. | `Ok(42)` / `Err(false)` | `0x002a` / `0x0100` |\n| Strings | Strings are Vectors of bytes (Vec) containing a valid UTF8 sequence. | | |\n| Structs | For structures, the values are named, but that is irrelevant for the encoding (names are ignored - only order matters). | `SortedVecAsc::from([3, 5, 2, 8])` | `[3, 2, 5, 8] ` |\n| Tuples | A fixed-size series of values, each with a possibly different but predetermined and fixed type. This is simply the concatenation of each encoded value. | Tuple of compact unsigned integer and boolean: `(3, false)` | `0x0c00` |\n| Vectors (lists, series, sets) | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. | Vector of unsigned `16`-bit integers: `[4, 8, 15, 16, 23, 42]` | `0x18040008000f00100017002a00` |"} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 8, "depth": 2, "title": "Encode and Decode Rust Trait Implementations", "anchor": "encode-and-decode-rust-trait-implementations", "start_char": 11053, "end_char": 12105, "estimated_token_count": 444, "token_estimator": "heuristic-v1", "text": "## Encode and Decode Rust Trait Implementations\n\nHere's how the `Encode` and `Decode` traits are implemented:\n\n\n```rust\nuse parity_scale_codec::{Encode, Decode};\n\n[derive(Debug, PartialEq, Encode, Decode)]\nenum EnumType {\n #[codec(index = 15)]\n A,\n B(u32, u64),\n C {\n a: u32,\n b: u64,\n },\n}\n\nlet a = EnumType::A;\nlet b = EnumType::B(1, 2);\nlet c = EnumType::C { a: 1, b: 2 };\n\na.using_encoded(|ref slice| {\n assert_eq!(slice, &b\"\\x0f\");\n});\n\nb.using_encoded(|ref slice| {\n assert_eq!(slice, &b\"\\x01\\x01\\0\\0\\0\\x02\\0\\0\\0\\0\\0\\0\\0\");\n});\n\nc.using_encoded(|ref slice| {\n assert_eq!(slice, &b\"\\x02\\x01\\0\\0\\0\\x02\\0\\0\\0\\0\\0\\0\\0\");\n});\n\nlet mut da: &[u8] = b\"\\x0f\";\nassert_eq!(EnumType::decode(&mut da).ok(), Some(a));\n\nlet mut db: &[u8] = b\"\\x01\\x01\\0\\0\\0\\x02\\0\\0\\0\\0\\0\\0\\0\";\nassert_eq!(EnumType::decode(&mut db).ok(), Some(b));\n\nlet mut dc: &[u8] = b\"\\x02\\x01\\0\\0\\0\\x02\\0\\0\\0\\0\\0\\0\\0\";\nassert_eq!(EnumType::decode(&mut dc).ok(), Some(c));\n\nlet mut dz: &[u8] = &[0];\nassert_eq!(EnumType::decode(&mut dz).ok(), None);\n```"} -{"page_id": "reference-parachains-data-encoding", "page_title": "Data Encoding", "index": 9, "depth": 2, "title": "SCALE Codec Libraries", "anchor": "scale-codec-libraries", "start_char": 12105, "end_char": 13629, "estimated_token_count": 557, "token_estimator": "heuristic-v1", "text": "## SCALE Codec Libraries\n\nSeveral SCALE codec implementations are available in various languages. Here's a list of them:\n\n- **AssemblyScript**: [`LimeChain/as-scale-codec`](https://github.com/LimeChain/as-scale-codec){target=\\_blank}\n- **C**: [`MatthewDarnell/cScale`](https://github.com/MatthewDarnell/cScale){target=\\_blank}\n- **C++**: [`qdrvm/scale-codec-cpp`](https://github.com/qdrvm/scale-codec-cpp){target=\\_blank}\n- **JavaScript**: [`polkadot-js/api`](https://github.com/polkadot-js/api){target=\\_blank}\n- **Dart**: [`leonardocustodio/polkadart`](https://github.com/leonardocustodio/polkadart){target=\\_blank}\n- **Haskell**: [`airalab/hs-web3`](https://github.com/airalab/hs-web3/tree/master/packages/scale){target=\\_blank}\n- **Golang**: [`itering/scale.go`](https://github.com/itering/scale.go){target=\\_blank}\n- **Java**: [`splix/polkaj`](https://github.com/splix/polkaj){target=\\_blank}\n- **Python**: [`polkascan/py-scale-codec`](https://github.com/polkascan/py-scale-codec){target=\\_blank}\n- **Ruby**: [` wuminzhe/scale_rb`](https://github.com/wuminzhe/scale_rb){target=\\_blank}\n- **TypeScript**: [`parity-scale-codec-ts`](https://github.com/tjjfvi/subshape){target=\\_blank}, [`scale-ts`](https://github.com/unstoppablejs/unstoppablejs/tree/main/packages/scale-ts#scale-ts){target=\\_blank}, [`soramitsu/scale-codec-js-library`](https://github.com/soramitsu/scale-codec-js-library){target=\\_blank}, [`subsquid/scale-codec`](https://github.com/subsquid/squid-sdk/tree/master/substrate/scale-codec){target=\\_blank}"} -{"page_id": "reference-parachains-interoperability", "page_title": "Interoperability", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 20, "end_char": 607, "estimated_token_count": 91, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nInteroperability lies at the heart of the Polkadot ecosystem, enabling communication and collaboration across a diverse range of blockchains. By bridging the gaps between parachains, relay chains, and even external networks, Polkadot unlocks the potential for truly decentralized applications, efficient resource sharing, and scalable solutions.\n\nPolkadot’s design ensures that blockchains can transcend their individual limitations by working together as part of a unified system. This cooperative architecture is what sets Polkadot apart in the blockchain landscape."} -{"page_id": "reference-parachains-interoperability", "page_title": "Interoperability", "index": 1, "depth": 2, "title": "Why Interoperability Matters", "anchor": "why-interoperability-matters", "start_char": 607, "end_char": 1641, "estimated_token_count": 169, "token_estimator": "heuristic-v1", "text": "## Why Interoperability Matters\n\nThe blockchain ecosystem is inherently fragmented. Different blockchains excel in specialized domains such as finance, gaming, or supply chain management, but these chains function in isolation without interoperability. This lack of connectivity stifles the broader utility of blockchain technology.\n\nInteroperability solves this problem by enabling blockchains to:\n\n- **Collaborate across networks**: Chains can interact to share assets, functionality, and data, creating synergies that amplify their individual strengths.\n- **Achieve greater scalability**: Specialized chains can offload tasks to others, optimizing performance and resource utilization.\n- **Expand use-case potential**: Cross-chain applications can leverage features from multiple blockchains, unlocking novel user experiences and solutions.\n\nIn the Polkadot ecosystem, interoperability transforms a collection of isolated chains into a cohesive, efficient network, pushing the boundaries of what blockchains can achieve together."} -{"page_id": "reference-parachains-interoperability", "page_title": "Interoperability", "index": 2, "depth": 2, "title": "Key Mechanisms for Interoperability", "anchor": "key-mechanisms-for-interoperability", "start_char": 1641, "end_char": 1921, "estimated_token_count": 45, "token_estimator": "heuristic-v1", "text": "## Key Mechanisms for Interoperability\n\nAt the core of Polkadot's cross-chain collaboration are foundational technologies designed to break down barriers between networks. These mechanisms empower blockchains to communicate, share resources, and operate as a cohesive ecosystem."} -{"page_id": "reference-parachains-interoperability", "page_title": "Interoperability", "index": 3, "depth": 3, "title": "Cross-Consensus Messaging (XCM): The Backbone of Communication", "anchor": "cross-consensus-messaging-xcm-the-backbone-of-communication", "start_char": 1921, "end_char": 2749, "estimated_token_count": 150, "token_estimator": "heuristic-v1", "text": "### Cross-Consensus Messaging (XCM): The Backbone of Communication\n\nPolkadot's Cross-Consensus Messaging (XCM) is the standard framework for interaction between parachains, relay chains, and, eventually, external blockchains. XCM provides a trustless, secure messaging format for exchanging assets, sharing data, and executing cross-chain operations.\n\nThrough XCM, decentralized applications can:\n\n- Transfer tokens and other assets across chains.\n- Coordinate complex workflows that span multiple blockchains.\n- Enable seamless user experiences where underlying blockchain differences are invisible.\n- XCM exemplifies Polkadot’s commitment to creating a robust and interoperable ecosystem.\n\nFor further information about XCM, check the [Introduction to XCM](/parachains/interoperability/get-started/){target=\\_blank} article."} -{"page_id": "reference-parachains-interoperability", "page_title": "Interoperability", "index": 4, "depth": 3, "title": "Bridges: Connecting External Networks", "anchor": "bridges-connecting-external-networks", "start_char": 2749, "end_char": 3529, "estimated_token_count": 138, "token_estimator": "heuristic-v1", "text": "### Bridges: Connecting External Networks\n\nWhile XCM enables interoperability within the Polkadot ecosystem, bridges extend this functionality to external blockchains such as Ethereum and Bitcoin. By connecting these networks, bridges allow Polkadot-based chains to access external liquidity, additional functionalities, and broader user bases.\n\nWith bridges, developers and users gain the ability to:\n\n- Integrate external assets into Polkadot-based applications.\n- Combine the strengths of Polkadot’s scalability with the liquidity of other networks.\n- Facilitate accurate multi-chain applications that transcend ecosystem boundaries.\n\nFor more information about bridges in the Polkadot ecosystem, see the [Bridge Hub](/reference/polkadot-hub/bridging/){target=\\_blank} guide."} -{"page_id": "reference-parachains-interoperability", "page_title": "Interoperability", "index": 5, "depth": 2, "title": "The Polkadot Advantage", "anchor": "the-polkadot-advantage", "start_char": 3529, "end_char": 4247, "estimated_token_count": 121, "token_estimator": "heuristic-v1", "text": "## The Polkadot Advantage\n\nPolkadot was purpose-built for interoperability. Unlike networks that add interoperability as an afterthought, Polkadot integrates it as a fundamental design principle. This approach offers several distinct advantages:\n\n- **Developer empowerment**: Polkadot’s interoperability tools allow developers to build applications that leverage multiple chains’ capabilities without added complexity.\n- **Enhanced ecosystem collaboration**: Chains in Polkadot can focus on their unique strengths while contributing to the ecosystem’s overall growth.\n- **Future-proofing blockchain**: By enabling seamless communication, Polkadot ensures its ecosystem can adapt to evolving demands and technologies."} -{"page_id": "reference-parachains-interoperability", "page_title": "Interoperability", "index": 6, "depth": 2, "title": "Looking Ahead", "anchor": "looking-ahead", "start_char": 4247, "end_char": 4635, "estimated_token_count": 58, "token_estimator": "heuristic-v1", "text": "## Looking Ahead\n\nPolkadot’s vision of interoperability extends beyond technical functionality, representing a shift towards a more collaborative blockchain landscape. By enabling chains to work together, Polkadot fosters innovation, efficiency, and accessibility, paving the way for a decentralized future where blockchains are not isolated competitors but interconnected collaborators."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 12, "end_char": 601, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe Polkadot ecosystem is built on a robust set of networks designed to enable secure and scalable development. Whether you are testing new features or deploying to live production, Polkadot offers several layers of networks tailored for each stage of the development process. From local environments to experimental networks like Kusama and community-run TestNets such as Paseo, developers can thoroughly test, iterate, and validate their applications. This guide will introduce you to Polkadot's various networks and explain how they fit into the development workflow."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 1, "depth": 2, "title": "Network Overview", "anchor": "network-overview", "start_char": 601, "end_char": 3131, "estimated_token_count": 484, "token_estimator": "heuristic-v1", "text": "## Network Overview \n\nPolkadot's development process is structured to ensure new features and upgrades are rigorously tested before being deployed on live production networks. The progression follows a well-defined path, starting from local environments and advancing through TestNets, ultimately reaching the Polkadot MainNet. The diagram below outlines the typical progression of the Polkadot development cycle:\n\n``` mermaid\nflowchart LR\n id1[Local] --> id2[Westend] --> id4[Kusama] --> id5[Polkadot] \n id1[Local] --> id3[Paseo] --> id5[Polkadot] \n```\n\nThis flow ensures developers can thoroughly test and iterate without risking real tokens or affecting production networks. Testing tools like [Chopsticks](#chopsticks) and various TestNets make it easier to experiment safely before releasing to production.\n\nA typical journey through the Polkadot core protocol development process might look like this:\n\n1. **Local development node**: Development starts in a local environment, where developers can create, test, and iterate on upgrades or new features using a local development node. This stage allows rapid experimentation in an isolated setup without any external dependencies.\n\n2. **Westend**: After testing locally, upgrades are deployed to [Westend](#westend), Polkadot's primary TestNet. Westend simulates real-world conditions without using real tokens, making it the ideal place for rigorous feature testing before moving on to production networks.\n\n3. **Kusama**: Once features have passed extensive testing on Westend, they move to Kusama, Polkadot's experimental and fast-moving \"canary\" network. Kusama operates as a high-fidelity testing ground with actual economic incentives, giving developers insights into how their features will perform in a real-world environment.\n\n4. **Polkadot**: After passing tests on Westend and Kusama, features are considered ready for deployment to Polkadot, the live production network.\n\n In addition, parachain developers can leverage local TestNets like [Zombienet](#zombienet) and deploy upgrades on parachain TestNets.\n\n5. **Paseo**: For parachain and dApp developers, Paseo serves as a community-run TestNet that mirrors Polkadot's runtime. Like Westend for core protocol development, Paseo provides a testing ground for parachain development without affecting live networks.\n\n!!!note\n The Rococo TestNet deprecation date was October 14, 2024. Teams should use Westend for Polkadot protocol and feature testing and Paseo for chain development-related testing."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 2, "depth": 2, "title": "Polkadot Development Networks", "anchor": "polkadot-development-networks", "start_char": 3131, "end_char": 3663, "estimated_token_count": 83, "token_estimator": "heuristic-v1", "text": "## Polkadot Development Networks\n\nDevelopment and testing are crucial to building robust dApps and parachains and performing network upgrades within the Polkadot ecosystem. To achieve this, developers can leverage various networks and tools that provide a risk-free environment for experimentation and validation before deploying features to live networks. These networks help avoid the costs and risks associated with real tokens, enabling testing for functionalities like governance, cross-chain messaging, and runtime upgrades."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 3, "depth": 2, "title": "Kusama Network", "anchor": "kusama-network", "start_char": 3663, "end_char": 4268, "estimated_token_count": 122, "token_estimator": "heuristic-v1", "text": "## Kusama Network\n\nKusama is the experimental version of Polkadot, designed for developers who want to move quickly and test their applications in a real-world environment with economic incentives. Kusama serves as a production-grade testing ground where developers can deploy features and upgrades with the pressure of game theory and economics in mind. It mirrors Polkadot but operates as a more flexible space for innovation.\n\nThe native token for Kusama is KSM. For more information about KSM, visit the [Native Assets](https://wiki.polkadot.com/kusama/kusama-getting-started/){target=\\_blank} page."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 4, "depth": 2, "title": "Test Networks", "anchor": "test-networks", "start_char": 4268, "end_char": 4488, "estimated_token_count": 47, "token_estimator": "heuristic-v1", "text": "## Test Networks\n\nThe following test networks provide controlled environments for testing upgrades and new features. TestNet tokens are available from the [Polkadot faucet](https://faucet.polkadot.io/){target=\\_blank}."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 5, "depth": 3, "title": "Westend", "anchor": "westend", "start_char": 4488, "end_char": 5009, "estimated_token_count": 110, "token_estimator": "heuristic-v1", "text": "### Westend\n\nWestend is Polkadot's primary permanent TestNet. Unlike temporary test networks, Westend is not reset to the genesis block, making it an ongoing environment for testing Polkadot core features. Managed by Parity Technologies, Westend ensures that developers can test features in a real-world simulation without using actual tokens.\n\nThe native token for Westend is WND. More details about WND can be found on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_2){target=\\_blank} page."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 6, "depth": 3, "title": "Paseo", "anchor": "paseo", "start_char": 5009, "end_char": 5579, "estimated_token_count": 127, "token_estimator": "heuristic-v1", "text": "### Paseo\n\n[Paseo](https://github.com/paseo-network){target=\\_blank} is a community-managed TestNet designed for parachain and dApp developers. It mirrors Polkadot's runtime and is maintained by Polkadot community members. Paseo provides a dedicated space for parachain developers to test their applications in a Polkadot-like environment without the risks associated with live networks.\n\nThe native token for Paseo is PAS. Additional information on PAS is available on the [Native Assets](https://wiki.polkadot.com/learn/learn-dot/#__tabbed_2_1){target=\\_blank} page."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 7, "depth": 2, "title": "Local Test Networks", "anchor": "local-test-networks", "start_char": 5579, "end_char": 6057, "estimated_token_count": 80, "token_estimator": "heuristic-v1", "text": "## Local Test Networks\n\nLocal test networks are an essential part of the development cycle for blockchain developers using the Polkadot SDK. They allow for fast, iterative testing in controlled, private environments without connecting to public TestNets. Developers can quickly spin up local instances to experiment, debug, and validate their code before deploying to larger TestNets like Westend or Paseo. Two key tools for local network testing are Zombienet and Chopsticks."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 8, "depth": 3, "title": "Zombienet", "anchor": "zombienet", "start_char": 6057, "end_char": 6981, "estimated_token_count": 164, "token_estimator": "heuristic-v1", "text": "### Zombienet\n\n[Zombienet](https://github.com/paritytech/zombienet){target=\\_blank} is a flexible testing framework for Polkadot SDK-based blockchains. It enables developers to create and manage ephemeral, short-lived networks. This feature makes Zombienet particularly useful for quick iterations, as it allows you to run multiple local networks concurrently, mimicking different runtime conditions. Whether you're developing a parachain or testing your custom blockchain logic, Zombienet gives you the tools to automate local testing.\n\nKey features of Zombienet include:\n\n- Creating dynamic, local networks with different configurations.\n- Running parachains and relay chains in a simulated environment.\n- Efficient testing of network components like cross-chain messaging and governance.\n\nZombienet is ideal for developers looking to test quickly and thoroughly before moving to more resource-intensive public TestNets."} -{"page_id": "reference-parachains-networks", "page_title": "Networks", "index": 9, "depth": 3, "title": "Chopsticks", "anchor": "chopsticks", "start_char": 6981, "end_char": 7834, "estimated_token_count": 157, "token_estimator": "heuristic-v1", "text": "### Chopsticks\n\n[Chopsticks](https://github.com/AcalaNetwork/chopsticks){target=\\_blank} is a tool designed to create forks of Polkadot SDK-based blockchains, allowing developers to interact with network forks as part of their testing process. This capability makes Chopsticks a powerful option for testing upgrades, runtime changes, or cross-chain applications in a forked network environment.\n\nKey features of Chopsticks include:\n\n- Forking live Polkadot SDK-based blockchains for isolated testing.\n- Simulating cross-chain messages in a private, controlled setup.\n- Debugging network behavior by interacting with the fork in real-time.\n\nChopsticks provides a controlled environment for developers to safely explore the effects of runtime changes. It ensures that network behavior is tested and verified before upgrades are deployed to live networks."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 20, "end_char": 1003, "estimated_token_count": 184, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nEvery blockchain platform relies on a decentralized network of computers, called nodes, that communicate with each other about transactions and blocks. In this context, a node refers to the software running on the connected devices rather than the physical or virtual machines in the network.\n\nPolkadot SDK-based nodes consist of two main components, each with distinct responsibilities: the client (also called node) and the runtime.\n\nIf the system were a monolithic protocol, any modification would require updating the entire system. Instead, Polkadot achieves true upgradeability by defining an immutable meta-protocol (the client) and a protocol (the runtime) that can be upgraded independently.\n\nThis separation gives the [Polkadot Relay Chain](/polkadot-protocol/architecture/polkadot-chain){target=\\_blank} and all connected [parachains](/polkadot-protocol/architecture/parachains){target=\\_blank} an evolutionary advantage over other blockchain platforms."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 1, "depth": 2, "title": "Architectural Principles", "anchor": "architectural-principles", "start_char": 1003, "end_char": 1725, "estimated_token_count": 123, "token_estimator": "heuristic-v1", "text": "## Architectural Principles\n\nThe Polkadot SDK-based blockchain architecture is fundamentally built on two distinct yet interconnected components:\n\n- Client (Meta-protocol):\n - Handles the foundational infrastructure of the blockchain.\n - Manages runtime execution, networking, consensus, and other off-chain components.\n - Provides an immutable base layer that ensures network stability.\n - Upgradable only through hard forks.\n\n- Runtime (Protocol):\n - Defines the blockchain's state transition logic.\n - Determines the specific rules and behaviors of the blockchain.\n - Compiled to WebAssembly (Wasm) for platform-independent execution.\n - Capable of being upgraded without network-wide forking."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 2, "depth": 3, "title": "Advantages of this Architecture", "anchor": "advantages-of-this-architecture", "start_char": 1725, "end_char": 2106, "estimated_token_count": 75, "token_estimator": "heuristic-v1", "text": "### Advantages of this Architecture\n\n- **Forkless upgrades**: Runtime can be updated without disrupting the entire network.\n- **Modularity**: Clear separation allows independent development of client and runtime.\n- **Flexibility**: Enables rapid iteration and evolution of blockchain logic.\n- **Performance**: WebAssembly compilation provides efficient, cross-platform execution."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 3, "depth": 2, "title": "Node (Client)", "anchor": "node-client", "start_char": 2106, "end_char": 2939, "estimated_token_count": 164, "token_estimator": "heuristic-v1", "text": "## Node (Client)\n\nThe node, also known as the client, is the core component responsible for executing the Wasm runtime and orchestrating various essential blockchain components. It ensures the correct execution of the state transition function and manages multiple critical subsystems, including:\n\n- **Wasm execution**: Runs the blockchain runtime, which defines the state transition rules.\n- **Database management**: Stores blockchain data.\n- **Networking**: Facilitates peer-to-peer communication, block propagation, and transaction gossiping.\n- **Transaction pool (Mempool)**: Manages pending transactions before they are included in a block.\n- **Consensus mechanism**: Ensures agreement on the blockchain state across nodes.\n- **RPC services**: Provides external interfaces for applications and users to interact with the node."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 4, "depth": 2, "title": "Runtime", "anchor": "runtime", "start_char": 2939, "end_char": 3221, "estimated_token_count": 56, "token_estimator": "heuristic-v1", "text": "## Runtime\n\nThe runtime is more than just a set of rules. It's the fundamental logic engine that defines a blockchain's entire behavior. In Polkadot SDK-based blockchains, the runtime represents a complete, self-contained description of the blockchain's state transition function."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 5, "depth": 3, "title": "Characteristics", "anchor": "characteristics", "start_char": 3221, "end_char": 3555, "estimated_token_count": 68, "token_estimator": "heuristic-v1", "text": "### Characteristics\n\nThe runtime is distinguished by three key characteristics:\n\n- **Business logic**: Defines the complete application-specific blockchain behavior.\n- **WebAssembly compilation**: Ensures platform-independent, secure execution.\n- **On-chain storage**: Stored within the blockchain's state, allowing dynamic updates."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 6, "depth": 3, "title": "Key Functions", "anchor": "key-functions", "start_char": 3555, "end_char": 3840, "estimated_token_count": 50, "token_estimator": "heuristic-v1", "text": "### Key Functions\n\nThe runtime performs several critical functions, such as:\n\n- Define state transition rules.\n- Implement blockchain-specific logic.\n- Manage account interactions.\n- Control transaction processing.\n- Define governance mechanisms.\n- Handle custom pallets and modules."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 7, "depth": 2, "title": "Communication Between Node and Runtime", "anchor": "communication-between-node-and-runtime", "start_char": 3840, "end_char": 4112, "estimated_token_count": 53, "token_estimator": "heuristic-v1", "text": "## Communication Between Node and Runtime\n\nThe client and runtime communicate exclusively using [SCALE-encoded](/polkadot-protocol/parachain-basics/data-encoding){target=\\_blank} communication. This ensures efficient and compact data exchange between the two components."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 8, "depth": 3, "title": "Runtime APIs", "anchor": "runtime-apis", "start_char": 4112, "end_char": 4537, "estimated_token_count": 76, "token_estimator": "heuristic-v1", "text": "### Runtime APIs\n\nThe Runtime API consists of well-defined functions and constants a client assumes are implemented in the Runtime Wasm blob. These APIs enable the client to interact with the runtime to execute blockchain operations and retrieve information. The client invokes these APIs to:\n\n- Build, execute, and finalize blocks.\n- Access metadata.\n- Access consensus related information.\n- Handle transaction execution."} -{"page_id": "reference-parachains-node-and-runtime", "page_title": "Node and Runtime", "index": 9, "depth": 3, "title": "Host Functions", "anchor": "host-functions", "start_char": 4537, "end_char": 4937, "estimated_token_count": 65, "token_estimator": "heuristic-v1", "text": "### Host Functions\n\nDuring execution, the runtime can access certain external client functionalities via host functions. The specific functions the client exposes allow the runtime to perform operations outside the WebAssembly domain. Host functions enable the runtime to:\n\n- Perform cryptographic operations.\n- Access the current blockchain state.\n- Handle storage modifications.\n- Allocate memory."} -{"page_id": "reference-parachains-randomness", "page_title": "Randomness", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 14, "end_char": 1254, "estimated_token_count": 285, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nRandomness is crucial in Proof of Stake (PoS) blockchains to ensure a fair and unpredictable distribution of validator duties. However, computers are inherently deterministic, meaning the same input always produces the same output. What we typically refer to as \"random\" numbers on a computer are actually pseudo-random. These numbers rely on an initial \"seed,\" which can come from external sources like [atmospheric noise](https://www.random.org/randomness/){target=\\_blank}, [heart rates](https://mdpi.altmetric.com/details/47574324){target=\\_blank}, or even [lava lamps](https://en.wikipedia.org/wiki/Lavarand){target=\\_blank}. While this may seem random, given the same \"seed,\" the same sequence of numbers will always be generated.\n\nIn a global blockchain network, relying on real-world entropy for randomness isn’t feasible because these inputs vary by time and location. If nodes use different inputs, blockchains can fork. Hence, real-world randomness isn't suitable for use as a seed in blockchain systems.\n\nCurrently, two primary methods for generating randomness in blockchains are used: [`RANDAO`](#randao) and [`VRF`](#vrf) (Verifiable Random Function). Polkadot adopts the `VRF` approach for its randomness."} -{"page_id": "reference-parachains-randomness", "page_title": "Randomness", "index": 1, "depth": 2, "title": "VRF", "anchor": "vrf", "start_char": 1254, "end_char": 2042, "estimated_token_count": 183, "token_estimator": "heuristic-v1", "text": "## VRF\n\nA Verifiable Random Function (VRF) is a cryptographic function that generates a random number and proof that ensures the submitter produced the number. This proof allows anyone to verify the validity of the random number.\n\nPolkadot's VRF is similar to the one used in [**Ouroboros Praos**](https://eprint.iacr.org/2017/573.pdf){target=\\_blank}, which secures randomness for block production in systems like [BABE](/reference/polkadot-hub/consensus-and-security/pos-consensus/#block-production-babe){target=\\_blank} (Polkadot’s block production mechanism). \n\nThe key difference is that Polkadot's VRF doesn’t rely on a central clock—avoiding the issue of whose clock to trust. Instead, it uses its own past results and slot numbers to simulate time and determine future outcomes."} -{"page_id": "reference-parachains-randomness", "page_title": "Randomness", "index": 2, "depth": 3, "title": "How VRF Works", "anchor": "how-vrf-works", "start_char": 2042, "end_char": 4579, "estimated_token_count": 537, "token_estimator": "heuristic-v1", "text": "### How VRF Works\n\nSlots on Polkadot are discrete units of time, each lasting six seconds, and can potentially hold a block. Multiple slots form an epoch, with 2400 slots making up one four-hour epoch.\n\nIn each slot, validators execute a \"die roll\" using a VRF. The VRF uses three inputs:\n\n1. A \"secret key,\" unique to each validator, is used for the die roll.\n2. An epoch randomness value, derived from the hash of VRF outputs from blocks two epochs ago (N-2), so past randomness influences the current epoch (N).\n3. The current slot number.\n\nThis process helps maintain fair randomness across the network.\n\nHere is a graphical representation:\n\n![](/images/reference/parachains/randomness/randomness-01.webp)\n\nThe VRF produces two outputs: a result (the random number) and a proof (verifying that the number was generated correctly).\n\nThe result is checked by the validator against a protocol threshold. If it's below the threshold, the validator becomes a candidate for block production in that slot. \n\nThe validator then attempts to create a block, submitting it along with the `PROOF` and `RESULT`.\n\nSo, VRF can be expressed like:\n\n`(RESULT, PROOF) = VRF(SECRET, EPOCH_RANDOMNESS_VALUE, CURRENT_SLOT_NUMBER)`\n\nPut simply, performing a \"VRF roll\" generates a random number along with proof that the number was genuinely produced and not arbitrarily chosen.\n\nAfter executing the VRF, the `RESULT` is compared to a protocol-defined `THRESHOLD`. If the `RESULT` is below the `THRESHOLD`, the validator becomes a valid candidate to propose a block for that slot. Otherwise, the validator skips the slot.\n\nAs a result, there may be multiple validators eligible to propose a block for a slot. In this case, the block accepted by other nodes will prevail, provided it is on the chain with the latest finalized block as determined by the GRANDPA finality gadget. It's also possible for no block producers to be available for a slot, in which case the AURA consensus takes over. AURA is a fallback mechanism that randomly selects a validator to produce a block, running in parallel with BABE and only stepping in when no block producers exist for a slot. Otherwise, it remains inactive.\n\nBecause validators roll independently, no block candidates may appear in some slots if all roll numbers are above the threshold. \n\nTo verify resolution of this issue and that Polkadot block times remain near constant-time, see the [PoS Consensus](/reference/polkadot-hub/consensus-and-security/pos-consensus/){target=\\_blank} page of this documentation."} -{"page_id": "reference-parachains-randomness", "page_title": "Randomness", "index": 3, "depth": 2, "title": "RANDAO", "anchor": "randao", "start_char": 4579, "end_char": 5266, "estimated_token_count": 134, "token_estimator": "heuristic-v1", "text": "## RANDAO\n\nAn alternative on-chain randomness method is Ethereum's RANDAO, where validators perform thousands of hashes on a seed and publish the final hash during a round. The collective input from all validators forms the random number, and as long as one honest validator participates, the randomness is secure.\n\nTo enhance security, RANDAO can optionally be combined with a Verifiable Delay Function (VDF), ensuring that randomness can't be predicted or manipulated during computation.\n\nFor more information about RANDAO, see the [Randomness - RANDAO](https://eth2book.info/capella/part2/building_blocks/randomness/){target=\\_blank} section of the Upgrading Ethereum documentation."} -{"page_id": "reference-parachains-randomness", "page_title": "Randomness", "index": 4, "depth": 2, "title": "VDFs", "anchor": "vdfs", "start_char": 5266, "end_char": 5943, "estimated_token_count": 125, "token_estimator": "heuristic-v1", "text": "## VDFs\n\nVerifiable Delay Functions (VDFs) are time-bound computations that, even on parallel computers, take a set amount of time to complete. \n\nThey produce a unique result that can be quickly verified publicly. When combined with RANDAO, feeding RANDAO's output into a VDF introduces a delay that nullifies an attacker's chance to influence the randomness.\n\nHowever, VDF likely requires specialized ASIC devices to run separately from standard nodes.\n\n!!!warning \n While only one is needed to secure the system, and they will be open-source and inexpensive, running VDF devices involves significant costs without direct incentives, adding friction for blockchain users."} -{"page_id": "reference-parachains-randomness", "page_title": "Randomness", "index": 5, "depth": 2, "title": "Additional Resources", "anchor": "additional-resources", "start_char": 5943, "end_char": 6503, "estimated_token_count": 124, "token_estimator": "heuristic-v1", "text": "## Additional Resources\n\nFor more information about the reasoning for choices made along with proofs, see Polkadot's research on blockchain randomness and sortition in the [Block production](https://research.web3.foundation/Polkadot/protocols/block-production){target=\\_blank} entry of the Polkadot Wiki. \n\nFor a discussion with Web3 Foundation researchers about when and under what conditions Polkadot's randomness can be utilized, see the [Discussion on Randomness used in Polkadot](https://github.com/use-ink/ink/issues/57){target=\\_blank} issue on GitHub."} -{"page_id": "reference-parachains", "page_title": "Parachains Overview", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 23, "end_char": 1338, "estimated_token_count": 235, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nA parachain is a specialized blockchain that connects to the Polkadot relay chain, benefiting from shared security, interoperability, and scalability. Parachains are built using the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}, a powerful toolkit written in Rust that provides everything needed to create custom blockchain logic while integrating seamlessly with the Polkadot network.\n\nUnlike standalone blockchains that must bootstrap their own validator sets and security, parachains leverage Polkadot's pooled security model. This allows parachain developers to focus on their application-specific functionality rather than consensus and security infrastructure. Parachains can communicate with each other through Cross-Consensus Messaging (XCM), enabling seamless interoperability across the Polkadot ecosystem.\n\nKey capabilities that parachains provide include:\n\n- **Shared security**: Inherit security from Polkadot's validator set without maintaining your own.\n- **Interoperability**: Communicate trustlessly with other parachains via XCM.\n- **Scalability**: Process transactions in parallel with other parachains.\n- **Customization**: Build application-specific logic tailored to your use case.\n- **Upgradeability**: Upgrade runtime logic without hard forks."} -{"page_id": "reference-parachains", "page_title": "Parachains Overview", "index": 1, "depth": 2, "title": "Polkadot SDK: Parachain Architecture", "anchor": "polkadot-sdk-parachain-architecture", "start_char": 1338, "end_char": 2576, "estimated_token_count": 308, "token_estimator": "heuristic-v1", "text": "## Polkadot SDK: Parachain Architecture\n\nBuilding a parachain involves understanding and utilizing several key components of the Polkadot SDK:\n\n![](/images/reference/parachains/index/overview-01.webp)\n\n- **[Substrate](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html){target=\\_blank}**: The foundation providing core blockchain primitives and libraries.\n- **[FRAME](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/frame_runtime/index.html){target=\\_blank}**: A modular framework for building your parachain's runtime logic.\n- **[Cumulus](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/cumulus/index.html){target=\\_blank}**: Essential libraries and pallets that enable parachain functionality.\n- **[XCM (Cross Consensus Messaging)](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/xcm/index.html){target=\\_blank}**: The messaging format for communicating with other parachains and the relay chain.\n- **[Polkadot](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/polkadot/index.html){target=\\_blank}**: The relay chain that provides security and coordination."} -{"page_id": "reference-parachains", "page_title": "Parachains Overview", "index": 2, "depth": 3, "title": "Substrate: The Foundation", "anchor": "substrate-the-foundation", "start_char": 2576, "end_char": 4333, "estimated_token_count": 345, "token_estimator": "heuristic-v1", "text": "### Substrate: The Foundation\n\nSubstrate provides the core infrastructure that every parachain is built upon. It handles the low-level blockchain functionality, allowing you to focus on your application's unique features. Substrate includes implementations for networking, database management, consensus participation, and the execution environment for your runtime.\n\nEvery Polkadot SDK node consists of two main components:\n\n- **Client (Host)**: Handles infrastructure services.\n\n - Native binary that runs on validator and collator nodes.\n - Executes the Wasm-compiled runtime.\n - Manages networking, database, mempool, and block production.\n - Interfaces with the relay chain for validation.\n\n- **Runtime (State Transition Function)**: Contains your business logic.\n\n - Defines how your Polkadot SDK node processes transactions.\n - Compiled to [Wasm](https://webassembly.org/){target=\\_blank} for deterministic execution.\n - Stored on-chain and upgradeable via governance.\n\n```mermaid\n%%{init: {'flowchart': {'padding': 5, 'nodeSpacing': 50, 'rankSpacing': 10}}}%%\ngraph TB\n classDef title font-size:20px,font-weight:bold,stroke-width:0px\n classDef clientStyle font-size:16px,font-weight:bold\n classDef clientSubNodeStyle margin-top:10px\n classDef runtimeCallExecutorStyle padding-top:10px\n\n subgraph sg1[Parachain
    Node]\n direction TB\n\n I[RuntimeCall Executor]\n B[Wasm Runtime - STF]\n\n subgraph sg2[Client]\n direction TB\n C[Network and Blockchain
    Infrastructure Services
    + Relay Chain Interface]\n end\n\n I --> B\n end\n\n class sg1 title\n class sg2 clientStyle\n class C clientSubNodeStyle\n class I runtimeCallExecutorStyle\n\n```"} -{"page_id": "reference-parachains", "page_title": "Parachains Overview", "index": 3, "depth": 3, "title": "FRAME: Building Blocks for Your Runtime", "anchor": "frame-building-blocks-for-your-runtime", "start_char": 4333, "end_char": 6265, "estimated_token_count": 409, "token_estimator": "heuristic-v1", "text": "### FRAME: Building Blocks for Your Runtime\n\nFRAME provides modular components called [pallets](/reference/glossary#pallet){target=\\_blank} that you can compose to build your parachain's runtime. Each pallet provides specific functionality that you can customize and configure for your needs. This modular approach allows you to quickly assemble complex functionality without writing everything from scratch.\n\n```mermaid\ngraph LR\n subgraph SP[\"Parachain Runtime\"]\n direction LR\n Timestamp ~~~ Aura ~~~ ParachainSystem\n Balances ~~~ TransactionPayment ~~~ Sudo\n subgraph Timestamp[\"Timestamp\"]\n SS1[Custom Config]\n end\n subgraph Aura[\"Aura\"]\n SS2[Custom Config]\n end\n subgraph ParachainSystem[\"Parachain System\"]\n SS3[Custom Config]\n end\n subgraph Balances[\"Balances\"]\n SS4[Custom Config]\n end\n subgraph TransactionPayment[\"Transaction Payment\"]\n SS5[Custom Config]\n end\n subgraph Sudo[\"Sudo\"]\n SS6[Custom Config]\n end\n style Timestamp stroke:#FF69B4\n style Aura stroke:#FF69B4\n style ParachainSystem stroke:#FF69B4\n style Balances stroke:#FF69B4\n style TransactionPayment stroke:#FF69B4\n style Sudo stroke:#FF69B4\n style SS1 stroke-dasharray: 5\n style SS2 stroke-dasharray: 5\n style SS3 stroke-dasharray: 5\n style SS4 stroke-dasharray: 5\n style SS5 stroke-dasharray: 5\n style SS6 stroke-dasharray: 5\n\n end\n subgraph AP[\"Available FRAME Pallets\"]\n direction LR\n A1[Aura]~~~A2[Parachain
    System]~~~A3[Transaction
    Payment]~~~A4[Sudo]\n B1[Identity]~~~B2[Balances]~~~B3[Assets]~~~B4[EVM]\n C1[Timestamp]~~~C2[Staking]~~~C3[Contracts]~~~C4[and more...]\n end\n AP --> SP\n```"} -{"page_id": "reference-parachains", "page_title": "Parachains Overview", "index": 4, "depth": 3, "title": "Cumulus: Parachain-Specific Functionality", "anchor": "cumulus-parachain-specific-functionality", "start_char": 6265, "end_char": 6970, "estimated_token_count": 133, "token_estimator": "heuristic-v1", "text": "### Cumulus: Parachain-Specific Functionality\n\nCumulus is what transforms a Polkadot SDK-based runtime into a parachain-capable runtime. It provides the essential components for communicating with the relay chain, participating in Polkadot's consensus, and handling parachain-specific operations like block validation and collation.\n\nKey Cumulus components include:\n\n- **Parachain system pallet**: Core parachain functionality and relay chain communication.\n- **Collator consensus**: Block production logic for parachain collators.\n- **Relay chain interface**: APIs for interacting with the Polkadot relay chain.\n- **Validation data**: Handling proof-of-validity data required by relay chain validators."} -{"page_id": "reference-parachains", "page_title": "Parachains Overview", "index": 5, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 6970, "end_char": 8495, "estimated_token_count": 329, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nBuilding a parachain requires understanding the relationship between your chain and the Polkadot relay chain. The Polkadot SDK provides all the tools needed to design custom runtime logic, enable cross-chain communication, and deploy your parachain to production.\n\nThe following sections provide detailed guidance on each aspect of parachain development, from initial design through deployment and ongoing maintenance.\n\n
    \n\n- Guide __Launch a Simple Parachain__\n\n ---\n\n Walk through the complete parachain launch flow: from setup and deployment to obtaining coretime.\n\n [:octicons-arrow-right-24: Deploy](/parachains/launch-a-parachain/set-up-the-parachain-template/)\n\n\n- Guide __Customize Your Runtime__\n\n ---\n\n Design your parachain's runtime logic and choose appropriate pallets for your use case.\n\n [:octicons-arrow-right-24: Get Started](/parachains/customize-runtime/)\n\n- Guide __Interoperability__\n\n ---\n\n Implement XCM for trustless cross-chain communication with other parachains.\n\n [:octicons-arrow-right-24: Learn More](/parachains/interoperability/get-started/)\n\n- Guide __Runtime Upgrades__\n\n ---\n\n Upgrade your parachain's runtime without hard forks using forkless upgrade mechanisms.\n\n [:octicons-arrow-right-24: Maintain](/parachains/runtime-maintenance/runtime-upgrades/)\n\n
    "} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 13, "end_char": 682, "estimated_token_count": 131, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe Asset Hub is a critical component in the Polkadot ecosystem, enabling the management of fungible and non-fungible assets across the network. Since the relay chain focuses on maintaining security and consensus without direct asset management, Asset Hub provides a streamlined platform for creating, managing, and using on-chain assets in a fee-efficient manner. This guide outlines the core features of Asset Hub, including how it handles asset operations, cross-chain transfers, and asset integration using XCM, as well as essential tools like [API Sidecar](#api-sidecar) and [`TxWrapper`](#txwrapper) for developers working with on-chain assets."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 1, "depth": 2, "title": "Assets Basics", "anchor": "assets-basics", "start_char": 682, "end_char": 3257, "estimated_token_count": 493, "token_estimator": "heuristic-v1", "text": "## Assets Basics\n\nIn the Polkadot ecosystem, the relay chain does not natively support additional assets beyond its native token (DOT for Polkadot, KSM for Kusama). The Asset Hub parachain on Polkadot and Kusama provides a fungible and non-fungible assets framework. Asset Hub allows developers and users to create, manage, and use assets across the ecosystem.\n\nAsset creators can use Asset Hub to track their asset issuance across multiple parachains and manage assets through operations such as minting, burning, and transferring. Projects that need a standardized method of handling on-chain assets will find this particularly useful. The fungible asset interface provided by Asset Hub closely resembles Ethereum's ERC-20 standard but is directly integrated into Polkadot's runtime, making it more efficient in terms of speed and transaction fees.\n\nIntegrating with Asset Hub offers several key benefits, particularly for infrastructure providers and users:\n\n- **Support for non-native on-chain assets**: Asset Hub enables seamless asset creation and management, allowing projects to develop tokens or assets that can interact with the broader ecosystem.\n- **Lower transaction fees**: Asset Hub offers significantly lower transaction costs—approximately one-tenth of the fees on the relay chain, providing cost-efficiency for regular operations.\n- **Reduced deposit requirements**: Depositing assets in Asset Hub is more accessible, with deposit requirements that are around one one-hundredth of those on the relay chain.\n- **Payment of transaction fees with non-native assets**: Users can pay transaction fees in assets other than the native token (DOT or KSM), offering more flexibility for developers and users.\n\nAssets created on the Asset Hub are stored as part of a map, where each asset has a unique ID that links to information about the asset, including details like:\n\n- The management team.\n- The total supply.\n- The number of accounts holding the asset.\n- **Sufficiency for account existence**: Whether the asset alone is enough to maintain an account without a native token balance.\n- The metadata of the asset, including its name, symbol, and the number of decimals for representation.\n\nSome assets can be regarded as sufficient to maintain an account's existence, meaning that users can create accounts on the network without needing a native token balance (i.e., no existential deposit required). Developers can also set minimum balances for their assets. If an account's balance drops below the minimum, the balance is considered dust and may be cleared."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 2, "depth": 2, "title": "Assets Pallet", "anchor": "assets-pallet", "start_char": 3257, "end_char": 3793, "estimated_token_count": 112, "token_estimator": "heuristic-v1", "text": "## Assets Pallet\n\nThe Polkadot SDK's Assets pallet is a powerful module designated for creating and managing fungible asset classes with a fixed supply. It offers a secure and flexible way to issue, transfer, freeze, and destroy assets. The pallet supports various operations and includes permissioned and non-permissioned functions to cater to simple and advanced use cases.\n\nVisit the [Assets Pallet Rust docs](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/index.html){target=\\_blank} for more in-depth information."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 3, "depth": 3, "title": "Key Features", "anchor": "key-features", "start_char": 3793, "end_char": 4454, "estimated_token_count": 140, "token_estimator": "heuristic-v1", "text": "### Key Features\n\nKey features of the Assets pallet include:\n\n- **Asset issuance**: Allows the creation of a new asset, where the total supply is assigned to the creator's account.\n- **Asset transfer**: Enables transferring assets between accounts while maintaining a balance in both accounts.\n- **Asset freezing**: Prevents transfers of a specific asset from one account, locking it from further transactions.\n- **Asset destruction**: Allows accounts to burn or destroy their holdings, removing those assets from circulation.\n- **Non-custodial transfers**: A non-custodial mechanism to enable one account to approve a transfer of assets on behalf of another."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 4, "depth": 3, "title": "Main Functions", "anchor": "main-functions", "start_char": 4454, "end_char": 5397, "estimated_token_count": 235, "token_estimator": "heuristic-v1", "text": "### Main Functions\n\nThe Assets pallet provides a broad interface for managing fungible assets. Some of the main dispatchable functions include:\n\n- **`create()`**: Create a new asset class by placing a deposit, applicable when asset creation is permissionless.\n- **`issue()`**: Mint a fixed supply of a new asset and assign it to the creator's account.\n- **`transfer()`**: Transfer a specified amount of an asset between two accounts.\n- **`approve_transfer()`**: Approve a non-custodial transfer, allowing a third party to move assets between accounts.\n- **`destroy()`**: Destroy an entire asset class, removing it permanently from the chain.\n- **`freeze()` and `thaw()`**: Administrators or privileged users can lock or unlock assets from being transferred.\n\nFor a full list of dispatchable and privileged functions, see the [dispatchables Rust docs](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/enum.Call.html){target=\\_blank}."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 5, "depth": 3, "title": "Querying Functions", "anchor": "querying-functions", "start_char": 5397, "end_char": 6347, "estimated_token_count": 193, "token_estimator": "heuristic-v1", "text": "### Querying Functions\n\nThe Assets pallet exposes several key querying functions that developers can interact with programmatically. These functions allow you to query asset information and perform operations essential for managing assets across accounts. The two main querying functions are:\n\n- **`balance(asset_id, account)`**: Retrieves the balance of a given asset for a specified account. Useful for checking the holdings of an asset class across different accounts.\n\n- **`total_supply(asset_id)`**: Returns the total supply of the asset identified by `asset_id`. Allows users to verify how much of the asset exists on-chain.\n\nIn addition to these basic functions, other utility functions are available for querying asset metadata and performing asset transfers. You can view the complete list of querying functions in the [Struct Pallet Rust docs](https://docs.rs/pallet-assets/latest/pallet_assets/pallet/struct.Pallet.html){target=\\_blank}."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 6, "depth": 3, "title": "Permission Models and Roles", "anchor": "permission-models-and-roles", "start_char": 6347, "end_char": 7634, "estimated_token_count": 239, "token_estimator": "heuristic-v1", "text": "### Permission Models and Roles\n\nThe Assets pallet incorporates a robust permission model, enabling control over who can perform specific operations like minting, transferring, or freezing assets. The key roles within the permission model are:\n\n- **Admin**: Can freeze (preventing transfers) and forcibly transfer assets between accounts. Admins also have the power to reduce the balance of an asset class across arbitrary accounts. They manage the more sensitive and administrative aspects of the asset class.\n- **Issuer**: Responsible for minting new tokens. When new assets are created, the Issuer is the account that controls their distribution to other accounts.\n- **Freezer**: Can lock the transfer of assets from an account, preventing the account holder from moving their balance. This function is useful for freezing accounts involved in disputes or fraud.\n- **Owner**: Has overarching control, including destroying an entire asset class. Owners can also set or update the Issuer, Freezer, and Admin roles.\n\nThese permissions provide fine-grained control over assets, enabling developers and asset managers to ensure secure, controlled operations. Each of these roles is crucial for managing asset lifecycles and ensuring that assets are used appropriately across the network."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 7, "depth": 3, "title": "Asset Freezing", "anchor": "asset-freezing", "start_char": 7634, "end_char": 8552, "estimated_token_count": 172, "token_estimator": "heuristic-v1", "text": "### Asset Freezing\n\nThe Assets pallet allows you to freeze assets. This feature prevents transfers or spending from a specific account, effectively locking the balance of an asset class until it is explicitly unfrozen. Asset freezing is beneficial when assets are restricted due to security concerns or disputes.\n\nFreezing assets is controlled by the Freezer role, as mentioned earlier. Only the account with the Freezer privilege can perform these operations. Here are the key freezing functions:\n\n- **`freeze(asset_id, account)`**: Locks the specified asset of the account. While the asset is frozen, no transfers can be made from the frozen account.\n- **`thaw(asset_id, account)`**: Corresponding function for unfreezing, allowing the asset to be transferred again.\n\nThis approach enables secure and flexible asset management, providing administrators the tools to control asset movement in special circumstances."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 8, "depth": 3, "title": "Non-Custodial Transfers (Approval API)", "anchor": "non-custodial-transfers-approval-api", "start_char": 8552, "end_char": 9746, "estimated_token_count": 232, "token_estimator": "heuristic-v1", "text": "### Non-Custodial Transfers (Approval API)\n\nThe Assets pallet also supports non-custodial transfers through the Approval API. This feature allows one account to approve another account to transfer a specific amount of its assets to a third-party recipient without granting full control over the account's balance. Non-custodial transfers enable secure transactions where trust is required between multiple parties.\n\nHere's a brief overview of the key functions for non-custodial asset transfers:\n\n- **`approve_transfer(asset_id, delegate, amount)`**: Approves a delegate to transfer up to a certain amount of the asset on behalf of the original account holder.\n- **`cancel_approval(asset_id, delegate)`**: Cancels a previous approval for the delegate. Once canceled, the delegate no longer has permission to transfer the approved amount.\n- **`transfer_approved(asset_id, owner, recipient, amount)`**: Executes the approved asset transfer from the owner’s account to the recipient. The delegate account can call this function once approval is granted.\n\nThese delegated operations make it easier to manage multi-step transactions and dApps that require complex asset flows between participants."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 9, "depth": 2, "title": "Foreign Assets", "anchor": "foreign-assets", "start_char": 9746, "end_char": 10290, "estimated_token_count": 94, "token_estimator": "heuristic-v1", "text": "## Foreign Assets\n\nForeign assets in Asset Hub refer to assets originating from external blockchains or parachains that are registered in the Asset Hub. These assets are typically native tokens from other parachains within the Polkadot ecosystem or bridged tokens from external blockchains such as Ethereum.\n\nOnce a foreign asset is registered in the Asset Hub by its originating blockchain's root origin, users are able to send these tokens to the Asset Hub and interact with them as they would any other asset within the Polkadot ecosystem."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 10, "depth": 3, "title": "Handling Foreign Assets", "anchor": "handling-foreign-assets", "start_char": 10290, "end_char": 11225, "estimated_token_count": 166, "token_estimator": "heuristic-v1", "text": "### Handling Foreign Assets\n\nThe Foreign Assets pallet, an instance of the Assets pallet, manages these assets. Since foreign assets are integrated into the same interface as native assets, developers can use the same functionalities, such as transferring and querying balances. However, there are important distinctions when dealing with foreign assets.\n\n- **Asset identifier**: Unlike native assets, foreign assets are identified using an XCM Multilocation rather than a simple numeric `AssetId`. This multilocation identifier represents the cross-chain location of the asset and provides a standardized way to reference it across different parachains and relay chains.\n\n- **Transfers**: Once registered in the Asset Hub, foreign assets can be transferred between accounts, just like native assets. Users can also send these assets back to their originating blockchain if supported by the relevant cross-chain messaging mechanisms."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 11, "depth": 2, "title": "Integration", "anchor": "integration", "start_char": 11225, "end_char": 11668, "estimated_token_count": 71, "token_estimator": "heuristic-v1", "text": "## Integration\n\nAsset Hub supports a variety of integration tools that make it easy for developers to manage assets and interact with the blockchain in their applications. The tools and libraries provided by Parity Technologies enable streamlined operations, such as querying asset information, building transactions, and monitoring cross-chain asset transfers.\n\nDevelopers can integrate Asset Hub into their projects using these core tools:"} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 12, "depth": 3, "title": "API Sidecar", "anchor": "api-sidecar", "start_char": 11668, "end_char": 12511, "estimated_token_count": 211, "token_estimator": "heuristic-v1", "text": "### API Sidecar\n\n[API Sidecar](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a RESTful service that can be deployed alongside Polkadot and Kusama nodes. It provides endpoints to retrieve real-time blockchain data, including asset information. When used with Asset Hub, Sidecar allows querying:\n\n- **Asset look-ups**: Retrieve specific assets using `AssetId`.\n- **Asset balances**: View the balance of a particular asset on Asset Hub.\n\nPublic instances of API Sidecar connected to Asset Hub are available, such as:\n\n- [Polkadot Asset Hub Sidecar](https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/){target=\\_blank}\n- [Kusama Asset Hub Sidecar](https://kusama-asset-hub-public-sidecar.parity-chains.parity.io/){target=\\_blank}\n\nThese public instances are primarily for ad-hoc testing and quick checks."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 13, "depth": 3, "title": "TxWrapper", "anchor": "txwrapper", "start_char": 12511, "end_char": 13113, "estimated_token_count": 113, "token_estimator": "heuristic-v1", "text": "### TxWrapper\n\n[`TxWrapper`](https://github.com/paritytech/txwrapper-core){target=\\_blank} is a library that simplifies constructing and signing transactions for Polkadot SDK-based chains, including Polkadot and Kusama. This tool includes support for working with Asset Hub, enabling developers to:\n\n- Construct offline transactions.\n- Leverage asset-specific functions such as minting, burning, and transferring assets.\n\n`TxWrapper` provides the flexibility needed to integrate asset operations into custom applications while maintaining the security and efficiency of Polkadot's transaction model."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 14, "depth": 3, "title": "Parachain Node", "anchor": "parachain-node", "start_char": 13113, "end_char": 13766, "estimated_token_count": 131, "token_estimator": "heuristic-v1", "text": "### Parachain Node\n\nTo fully leverage the Asset Hub's functionality, developers will need to run a system parachain node. Setting up an Asset Hub node allows users to interact with the parachain in real time, syncing data and participating in the broader Polkadot ecosystem. Guidelines for setting up an [Asset Hub node](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/cumulus#asset-hub-){target=\\_blank} are available in the Parity documentation.\n\nUsing these integration tools, developers can manage assets seamlessly and integrate Asset Hub functionality into their applications, leveraging Polkadot's powerful infrastructure."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 15, "depth": 2, "title": "XCM Transfer Monitoring", "anchor": "xcm-transfer-monitoring", "start_char": 13766, "end_char": 14109, "estimated_token_count": 56, "token_estimator": "heuristic-v1", "text": "## XCM Transfer Monitoring\n\nSince Asset Hub facilitates cross-chain asset transfers across the Polkadot ecosystem, XCM transfer monitoring becomes an essential practice for developers and infrastructure providers. This section outlines how to monitor the cross-chain movement of assets between parachains, the relay chain, and other systems."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 16, "depth": 3, "title": "Monitor XCM Deposits", "anchor": "monitor-xcm-deposits", "start_char": 14109, "end_char": 14901, "estimated_token_count": 160, "token_estimator": "heuristic-v1", "text": "### Monitor XCM Deposits\n\nAs assets move between chains, tracking the cross-chain transfers in real time is crucial. Whether assets are transferred via a teleport from system parachains or through a reserve-backed transfer from any other parachain, each transfer emits a relevant event (such as the `balances.minted` event).\n\nTo ensure accurate monitoring of these events:\n\n- **Track XCM deposits**: Query every new block created in the relay chain or Asset Hub, loop through the events array, and filter for any `balances.minted` events which confirm the asset was successfully transferred to the account.\n- **Track event origins**: Each `balances.minted` event points to a specific address. By monitoring this, service providers can verify that assets have arrived in the correct account."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 17, "depth": 3, "title": "Track XCM Information Back to the Source", "anchor": "track-xcm-information-back-to-the-source", "start_char": 14901, "end_char": 15568, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "### Track XCM Information Back to the Source\n\nWhile the `balances.minted` event confirms the arrival of assets, there may be instances where you need to trace the origin of the cross-chain message that triggered the event. In such cases, you can:\n\n1. Query the relevant chain at the block where the `balances.minted` event was emitted.\n2. Look for a `messageQueue(Processed)` event within that block's initialization. This event contains a parameter (`Id`) that identifies the cross-chain message received by the relay chain or Asset Hub. You can use this `Id` to trace the message back to its origin chain, offering full visibility of the asset transfer's journey."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 18, "depth": 3, "title": "Practical Monitoring Examples", "anchor": "practical-monitoring-examples", "start_char": 15568, "end_char": 16379, "estimated_token_count": 163, "token_estimator": "heuristic-v1", "text": "### Practical Monitoring Examples\n\nThe preceding sections outline the process of monitoring XCM deposits to specific accounts and then tracing back the origin of these deposits. The process of tracking an XCM transfer and the specific events to monitor may vary based on the direction of the XCM message. Here are some examples to showcase the slight differences:\n\n- **Transfer from parachain to relay chain**: Track `parachainsystem(UpwardMessageSent)` on the parachain and `messagequeue(Processed)` on the relay chain.\n- **Transfer from relay chain to parachain**: Track `xcmPallet(sent)` on the relay chain and `dmpqueue(ExecutedDownward)` on the parachain.\n- **Transfer between parachains**: Track `xcmpqueue(XcmpMessageSent)` on the system parachain and `xcmpqueue(Success)` on the destination parachain."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 19, "depth": 3, "title": "Monitor for Failed XCM Transfers", "anchor": "monitor-for-failed-xcm-transfers", "start_char": 16379, "end_char": 17187, "estimated_token_count": 176, "token_estimator": "heuristic-v1", "text": "### Monitor for Failed XCM Transfers\n\nSometimes, XCM transfers may fail due to liquidity or other errors. Failed transfers emit specific error events, which are key to resolving issues in asset transfers. Monitoring for these failure events helps catch issues before they affect asset balances.\n\n- **Relay chain to system parachain**: Look for the `dmpqueue(ExecutedDownward)` event on the parachain with an `Incomplete` outcome and an error type such as `UntrustedReserveLocation`.\n- **Parachain to parachain**: Monitor for `xcmpqueue(Fail)` on the destination parachain with error types like `TooExpensive`.\n\nFor detailed error management in XCM, see Gavin Wood's blog post on [XCM Execution and Error Management](https://polkadot.com/blog/xcm-part-three-execution-and-error-management/){target=\\_blank}."} -{"page_id": "reference-polkadot-hub-assets-and-smart-contracts", "page_title": "Asset Hub", "index": 20, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 17187, "end_char": 18211, "estimated_token_count": 244, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
    \n\n- Tutorial __Register a Local Asset__\n\n ---\n\n Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions.\n\n [:octicons-arrow-right-24: Reference](/chain-interactions/token-operations/register-local-asset/)\n\n- Tutorial __Register a Foreign Asset__\n\n ---\n\n An in-depth guide to registering a foreign asset on the Asset Hub parachain, providing clear, step-by-step instructions.\n\n [:octicons-arrow-right-24: Reference](/chain-interactions/token-operations/register-foreign-asset/)\n\n- Tutorial __Convert Assets__\n\n ---\n\n A guide detailing the step-by-step process of converting assets on Asset Hub, helping users efficiently navigate asset management on the platform.\n\n [:octicons-arrow-right-24: Reference](/chain-interactions/token-operations/convert-assets/)\n\n
    "} -{"page_id": "reference-polkadot-hub-bridging", "page_title": "Bridge Hub", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 14, "end_char": 1065, "estimated_token_count": 184, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe Bridge Hub system parachain plays a crucial role in facilitating trustless interactions between Polkadot, Kusama, Ethereum, and other blockchain ecosystems. By implementing on-chain light clients and supporting protocols like BEEFY and GRANDPA, Bridge Hub ensures seamless message transmission and state verification across chains. It also provides essential [pallets](/reference/glossary/#pallet){target=\\_blank} for sending and receiving messages, making it a cornerstone of Polkadot’s interoperability framework. With built-in support for XCM (Cross-Consensus Messaging), Bridge Hub enables secure, efficient communication between diverse blockchain networks.\n\nThis guide covers the architecture, components, and deployment of the Bridge Hub system. You'll explore its trustless bridging mechanisms, key pallets for various blockchains, and specific implementations like Snowbridge and the Polkadot <> Kusama bridge. By the end, you'll understand how Bridge Hub enhances connectivity within the Polkadot ecosystem and beyond."} -{"page_id": "reference-polkadot-hub-bridging", "page_title": "Bridge Hub", "index": 1, "depth": 2, "title": "Trustless Bridging", "anchor": "trustless-bridging", "start_char": 1065, "end_char": 2671, "estimated_token_count": 313, "token_estimator": "heuristic-v1", "text": "## Trustless Bridging\n\nBridge Hub provides a mode of trustless bridging through its implementation of on-chain light clients and trustless relayers. Trustless bridges are essentially two one-way bridges, where each chain has a method of verifying the state of the other in a trustless manner through consensus proofs. In this context, \"trustless\" refers to the lack of need to trust a human when interacting with various system components. Trustless systems are based instead on trusting mathematics, cryptography, and code. The target chain and source chain both provide ways of verifying one another's state and actions (such as a transfer) based on the consensus and finality of both chains rather than an external mechanism controlled by a third party.\n\n[BEEFY (Bridge Efficiency Enabling Finality Yielder)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#bridging-beefy){target=\\_blank} is instrumental in this solution. It provides a more efficient way to verify the consensus on the relay chain. It allows the participants in a network to verify finality proofs, meaning a remote chain like Ethereum can verify the state of Polkadot at a given block height. \n\nFor example, the Ethereum and Polkadot bridging solution that [Snowbridge](https://docs.snowbridge.network/){target=\\_blank} implements involves two light clients: one which verifies the state of Polkadot and the other which verifies the state of Ethereum. The light client for Polkadot is implemented in the runtime as a pallet, whereas the light client for Ethereum is implemented as a smart contract on the beacon chain."} -{"page_id": "reference-polkadot-hub-bridging", "page_title": "Bridge Hub", "index": 2, "depth": 2, "title": "Bridging Components", "anchor": "bridging-components", "start_char": 2671, "end_char": 3623, "estimated_token_count": 242, "token_estimator": "heuristic-v1", "text": "## Bridging Components\n\nIn any given Bridge Hub implementation (Kusama, Polkadot, or other relay chains), there are a few primary pallets that are utilized:\n\n- **[Pallet Bridge GRANDPA](https://paritytech.github.io/polkadot-sdk/master/pallet_bridge_grandpa/index.html){target=\\_blank}**: An on-chain GRANDPA light client for Substrate based chains.\n- **[Pallet Bridge Parachains](https://paritytech.github.io/polkadot-sdk/master/pallet_bridge_parachains/index.html){target=\\_blank}**: A finality module for parachains.\n- **[Pallet Bridge Messages](https://paritytech.github.io/polkadot-sdk/master/pallet_bridge_messages/index.html){target=\\_blank}**: A pallet which allows sending, receiving, and tracking of inbound and outbound messages.\n- **[Pallet XCM Bridge](https://paritytech.github.io/polkadot-sdk/master/pallet_xcm_bridge_hub/index.html){target=\\_blank}**: A pallet which, with the Bridge Messages pallet, adds XCM support to bridge pallets."} -{"page_id": "reference-polkadot-hub-bridging", "page_title": "Bridge Hub", "index": 3, "depth": 3, "title": "Ethereum-Specific Support", "anchor": "ethereum-specific-support", "start_char": 3623, "end_char": 4243, "estimated_token_count": 149, "token_estimator": "heuristic-v1", "text": "### Ethereum-Specific Support\n\nBridge Hub also has a set of components and pallets that support a bridge between Polkadot and Ethereum through [Snowbridge](https://github.com/Snowfork/snowbridge){target=\\_blank}.\n\nTo view the complete list of which pallets are included in Bridge Hub, visit the Subscan [Runtime Modules](https://bridgehub-polkadot.subscan.io/runtime){target=\\_blank} page. Alternatively, the source code for those pallets can be found in the Polkadot SDK [Snowbridge Pallets](https://github.com/paritytech/polkadot-sdk/tree/polkadot-stable2506-2/bridges/snowbridge/pallets){target=\\_blank} repository."} -{"page_id": "reference-polkadot-hub-bridging", "page_title": "Bridge Hub", "index": 4, "depth": 2, "title": "Deployed Bridges", "anchor": "deployed-bridges", "start_char": 4243, "end_char": 4840, "estimated_token_count": 160, "token_estimator": "heuristic-v1", "text": "## Deployed Bridges\n\n- [**Snowbridge**](https://wiki.polkadot.com/learn/learn-snowbridge/){target=\\_blank}: A general-purpose, trustless bridge between Polkadot and Ethereum.\n- [**Hyperbridge**](https://wiki.polkadot.com/learn/learn-hyperbridge/){target=\\_blank}: A cross-chain solution built as an interoperability coprocessor, providing state-proof-based interoperability across all blockchains.\n- [**Polkadot <> Kusama Bridge**](https://wiki.polkadot.com/learn/learn-dot-ksm-bridge/){target=\\_blank}: A bridge that utilizes relayers to bridge the Polkadot and Kusama relay chains trustlessly."} -{"page_id": "reference-polkadot-hub-bridging", "page_title": "Bridge Hub", "index": 5, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 4840, "end_char": 5467, "estimated_token_count": 172, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n- Go over the Bridge Hub README in the Polkadot SDK [Bridge-hub Parachains](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/cumulus/parachains/runtimes/bridge-hubs/README.md){target=\\_blank} repository.\n- Take a deeper dive into bridging architecture in the Polkadot SDK [High-Level Bridge](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/bridges/docs/high-level-overview.md){target=\\_blank} documentation.\n- Read more about [BEEFY and Bridging in the Polkadot Wiki](/reference/polkadot-hub/consensus-and-security/pos-consensus/#bridging-beefy){target=\\_blank}."} -{"page_id": "reference-polkadot-hub-collectives-and-daos", "page_title": "Collectives Chain", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 0, "end_char": 824, "estimated_token_count": 150, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nEstablished through [Referendum 81](https://polkadot-old.polkassembly.io/referendum/81){target=\\_blank}, the Collectives chain operates as a dedicated parachain exclusive to the Polkadot network with no counterpart on Kusama. This specialized infrastructure provides a foundation for various on-chain governance groups essential to Polkadot's ecosystem.\n\nThe architecture enables entire networks to function as unified entities, allowing them to present cohesive positions and participate in cross-network governance through [Bridge Hub](/polkadot-protocol/architecture/system-chains/bridge-hub){target=\\_blank}. This capability represents a fundamental advancement in Web3 principles, eliminating dependencies on traditional third-party intermediaries such as legal systems or jurisdictional authorities."} -{"page_id": "reference-polkadot-hub-collectives-and-daos", "page_title": "Collectives Chain", "index": 1, "depth": 2, "title": "Key Collectives", "anchor": "key-collectives", "start_char": 824, "end_char": 2288, "estimated_token_count": 274, "token_estimator": "heuristic-v1", "text": "## Key Collectives\n\nThe Collectives chain hosts several important governance bodies:\n\n- [**Polkadot Technical Fellowship**](https://wiki.polkadot.com/learn/learn-polkadot-technical-fellowship/){target=\\_blank}: A self-governing assembly of protocol experts and developers who oversee technical aspects of the Polkadot and Kusama networks. The Fellowship operates both on-chain through the collectives system and off-chain via GitHub repositories, public discussion forums, and monthly development calls that are publicly accessible.\n\n- [**Polkadot Alliance**](https://wiki.polkadot.com/general/glossary/#polkadot-alliance){target=\\_blank}: A consortium founded by seven leading parachain projects (Acala, Astar, Interlay, Kilt, Moonbeam, Phala, and Subscan) to establish development standards and ethical guidelines within the ecosystem. This ranked collective, comprised of \"Fellows\" and \"Allies,\" focuses on promoting best practices and identifying potential bad actors. Membership is primarily designed for organizations, projects, and other networks rather than individuals.\n\nThese collectives serve as pillars of Polkadot's decentralized governance model, enabling community-driven decision-making and establishing technical standards that shape the network's evolution. Through structured on-chain representation, they provide transparent mechanisms for ecosystem development while maintaining the core Web3 principles of trustlessness and decentralization."} -{"page_id": "reference-polkadot-hub-consensus-and-security-agile-coretime", "page_title": "Agile Coretime", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 18, "end_char": 1479, "estimated_token_count": 318, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nAgile Coretime is the [scheduling](https://en.wikipedia.org/wiki/Scheduling_(computing)){target=\\_blank} framework on Polkadot that lets parachains efficiently access cores, which comprise an active validator set tasked with parablock validation. As the first blockchain to enable a flexible scheduling system for blockspace production, Polkadot offers unparalleled adaptability for parachains.\n\n``` mermaid\ngraph TB\n A[Cores Designation]\n B[Bulk Coretime]\n C[On-Demand Coretime]\n A --continuous--> B\n A --flexible--> C \n```\n\nCores can be designated to a parachain either continuously through [bulk coretime](#bulk-coretime) or dynamically via [on-demand coretime](#on-demand-coretime). Additionally, Polkadot supports scheduling multiple cores in parallel through [elastic scaling](https://wiki.polkadot.com/learn/learn-elastic-scaling/){target=\\_blank}, which is a feature under active development on Polkadot. This flexibility empowers parachains to optimize their resource usage and block production according to their unique needs.\n\nIn this guide, you'll learn how bulk coretime enables continuous core access with features like interlacing and splitting, and how on-demand coretime provides flexible, pay-per-use scheduling for parachains. For a deep dive on Agile Coretime and its terminology, refer to the [Wiki doc](https://wiki.polkadot.com/learn/learn-agile-coretime/#introduction-to-agile-coretime){target=\\_blank}."} -{"page_id": "reference-polkadot-hub-consensus-and-security-agile-coretime", "page_title": "Agile Coretime", "index": 1, "depth": 2, "title": "Bulk Coretime", "anchor": "bulk-coretime", "start_char": 1479, "end_char": 2179, "estimated_token_count": 148, "token_estimator": "heuristic-v1", "text": "## Bulk Coretime\n\nBulk coretime is a fixed duration of continuous coretime represented by an NFT that can be purchased through [coretime sales](#coretime-sales) in DOT and can be split, shared, or resold. Currently, the duration of bulk coretime is set to 28 days. Coretime purchased in bulk and assigned to a single parachain is eligible for a price-capped renewal, providing a form of rent-controlled access, which is important for predicting the running costs in the near future. Suppose the bulk coretime is [interlaced](#coretime-interlacing) or [split](#coretime-splitting) or is kept idle without assigning it to a parachain. In that case, it will be ineligible for the price-capped renewal."} -{"page_id": "reference-polkadot-hub-consensus-and-security-agile-coretime", "page_title": "Agile Coretime", "index": 2, "depth": 3, "title": "Coretime Interlacing", "anchor": "coretime-interlacing", "start_char": 2179, "end_char": 2550, "estimated_token_count": 62, "token_estimator": "heuristic-v1", "text": "### Coretime Interlacing\n\nIt is the action of dividing bulk coretime across multiple parachains that produce blocks spaced uniformly in time. For example, think of multiple parachains taking turns producing blocks, demonstrating a simple form of interlacing. This feature can be used by parachains with a low transaction volume and need not continuously produce blocks."} -{"page_id": "reference-polkadot-hub-consensus-and-security-agile-coretime", "page_title": "Agile Coretime", "index": 3, "depth": 3, "title": "Coretime Splitting", "anchor": "coretime-splitting", "start_char": 2550, "end_char": 2815, "estimated_token_count": 49, "token_estimator": "heuristic-v1", "text": "### Coretime Splitting\n\nIt is the action of dividing bulk coretime into multiple contiguous regions. This feature can be used by parachains that need to produce blocks continuously but do not require the whole 28 days of bulk coretime and require only part of it."} -{"page_id": "reference-polkadot-hub-consensus-and-security-agile-coretime", "page_title": "Agile Coretime", "index": 4, "depth": 2, "title": "On-Demand Coretime", "anchor": "on-demand-coretime", "start_char": 2815, "end_char": 3028, "estimated_token_count": 42, "token_estimator": "heuristic-v1", "text": "## On-Demand Coretime\n\nPolkadot has dedicated cores assigned to provide core time on demand. These cores are excluded from the coretime sales and are reserved for on-demand parachains, which pay in DOT per block."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 28, "end_char": 761, "estimated_token_count": 132, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot's Proof of Stake consensus model leverages a unique hybrid approach by design to promote decentralized and secure network operations. In traditional Proof of Stake (PoS) systems, a node's ability to validate transactions is tied to its token holdings, which can lead to centralization risks and limited validator participation. Polkadot addresses these concerns through its [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank} model and a combination of advanced consensus mechanisms to ensure efficient block production and strong finality guarantees. This combination enables the Polkadot network to scale while maintaining security and decentralization."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 1, "depth": 2, "title": "Nominated Proof of Stake", "anchor": "nominated-proof-of-stake", "start_char": 761, "end_char": 1788, "estimated_token_count": 215, "token_estimator": "heuristic-v1", "text": "## Nominated Proof of Stake\n\nPolkadot uses Nominated Proof of Stake (NPoS) to select the validator set and secure the network. This model is designed to maximize decentralization and security by balancing the roles of [validators](https://wiki.polkadot.com/learn/learn-validator/){target=\\_blank} and [nominators](https://wiki.polkadot.com/learn/learn-nominator/){target=\\_blank}.\n\n- **Validators**: Play a key role in maintaining the network's integrity. They produce new blocks, validate parachain blocks, and ensure the finality of transactions across the relay chain.\n- **Nominators**: Support the network by selecting validators to back with their stake. This mechanism allows users who don't want to run a validator node to still participate in securing the network and earn rewards based on the validators they support.\n\nIn Polkadot's NPoS system, nominators can delegate their tokens to trusted validators, giving them voting power in selecting validators while spreading security responsibilities across the network."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 2, "depth": 2, "title": "Hybrid Consensus", "anchor": "hybrid-consensus", "start_char": 1788, "end_char": 2840, "estimated_token_count": 193, "token_estimator": "heuristic-v1", "text": "## Hybrid Consensus\n\nPolkadot employs a hybrid consensus model that combines two key protocols: a finality gadget called [GRANDPA](#finality-gadget-grandpa) and a block production mechanism known as [BABE](#block-production-babe). This hybrid approach enables the network to benefit from both rapid block production and provable finality, ensuring security and performance.\n\nThe hybrid consensus model has some key advantages:\n\n- **Probabilistic finality**: With BABE constantly producing new blocks, Polkadot ensures that the network continues to make progress, even when a final decision has not yet been reached on which chain is the true canonical chain.\n\n- **Provable finality**: GRANDPA guarantees that once a block is finalized, it can never be reverted, ensuring that all network participants agree on the finalized chain.\n\nBy using separate protocols for block production and finality, Polkadot can achieve rapid block creation and strong guarantees of finality while avoiding the typical trade-offs seen in traditional consensus mechanisms."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 3, "depth": 2, "title": "Block Production - BABE", "anchor": "block-production-babe", "start_char": 2840, "end_char": 4656, "estimated_token_count": 360, "token_estimator": "heuristic-v1", "text": "## Block Production - BABE\n\nBlind Assignment for Blockchain Extension (BABE) is Polkadot's block production mechanism, working with GRANDPA to ensure blocks are produced consistently across the network. As validators participate in BABE, they are assigned block production slots through a randomness-based lottery system. This helps determine which validator is responsible for producing a block at a given time. BABE shares similarities with [Ouroboros Praos](https://eprint.iacr.org/2017/573.pdf){target=\\_blank} but differs in key aspects like chain selection rules and slot timing.\n\nKey features of BABE include:\n\n- **Epochs and slots**: BABE operates in phases called epochs, each of which is divided into slots (around 6 seconds per slot). Validators are assigned slots at the beginning of each epoch based on stake and randomness.\n\n- **Randomized block production**: Validators enter a lottery to determine which will produce a block in a specific slot. This randomness is sourced from the relay chain's [randomness cycle](/reference/parachains/randomness/){target=\\_blank}.\n\n- **Multiple block producers per slot**: In some cases, more than one validator might win the lottery for the same slot, resulting in multiple blocks being produced. These blocks are broadcasted, and the network's fork choice rule helps decide which chain to follow.\n\n- **Handling empty slots**: If no validators win the lottery for a slot, a secondary selection algorithm ensures that a block is still produced. Validators selected through this method always produce a block, ensuring no slots are skipped.\n\nBABE's combination of randomness and slot allocation creates a secure, decentralized system for consistent block production while also allowing for fork resolution when multiple validators produce blocks for the same slot."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 4, "depth": 3, "title": "Validator Participation", "anchor": "validator-participation", "start_char": 4656, "end_char": 6311, "estimated_token_count": 331, "token_estimator": "heuristic-v1", "text": "### Validator Participation\n\nIn BABE, validators participate in a lottery for every slot to determine whether they are responsible for producing a block during that slot. This process's randomness ensures a decentralized and unpredictable block production mechanism.\n\nThere are two lottery outcomes for any given slot that initiate additional processes:\n\n- **Multiple validators in a slot**: Due to the randomness, multiple validators can be selected to produce a block for the same slot. When this happens, each validator produces a block and broadcasts it to the network resulting in a race condition. The network's topology and latency then determine which block reaches the majority of nodes first. BABE allows both chains to continue building until the finalization process resolves which one becomes canonical. The [Fork Choice](#fork-choice) rule is then used to decide which chain the network should follow.\n\n- **No validators in a slot**: On occasions when no validator is selected by the lottery, a [secondary validator selection algorithm](https://spec.polkadot.network/sect-block-production#defn-babe-secondary-slots){target=\\_blank} steps in. This backup ensures that a block is still produced, preventing skipped slots. However, if the primary block produced by a verifiable random function [(VRF)-selected](/reference/parachains/randomness/#vrf){target=\\_blank} validator exists for that slot, the secondary block will be ignored. As a result, every slot will have either a primary or a secondary block.\n\nThis design ensures continuous block production, even in cases of multiple competing validators or an absence of selected validators."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 5, "depth": 3, "title": "Additional Resources", "anchor": "additional-resources", "start_char": 6311, "end_char": 6806, "estimated_token_count": 111, "token_estimator": "heuristic-v1", "text": "### Additional Resources\n\nFor further technical insights about BABE, including cryptographic details and formal proofs, see the [BABE paper](https://research.web3.foundation/Polkadot/protocols/block-production/Babe){target=\\_blank} from Web3 Foundation.\n\nFor BABE technical definitions, constants, and formulas, see the [Block Production Lottery](https://spec.polkadot.network/sect-block-production#sect-block-production-lottery){target=\\_blank} section of the Polkadot Protocol Specification."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 6, "depth": 2, "title": "Finality Gadget - GRANDPA", "anchor": "finality-gadget-grandpa", "start_char": 6806, "end_char": 8324, "estimated_token_count": 292, "token_estimator": "heuristic-v1", "text": "## Finality Gadget - GRANDPA\n\nGRANDPA (GHOST-based Recursive ANcestor Deriving Prefix Agreement) serves as the finality gadget for Polkadot's relay chain. Operating alongside the BABE block production mechanism, it ensures provable finality, giving participants confidence that blocks finalized by GRANDPA cannot be reverted.\n\nKey features of GRANDPA include:\n\n- **Independent finality service**: GRANDPA runs separately from the block production process, operating in parallel to ensure seamless finalization.\n- **Chain-based finalization**: Instead of finalizing one block at a time, GRANDPA finalizes entire chains, speeding up the process significantly.\n- **Batch finalization**: Can finalize multiple blocks in a single round, enhancing efficiency and minimizing delays in the network.\n- **Partial synchrony tolerance**: GRANDPA works effectively in a partially synchronous network environment, managing both asynchronous and synchronous conditions.\n- **Byzantine fault tolerance**: Can handle up to 1/5 Byzantine (malicious) nodes, ensuring the system remains secure even when faced with adversarial behavior.\n\n??? note \"What is GHOST?\"\n [GHOST (Greedy Heaviest-Observed Subtree)](https://eprint.iacr.org/2018/104.pdf){target=\\blank} is a consensus protocol used in blockchain networks to select the heaviest branch in a block tree. Unlike traditional longest-chain rules, GHOST can more efficiently handle high block production rates by considering the weight of subtrees rather than just the chain length."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 7, "depth": 3, "title": "Probabilistic vs. Provable Finality", "anchor": "probabilistic-vs-provable-finality", "start_char": 8324, "end_char": 9130, "estimated_token_count": 142, "token_estimator": "heuristic-v1", "text": "### Probabilistic vs. Provable Finality\n\nIn traditional Proof of Work (PoW) blockchains, finality is probabilistic. As blocks are added to the chain, the probability that a block is final increases, but it can never be guaranteed. Eventual consensus means that all nodes will agree on a single version of the blockchain over time, but this process can be unpredictable and slow.\n\nConversely, GRANDPA provides provable finality, which means that once a block is finalized, it is irreversible. By using Byzantine fault-tolerant agreements, GRANDPA finalizes blocks more efficiently and securely than probabilistic mechanisms like Nakamoto consensus. Like Ethereum's Casper the Friendly Finality Gadget (FFG), GRANDPA ensures that finalized blocks cannot be reverted, offering stronger consensus guarantees."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 8, "depth": 3, "title": "Additional Resources", "anchor": "additional-resources-2", "start_char": 9130, "end_char": 9678, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "### Additional Resources\n\nFor technical insights, including formal proofs and detailed algorithms, see the [GRANDPA paper](https://github.com/w3f/consensus/blob/master/pdf/grandpa.pdf){target=\\_blank} from Web3 Foundation.\n\nFor a deeper look at the code behind GRANDPA, see the following GitHub repositories:\n\n- [GRANDPA Rust implementation](https://github.com/paritytech/finality-grandpa){target=\\_blank}\n- [GRANDPA Pallet](https://github.com/paritytech/polkadot-sdk/blob/polkadot-stable2506-2/substrate/frame/grandpa/src/lib.rs){target=\\_blank}"} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 9, "depth": 2, "title": "Fork Choice", "anchor": "fork-choice", "start_char": 9678, "end_char": 10520, "estimated_token_count": 176, "token_estimator": "heuristic-v1", "text": "## Fork Choice\n\nThe fork choice of the relay chain combines BABE and GRANDPA:\n\n1. BABE must always build on the chain that GRANDPA has finalized.\n2. When there are forks after the finalized head, BABE builds on the chain with the most primary blocks to provide probabilistic finality.\n\n![Fork choice diagram](/images/reference/polkadot-hub/consensus-and-security/pos-consensus/consensus-protocols-01.webp)\n\nIn the preceding diagram, finalized blocks are black, and non-finalized blocks are yellow. Primary blocks are labeled '1', and secondary blocks are labeled '2.' The topmost chain is the longest chain originating from the last finalized block, but it is not selected because it only has one primary block at the time of evaluation. In comparison, the one below it originates from the last finalized block and has three primary blocks."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 10, "depth": 3, "title": "Additional Resources", "anchor": "additional-resources-3", "start_char": 10520, "end_char": 11107, "estimated_token_count": 131, "token_estimator": "heuristic-v1", "text": "### Additional Resources\n\nTo learn more about how BABE and GRANDPA work together to produce and finalize blocks on Kusama, see this [Block Production and Finalization in Polkadot](https://youtu.be/FiEAnVECa8c){target=\\_blank} talk from Web3 Foundation's Bill Laboon. \n\nFor an in-depth academic discussion about Polkadot's hybrid consensus model, see this [Block Production and Finalization in Polkadot: Understanding the BABE and GRANDPA Protocols](https://www.youtube.com/watch?v=1CuTSluL7v4&t=4s){target=\\_blank} MIT Cryptoeconomic Systems 2020 talk by Web3 Foundation's Bill Laboon."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 11, "depth": 2, "title": "Bridging - BEEFY", "anchor": "bridging-beefy", "start_char": 11107, "end_char": 12509, "estimated_token_count": 241, "token_estimator": "heuristic-v1", "text": "## Bridging - BEEFY\n\nBridge Efficiency Enabling Finality Yielder (BEEFY) is a specialized protocol that extends the finality guarantees provided by GRANDPA. It is specifically designed to facilitate efficient bridging between Polkadot relay chains (such as Polkadot and Kusama) and external blockchains like Ethereum. While GRANDPA is well-suited for finalizing blocks within Polkadot, it has limitations when bridging external chains that weren't built with Polkadot's interoperability features in mind. BEEFY addresses these limitations by ensuring other networks can efficiently verify finality proofs.\n\nKey features of BEEFY include:\n\n- **Efficient finality proof verification**: BEEFY enables external networks to easily verify Polkadot finality proofs, ensuring seamless communication between chains.\n- **Merkle Mountain Ranges (MMR)**: This data structure is used to efficiently store and transmit proofs between chains, optimizing data storage and reducing transmission overhead.\n- **ECDSA signature schemes**: BEEFY uses ECDSA signatures, which are widely supported on Ethereum and other EVM-based chains, making integration with these ecosystems smoother.\n- **Light client optimization**: BEEFY reduces the computational burden on light clients by allowing them to check for a super-majority of validator votes rather than needing to process all validator signatures, improving performance."} -{"page_id": "reference-polkadot-hub-consensus-and-security-pos-consensus", "page_title": "Proof of Stake Consensus", "index": 12, "depth": 3, "title": "Additional Resources", "anchor": "additional-resources-4", "start_char": 12509, "end_char": 12753, "estimated_token_count": 58, "token_estimator": "heuristic-v1", "text": "### Additional Resources\n\nFor BEEFY technical definitions, constants, and formulas, see the [Bridge design (BEEFY)](https://spec.polkadot.network/sect-finality#sect-grandpa-beefy){target=\\_blank} section of the Polkadot Protocol Specification."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 12, "end_char": 876, "estimated_token_count": 184, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot is a next-generation blockchain protocol designed to support a multi-chain future by enabling secure communication and interoperability between different blockchains. Built as a Layer-0 protocol, Polkadot introduces innovations like application-specific Layer-1 chains ([parachains](/polkadot-protocol/architecture/parachains/){targe=\\_blank}), shared security through [Nominated Proof of Stake (NPoS)](/reference/glossary/#nominated-proof-of-stake-npos){target=\\_blank}, and cross-chain interactions via its native [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\\_blank}.\n\nThis guide covers key aspects of Polkadot’s architecture, including its high-level protocol structure, blockspace commoditization, and the role of its native token, DOT, in governance, staking, and resource allocation."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 1, "depth": 2, "title": "Polkadot 1.0", "anchor": "polkadot-10", "start_char": 876, "end_char": 2903, "estimated_token_count": 458, "token_estimator": "heuristic-v1", "text": "## Polkadot 1.0\n\nPolkadot 1.0 represents the state of Polkadot as of 2023, coinciding with the release of [Polkadot runtime v1.0.0](https://github.com/paritytech/polkadot/releases/tag/v1.0.0){target=\\_blank}. This section will focus on Polkadot 1.0, along with philosophical insights into network resilience and blockspace.\n\nAs a Layer-0 blockchain, Polkadot contributes to the multi-chain vision through several key innovations and initiatives, including:\n\n- **Application-specific Layer-1 blockchains (parachains)**: Polkadot's sharded network allows for parallel transaction processing, with shards that can have unique state transition functions, enabling custom-built L1 chains optimized for specific applications.\n\n- **Shared security and scalability**: L1 chains connected to Polkadot benefit from its [Nominated Proof of Stake (NPoS)](/reference/polkadot-hub/consensus-and-security/pos-consensus/#nominated-proof-of-stake){target=\\_blank} system, providing security out-of-the-box without the need to bootstrap their own.\n\n- **Secure interoperability**: Polkadot's native interoperability enables seamless data and value exchange between parachains. This interoperability can also be used outside of the ecosystem for bridging with external networks.\n\n- **Resilient infrastructure**: Decentralized and scalable, Polkadot ensures ongoing support for development and community initiatives via its on-chain [treasury](https://wiki.polkadot.com/learn/learn-polkadot-opengov-treasury/){target=\\_blank} and governance.\n\n- **Rapid L1 development**: The [Polkadot SDK](/reference/parachains/){target=\\_blank} allows fast, flexible creation and deployment of Layer-1 chains.\n\n- **Cultivating the next generation of Web3 developers**: Polkadot supports the growth of Web3 core developers through initiatives such as.\n\n - [Polkadot Blockchain Academy](https://polkadot.com/blockchain-academy){target=\\_blank}\n - [EdX courses](https://www.edx.org/school/web3x){target=\\_blank}\n - Rust and Substrate courses (coming soon)"} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 2, "depth": 3, "title": "High-Level Architecture", "anchor": "high-level-architecture", "start_char": 2903, "end_char": 4245, "estimated_token_count": 279, "token_estimator": "heuristic-v1", "text": "### High-Level Architecture\n\nPolkadot features a chain that serves as the central component of the system. This chain is depicted as a ring encircled by several parachains that are connected to it.\n\nAccording to Polkadot's design, any blockchain that can compile to WebAssembly (Wasm) and adheres to the Parachains Protocol becomes a parachain on the Polkadot network.\n\nHere’s a high-level overview of the Polkadot protocol architecture:\n\n![](/images/reference/polkadot-hub/consensus-and-security/relay-chain/relay-chain-01.webp){ style=\"background:white\" }\n\nParachains propose blocks to Polkadot validators, who check for availability and validity before finalizing them. With the relay chain providing security, collators—full nodes of parachains—can focus on their tasks without needing strong incentives.\n\nThe [Cross-Consensus Messaging Format (XCM)](/parachains/interoperability/get-started/){target=\\_blank} allows parachains to exchange messages freely, leveraging the chain's security for trust-free communication.\n\nIn order to interact with chains that want to use their own finalization process (e.g., Bitcoin), Polkadot has [bridges](/reference/parachains/interoperability/#bridges-connecting-external-networks){target=\\_blank} that offer two-way compatibility, meaning that transactions can be made between different parachains."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 3, "depth": 3, "title": "Polkadot's Additional Functionalities", "anchor": "polkadots-additional-functionalities", "start_char": 4245, "end_char": 6180, "estimated_token_count": 422, "token_estimator": "heuristic-v1", "text": "### Polkadot's Additional Functionalities\n\nHistorically, obtaining core slots on Polkadot chain relied upon crowdloans and auctions. Chain cores were leased through auctions for three-month periods, up to a maximum of two years. Crowdloans enabled users to securely lend funds to teams for lease deposits in exchange for pre-sale tokens, which is the only way to access slots on Polkadot 1.0. Auctions are now deprecated in favor of [coretime](/polkadot-protocol/architecture/system-chains/coretime/){target=\\_blank}.\n\nAdditionally, the chain handles [staking](https://wiki.polkadot.com/learn/learn-staking/){target=\\_blank}, [accounts](/reference/parachains/accounts/){target=\\_blank}, balances, and [governance](/reference/governance/){target=\\_blank}.\n\n#### Agile Coretime\n\nThe new and more efficient way of obtaining core on Polkadot is to go through the process of purchasing coretime.\n\n[Agile coretime](/reference/polkadot-hub/consensus-and-security/agile-coretime/){target=\\_blank} improves the efficient use of Polkadot's network resources and offers economic flexibility for developers, extending Polkadot's capabilities far beyond the original vision outlined in the [whitepaper](https://polkadot.com/papers/Polkadot-whitepaper.pdf){target=\\_blank}.\n\nIt enables parachains to purchase monthly \"bulk\" allocations of coretime (the time allocated for utilizing a core, measured in Polkadot relay chain blocks), ensuring heavy-duty parachains that can author a block every six seconds with [Asynchronous Backing](https://wiki.polkadot.com/learn/learn-async-backing/#asynchronous-backing){target=\\_blank} can reliably renew their coretime each month. Although six-second block times are now the default, parachains have the option of producing blocks less frequently.\n\nRenewal orders are prioritized over new orders, offering stability against price fluctuations and helping parachains budget more effectively for project costs."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 4, "depth": 3, "title": "Polkadot's Resilience", "anchor": "polkadots-resilience", "start_char": 6180, "end_char": 7464, "estimated_token_count": 253, "token_estimator": "heuristic-v1", "text": "### Polkadot's Resilience\n\nDecentralization is a vital component of blockchain networks, but it comes with trade-offs:\n\n- An overly decentralized network may face challenges in reaching consensus and require significant energy to operate.\n- Also, a network that achieves consensus quickly risks centralization, making it easier to manipulate or attack.\n\nA network should be decentralized enough to prevent manipulative or malicious influence. In this sense, decentralization is a tool for achieving resilience.\n\nPolkadot 1.0 currently achieves resilience through several strategies:\n\n- **Nominated Proof of Stake (NPoS)**: Ensures that the stake per validator is maximized and evenly distributed among validators.\n\n- **Decentralized nodes**: Designed to encourage operators to join the network. This program aims to expand and diversify the validators in the ecosystem who aim to become independent of the program during their term. Feel free to explore more about the program on the official [Decentralized Nodes](https://nodes.web3.foundation/){target=\\_blank} page.\n\n- **On-chain treasury and governance**: Known as [OpenGov](/reference/governance/){target=\\_blank}, this system allows every decision to be made through public referenda, enabling any token holder to cast a vote."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 5, "depth": 3, "title": "Polkadot's Blockspace", "anchor": "polkadots-blockspace", "start_char": 7464, "end_char": 9276, "estimated_token_count": 363, "token_estimator": "heuristic-v1", "text": "### Polkadot's Blockspace\n\nPolkadot 1.0’s design allows for the commoditization of blockspace.\n\nBlockspace is a blockchain's capacity to finalize and commit operations, encompassing its security, computing, and storage capabilities. Its characteristics can vary across different blockchains, affecting security, flexibility, and availability.\n\n- **Security**: Measures the robustness of blockspace in Proof of Stake (PoS) networks linked to the stake locked on validator nodes, the variance in stake among validators, and the total number of validators. It also considers social centralization (how many validators are owned by single operators) and physical centralization (how many validators run on the same service provider).\n\n- **Flexibility**: Reflects the functionalities and types of data that can be stored, with high-quality data essential to avoid bottlenecks in critical processes.\n\n- **Availability**: Indicates how easily users can access blockspace. It should be easily accessible, allowing diverse business models to thrive, ideally regulated by a marketplace based on demand and supplemented by options for \"second-hand\" blockspace.\n\nPolkadot is built on core blockspace principles, but there's room for improvement. Tasks like balance transfers, staking, and governance are managed on the relay chain.\n\nDelegating these responsibilities to [system chains](/polkadot-protocol/architecture/system-chains/){target=\\_blank} could enhance flexibility and allow the relay chain to concentrate on providing shared security and interoperability.\n\nFor more information about blockspace, watch [Robert Habermeier’s interview](https://www.youtube.com/watch?v=e1vISppPwe4){target=\\_blank} or read his [technical blog post](https://www.rob.tech/blog/polkadot-blockspace-over-blockchains/){target=\\_blank}."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 6, "depth": 2, "title": "DOT Token", "anchor": "dot-token", "start_char": 9276, "end_char": 9569, "estimated_token_count": 65, "token_estimator": "heuristic-v1", "text": "## DOT Token\n\nDOT is the native token of the Polkadot network, much like BTC for Bitcoin and Ether for the Ethereum blockchain. DOT has 10 decimals, uses the Planck base unit, and has a balance type of `u128`. The same is true for Kusama's KSM token with the exception of having 12 decimals."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 7, "depth": 3, "title": "Redenomination of DOT", "anchor": "redenomination-of-dot", "start_char": 9569, "end_char": 10121, "estimated_token_count": 112, "token_estimator": "heuristic-v1", "text": "### Redenomination of DOT\n \nPolkadot conducted a community poll, which ended on 27 July 2020 at block 888,888, to decide whether to redenominate the DOT token. The stakeholders chose to redenominate the token, changing the value of 1 DOT from 1e12 plancks to 1e10 plancks.\n\nImportantly, this did not affect the network's total number of base units (plancks); it only affects how a single DOT is represented. The redenomination became effective 72 hours after transfers were enabled, occurring at block 1,248,328 on 21 August 2020 around 16:50 UTC."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 8, "depth": 3, "title": "The Planck Unit", "anchor": "the-planck-unit", "start_char": 10121, "end_char": 10527, "estimated_token_count": 84, "token_estimator": "heuristic-v1", "text": "### The Planck Unit\n\nThe smallest unit of account balance on Polkadot SDK-based blockchains (such as Polkadot and Kusama) is called _Planck_, named after the Planck length, the smallest measurable distance in the physical universe.\n\nSimilar to how BTC's smallest unit is the Satoshi and ETH's is the Wei, Polkadot's native token DOT equals 1e10 Planck, while Kusama's native token KSM equals 1e12 Planck."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 9, "depth": 3, "title": "Uses for DOT", "anchor": "uses-for-dot", "start_char": 10527, "end_char": 11094, "estimated_token_count": 121, "token_estimator": "heuristic-v1", "text": "### Uses for DOT\n\nDOT serves three primary functions within the Polkadot network:\n\n- **Governance**: It is used to participate in the governance of the network.\n- **Staking**: DOT is staked to support the network's operation and security.\n- **Buying coretime**: Used to purchase coretime in-bulk or on-demand and access the chain to benefit from Polkadot's security and interoperability.\n\nAdditionally, DOT can serve as a transferable token. For example, DOT, held in the treasury, can be allocated to teams developing projects that benefit the Polkadot ecosystem."} -{"page_id": "reference-polkadot-hub-consensus-and-security-relay-chain", "page_title": "Overview of the Polkadot Relay Chain", "index": 10, "depth": 2, "title": "JAM and the Road Ahead", "anchor": "jam-and-the-road-ahead", "start_char": 11094, "end_char": 12458, "estimated_token_count": 239, "token_estimator": "heuristic-v1", "text": "## JAM and the Road Ahead\n\nThe Join-Accumulate Machine (JAM) represents a transformative redesign of Polkadot's core architecture, envisioned as the successor to the current relay chain. Unlike traditional blockchain architectures, JAM introduces a unique computational model that processes work through two primary functions:\n\n- **Join**: Handles data integration.\n- **Accumulate**: Folds computations into the chain's state.\n\nJAM removes many of the opinions and constraints of the current relay chain while maintaining its core security properties. Expected improvements include:\n\n- **Permissionless code execution**: JAM is designed to be more generic and flexible, allowing for permissionless code execution through services that can be deployed without governance approval.\n- **More effective block time utilization**: JAM's efficient pipeline processing model places the prior state root in block headers instead of the posterior state root, enabling more effective utilization of block time for computations.\n\nThis architectural evolution promises to enhance Polkadot's scalability and flexibility while maintaining robust security guarantees. JAM is planned to be rolled out to Polkadot as a single, complete upgrade rather than a stream of smaller updates. This approach seeks to minimize the developer overhead required to address any breaking changes."} -{"page_id": "reference-polkadot-hub-people-and-identity", "page_title": "People Chain", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 16, "end_char": 504, "estimated_token_count": 70, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPeople chain is a specialized parachain within the Polkadot ecosystem dedicated to secure, decentralized identity management. \n\nThis solution empowers users to create, control, and verify their digital identities without reliance on centralized authorities. By prioritizing user sovereignty and data privacy, People chain establishes a foundation for trusted interactions throughout the Polkadot ecosystem while returning control of personal information to individuals."} -{"page_id": "reference-polkadot-hub-people-and-identity", "page_title": "People Chain", "index": 1, "depth": 2, "title": "Identity Management System", "anchor": "identity-management-system", "start_char": 504, "end_char": 953, "estimated_token_count": 77, "token_estimator": "heuristic-v1", "text": "## Identity Management System\n\nPeople chain provides a comprehensive identity framework allowing users to:\n\n- Establish verifiable on-chain identities.\n- Control disclosure of personal information.\n- Receive verification from trusted registrars.\n- Link multiple accounts under a unified identity.\n\nUsers must reserve funds in a bond to store their information on chain. These funds are locked, not spent, and returned when the identity is cleared."} -{"page_id": "reference-polkadot-hub-people-and-identity", "page_title": "People Chain", "index": 2, "depth": 3, "title": "Sub-Identities", "anchor": "sub-identities", "start_char": 953, "end_char": 1224, "estimated_token_count": 52, "token_estimator": "heuristic-v1", "text": "### Sub-Identities\n\nThe platform supports hierarchical identity structures through sub-accounts:\n\n- Primary accounts can establish up to 100 linked sub-accounts.\n- Each sub-account maintains its own distinct identity.\n- All sub-accounts require a separate bond deposit."} -{"page_id": "reference-polkadot-hub-people-and-identity", "page_title": "People Chain", "index": 3, "depth": 2, "title": "Verification Process", "anchor": "verification-process", "start_char": 1224, "end_char": 1249, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Verification Process"} -{"page_id": "reference-polkadot-hub-people-and-identity", "page_title": "People Chain", "index": 4, "depth": 3, "title": "Judgment Requests", "anchor": "judgment-requests", "start_char": 1249, "end_char": 1598, "estimated_token_count": 68, "token_estimator": "heuristic-v1", "text": "### Judgment Requests\n\nAfter establishing an on-chain identity, users can request verification from [registrars](#registrars):\n\n1. Users specify the maximum fee they're willing to pay for judgment.\n2. Only registrars whose fees fall below this threshold can provide verification.\n3. Registrars assess the provided information and issue a judgment."} -{"page_id": "reference-polkadot-hub-people-and-identity", "page_title": "People Chain", "index": 5, "depth": 3, "title": "Judgment Classifications", "anchor": "judgment-classifications", "start_char": 1598, "end_char": 2385, "estimated_token_count": 150, "token_estimator": "heuristic-v1", "text": "### Judgment Classifications\n\nRegistrars can assign the following confidence levels to identity information:\n\n- **Unknown**: Default status; no judgment rendered yet.\n- **Reasonable**: Data appears valid but without formal verification (standard for most verified identities).\n- **Known good**: Information certified correct through formal verification (requires documentation; limited to registrars).\n- **Out of date**: Previously verified information that requires updating.\n- **Low quality**: Imprecise information requiring correction.\n- **Erroneous**: Incorrect information, potentially indicating fraudulent intent.\n\nA temporary \"Fee Paid\" status indicates judgment in progress. Both \"Fee Paid\" and \"Erroneous\" statuses lock identity information from modification until resolved."} -{"page_id": "reference-polkadot-hub-people-and-identity", "page_title": "People Chain", "index": 6, "depth": 3, "title": "Registrars", "anchor": "registrars", "start_char": 2385, "end_char": 3680, "estimated_token_count": 198, "token_estimator": "heuristic-v1", "text": "### Registrars\n\nRegistrars serve as trusted verification authorities within the People chain ecosystem. These entities validate user identities and provide attestations that build trust in the network.\n\n- Registrars set specific fees for their verification services.\n- They can specialize in verifying particular identity fields.\n- Verification costs vary based on complexity and thoroughness.\n\nWhen requesting verification, users specify their maximum acceptable fee. Only registrars whose fees fall below this threshold can provide judgment. Upon completing the verification process, the user pays the registrar's fee, and the registrar issues an appropriate confidence level classification based on their assessment.\n\nMultiple registrars operate across the Polkadot and People chain ecosystems, each with unique specializations and fee structures. To request verification:\n\n1. Research available registrars and their verification requirements.\n2. Contact your chosen registrar directly through their specified channels.\n3. Submit required documentation according to their verification process.\n4. Pay the associated verification fee.\n\nYou must contact specific registrars individually to request judgment. Each registrar maintains its own verification procedures and communication channels."} -{"page_id": "reference-polkadot-hub-people-and-identity", "page_title": "People Chain", "index": 7, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 3680, "end_char": 4750, "estimated_token_count": 257, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
    \n\n- External __Polkadot.js Guides about Identity__\n\n ---\n\n Step-by-step instructions for managing identities through the Polkadot.js interface, with practical examples and visual guides.\n\n [:octicons-arrow-right-24: Reference](https://wiki.polkadot.com/learn/learn-guides-identity/)\n\n- External __How to Set and Clear an Identity__\n\n ---\n\n Practical walkthrough covering identity setup and removal process on People chain.\n\n [:octicons-arrow-right-24: Reference](https://support.polkadot.network/support/solutions/articles/65000181981-how-to-set-and-clear-an-identity)\n\n- External __People Chain Runtime Implementation__\n\n ---\n\n Source code for the People chain runtime, detailing the technical architecture of decentralized identity management.\n\n [:octicons-arrow-right-24: Reference](https://github.com/polkadot-fellows/runtimes/tree/main/system-parachains/people)\n\n
    "} -{"page_id": "reference-tools-dedot", "page_title": "Dedot", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 9, "end_char": 445, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Introduction\n\n[Dedot](https://github.com/dedotdev/dedot){target=\\_blank} is a next-generation JavaScript client for Polkadot and Polkadot SDK-based blockchains. Designed to elevate the dApp development experience, Dedot is built and optimized to be lightweight and tree-shakable, offering precise types and APIs suggestions for individual Polkadot SDK-based blockchains and [ink! smart contracts](https://use.ink/){target=\\_blank}."} -{"page_id": "reference-tools-dedot", "page_title": "Dedot", "index": 1, "depth": 3, "title": "Key Features", "anchor": "key-features", "start_char": 445, "end_char": 1529, "estimated_token_count": 298, "token_estimator": "heuristic-v1", "text": "### Key Features\n\n- **Lightweight and tree-shakable**: No more bn.js or WebAssembly blobs, optimized for dapps bundle size.\n- **Fully typed API**: Comprehensive TypeScript support for seamless on-chain interaction and ink! smart contract integration.\n- **Multi-version JSON-RPC support**: Compatible with both [legacy](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md){target=\\_blank} and [new](https://paritytech.github.io/json-rpc-interface-spec/introduction.html){target=\\_blank} JSON-RPC APIs for broad ecosystem interoperability.\n- **Light client support**: Designed to work with light clients such as [Smoldot](https://github.com/smol-dot/smoldot){target=\\_blank}.\n- **Native TypeScript for scale codec**: Implements scale codec parsing directly in TypeScript without relying on custom wrappers.\n- **Wallet integration**: Works out-of-the-box with [@polkadot/extension-based](https://github.com/polkadot-js/extension?tab=readme-ov-file#api-interface){target=\\_blank} wallets.\n- **Familiar API design**: Similar API style to Polkadot.js for easy and fast migration."} -{"page_id": "reference-tools-dedot", "page_title": "Dedot", "index": 2, "depth": 2, "title": "Installation", "anchor": "installation", "start_char": 1529, "end_char": 2152, "estimated_token_count": 177, "token_estimator": "heuristic-v1", "text": "## Installation\n\nTo add Dedot to your project, use the following command:\n\n=== \"npm\"\n\n ```bash\n npm i dedot\n ```\n\n=== \"pnpm\"\n\n ```bash\n pnpm add dedot\n ```\n\n=== \"yarn\"\n\n ```bash\n yarn add dedot\n ```\n\nTo enable auto-completion/IntelliSense for individual chains, install the [`@dedot/chaintypes`](https://www.npmjs.com/package/@dedot/chaintypes){target=\\_blank} package as a development dependency:\n\n=== \"npm\"\n\n ```bash\n npm i -D @dedot/chaintypes\n ```\n\n=== \"pnpm\"\n\n ```bash\n pnpm add -D @dedot/chaintypes\n ```\n\n=== \"yarn\"\n\n ```bash\n yarn add -D @dedot/chaintypes\n ```"} -{"page_id": "reference-tools-dedot", "page_title": "Dedot", "index": 3, "depth": 2, "title": "Get Started", "anchor": "get-started", "start_char": 2152, "end_char": 2168, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Get Started"} -{"page_id": "reference-tools-dedot", "page_title": "Dedot", "index": 4, "depth": 3, "title": "Initialize a Client Instance", "anchor": "initialize-a-client-instance", "start_char": 2168, "end_char": 4242, "estimated_token_count": 522, "token_estimator": "heuristic-v1", "text": "### Initialize a Client Instance\n\nTo connect to and interact with different networks, Dedot provides two client options depending on your needs:\n\n- **[`DedotClient`](https://docs.dedot.dev/clients-and-providers/clients#dedotclient){target=\\_blank}**: Interacts with chains via the [new JSON-RPC APIs](https://paritytech.github.io/json-rpc-interface-spec/introduction.html){target=\\_blank}.\n- **[`LegacyClient`](https://docs.dedot.dev/clients-and-providers/clients#legacyclient){target=\\_blank}**: Interacts with chains via the [legacy JSON-RPC APIs](https://github.com/w3f/PSPs/blob/master/PSPs/drafts/psp-6.md){target=\\_blank}.\n\nUse the following snippets to connect to Polkadot using `DedotClient`:\n\n=== \"WebSocket\"\n\n ```typescript\n import { DedotClient, WsProvider } from 'dedot';\n import type { PolkadotApi } from '@dedot/chaintypes';\n\n // Initialize providers & clients\n const provider = new WsProvider('wss://rpc.polkadot.io');\n const client = await DedotClient.new(provider);\n\n ```\n\n=== \"Light Client (Smoldot)\"\n\n ```typescript\n import { DedotClient, SmoldotProvider } from 'dedot';\n import type { PolkadotApi } from '@dedot/chaintypes';\n import * as smoldot from 'smoldot';\n\n // import `polkadot` chain spec to connect to Polkadot\n import { polkadot } from '@substrate/connect-known-chains';\n\n // Start smoldot instance & initialize a chain\n const client = smoldot.start();\n const chain = await client.addChain({ chainSpec: polkadot });\n\n // Initialize providers & clients\n const provider = new SmoldotProvider(chain);\n const client = await DedotClient.new(provider);\n\n ```\n\nIf the node doesn't support new JSON-RPC APIs yet, you can connect to the network using the `LegacyClient`, which is built on top of the legacy JSON-RPC APIs.\n\n```typescript\nimport { LegacyClient, WsProvider } from 'dedot';\nimport type { PolkadotApi } from '@dedot/chaintypes';\n\nconst provider = new WsProvider('wss://rpc.polkadot.io');\nconst client = await LegacyClient.new(provider);\n\n```"} -{"page_id": "reference-tools-dedot", "page_title": "Dedot", "index": 5, "depth": 3, "title": "Enable Type and API Suggestions", "anchor": "enable-type-and-api-suggestions", "start_char": 4242, "end_char": 5662, "estimated_token_count": 377, "token_estimator": "heuristic-v1", "text": "### Enable Type and API Suggestions\n\nIt is recommended to specify the `ChainApi` interface (e.g., `PolkadotApi` in the example in the previous section) of the chain you want to interact with. This enables type and API suggestions/autocompletion for that particular chain (via IntelliSense). If you don't specify a `ChainApi` interface, a default `SubstrateApi` interface will be used.\n\n```typescript\nimport { DedotClient, WsProvider } from 'dedot';\nimport type { PolkadotApi, KusamaApi } from '@dedot/chaintypes';\n\nconst polkadotClient = await DedotClient.new(\n new WsProvider('wss://rpc.polkadot.io')\n);\nconst kusamaClient = await DedotClient.new(\n new WsProvider('wss://kusama-rpc.polkadot.io')\n);\nconst genericClient = await DedotClient.new(\n new WsProvider('ws://localhost:9944')\n);\n\n```\n\nIf you don't find the `ChainApi` for the network you're working with in [the list](https://github.com/dedotdev/chaintypes?tab=readme-ov-file#supported-networks){target=\\_blank}, you can generate the `ChainApi` (types and APIs) using the built-in [`dedot` cli](https://docs.dedot.dev/cli){target=\\_blank}.\n\n```bash\n# Generate ChainApi interface for Polkadot network via rpc endpoint: wss://rpc.polkadot.io\nnpx dedot chaintypes -w wss://rpc.polkadot.io\n```\n\nOr open a pull request to add your favorite network to the [`@dedot/chaintypes`](https://github.com/dedotdev/chaintypes){target=\\_blank} repo."} -{"page_id": "reference-tools-dedot", "page_title": "Dedot", "index": 6, "depth": 3, "title": "Read On-Chain Data", "anchor": "read-on-chain-data", "start_char": 5662, "end_char": 6993, "estimated_token_count": 348, "token_estimator": "heuristic-v1", "text": "### Read On-Chain Data\n\nDedot provides several ways to read data from the chain:\n\n- **Access runtime constants**: Use the syntax `client.consts..` to inspect runtime constants (parameter types).\n\n ```typescript\n const ss58Prefix = client.consts.system.ss58Prefix;\n console.log('Polkadot ss58Prefix:', ss58Prefix);\n\n ```\n\n- **Storage queries**: Use the syntax `client.query..` to query on-chain storage.\n\n ```typescript\n const balance = await client.query.system.account('INSERT_ADDRESS');\n console.log('Balance:', balance.data.free);\n\n ```\n\n- **Subscribe to storage changes**:\n\n ```typescript\n const unsub = await client.query.system.number((blockNumber) => {\n console.log(`Current block number: ${blockNumber}`);\n });\n\n ```\n\n- **Call Runtime APIs**: Use the syntax `client.call..` to execute Runtime APIs.\n\n ```typescript\n const metadata = await client.call.metadata.metadataAtVersion(15);\n console.log('Metadata V15', metadata);\n\n ```\n\n- **Watch on-chain events**: Use the syntax `client.events..` to access pallet events.\n \n ```typescript\n const unsub = await client.events.system.NewAccount.watch((events) => {\n console.log('New Account Created', events);\n });\n\n ```"} -{"page_id": "reference-tools-dedot", "page_title": "Dedot", "index": 7, "depth": 3, "title": "Sign and Send Transactions", "anchor": "sign-and-send-transactions", "start_char": 6993, "end_char": 8719, "estimated_token_count": 439, "token_estimator": "heuristic-v1", "text": "### Sign and Send Transactions\n\nSign the transaction using `IKeyringPair` from Keyring ([`@polkadot/keyring`](https://polkadot.js.org/docs/keyring/start/sign-verify/){target=\\_blank}) and send the transaction.\n\n```typescript\nimport { cryptoWaitReady } from '@polkadot/util-crypto';\nimport { Keyring } from '@polkadot/keyring';\n// Setup keyring\nawait cryptoWaitReady();\nconst keyring = new Keyring({ type: 'sr25519' });\nconst alice = keyring.addFromUri('//Alice');\n// Send transaction\nconst unsub = await client.tx.balances\n .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n)\n .signAndSend(alice, async ({ status }) => {\n console.log('Transaction status', status.type);\n if (status.type === 'BestChainBlockIncluded') {\n console.log(`Transaction is included in best block`);\n }\n if (status.type === 'Finalized') {\n console.log(\n `Transaction completed at block hash ${status.value.blockHash}`\n );\n await unsub();\n }\n });\n\n```\n\nYou can also use `Signer` from wallet extensions:\n\n```typescript\nconst injected = await window.injectedWeb3['polkadot-js'].enable('My dApp');\nconst account = (await injected.accounts.get())[0];\nconst signer = injected.signer;\nconst unsub = await client.tx.balances\n .transferKeepAlive('INSERT_DEST_ADDRESS', 2_000_000_000_000n)\n .signAndSend(account.address, { signer }, async ({ status }) => {\n console.log('Transaction status', status.type);\n if (status.type === 'BestChainBlockIncluded') {\n console.log(`Transaction is included in best block`);\n }\n if (status.type === 'Finalized') {\n console.log(\n `Transaction completed at block hash ${status.value.blockHash}`\n );\n await unsub();\n }\n });\n\n```"} -{"page_id": "reference-tools-dedot", "page_title": "Dedot", "index": 8, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 8719, "end_char": 8855, "estimated_token_count": 36, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor more detailed information about Dedot, check the [official documentation](https://dedot.dev/){target=\\_blank}."} -{"page_id": "reference-tools-light-clients", "page_title": "Light Clients", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 17, "end_char": 994, "estimated_token_count": 167, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nLight clients enable secure and efficient blockchain interaction without running a full node. They provide a trust-minimized alternative to JSON-RPC by verifying data through cryptographic proofs rather than blindly trusting remote nodes.\n\nThis guide covers:\n\n- What light clients are and how they work.\n- Their advantages compared to full nodes and JSON-RPC.\n- Available implementations in the Polkadot ecosystem.\n- How to use light clients in your applications.\n\nLight clients are particularly valuable for resource-constrained environments and applications requiring secure, decentralized blockchain access without the overhead of maintaining full nodes.\n\n!!!note \"Light node or light client?\"\n The terms _light node_ and _light client_ are interchangeable. Both refer to a blockchain client that syncs without downloading the entire blockchain state. All nodes in a blockchain network are fundamentally clients, engaging in peer-to-peer communication."} -{"page_id": "reference-tools-light-clients", "page_title": "Light Clients", "index": 1, "depth": 2, "title": "Light Clients Workflow", "anchor": "light-clients-workflow", "start_char": 994, "end_char": 2625, "estimated_token_count": 359, "token_estimator": "heuristic-v1", "text": "## Light Clients Workflow\n\nUnlike JSON-RPC interfaces, where an application must maintain a list of providers or rely on a single node, light clients are not limited to or dependent on a single node. They use cryptographic proofs to verify the blockchain's state, ensuring it is up-to-date and accurate. By verifying only block headers, light clients avoid syncing the entire state, making them ideal for resource-constrained environments.\n\n```mermaid\nflowchart LR\nDAPP([dApp])-- Query Account Info -->LC([Light Client])\nLC -- Request --> FN(((Full Node)))\nLC -- Response --> DAPP\nFN -- Response (validated via Merkle proof) --> LC\n```\n\nIn the diagram above, the decentralized application queries on-chain account information through the light client. The light client runs as part of the application and requires minimal memory and computational resources. It uses Merkle proofs to verify the state retrieved from a full node in a trust-minimized manner. Polkadot-compatible light clients utilize [warp syncing](https://spec.polkadot.network/sect-lightclient#sect-sync-warp-lightclient){target=\\_blank}, which downloads only block headers.\n\nLight clients can quickly verify the blockchain's state, including [GRANDPA finality](/polkadot-protocol/glossary#grandpa){target=\\_blank} justifications.\n\n!!!note \"What does it mean to be trust-minimized?\"\n _Trust-minimized_ means that the light client does not need to fully trust the full node from which it retrieves the state. This is achieved through the use of Merkle proofs, which allow the light client to verify the correctness of the state by checking the Merkle tree root."} -{"page_id": "reference-tools-light-clients", "page_title": "Light Clients", "index": 2, "depth": 2, "title": "JSON-RPC and Light Client Comparison", "anchor": "json-rpc-and-light-client-comparison", "start_char": 2625, "end_char": 4478, "estimated_token_count": 442, "token_estimator": "heuristic-v1", "text": "## JSON-RPC and Light Client Comparison\n\nAnother common method of communication between a user interface (UI) and a node is through the JSON-RPC protocol. Generally, the UI retrieves information from the node, fetches network or [pallet](/polkadot-protocol/glossary#pallet){target=\\_blank} data, and interacts with the blockchain. This is typically done in one of two ways:\n\n- **User-controlled nodes**: The UI connects to a node client installed on the user's machine.\n - These nodes are secure, but installation and maintenance can be inconvenient.\n- **Publicly accessible nodes**: The UI connects to a third-party-owned publicly accessible node client.\n - These nodes are convenient but centralized and less secure. Applications must maintain a list of backup nodes in case the primary node becomes unavailable.\n\nWhile light clients still communicate with [full nodes](/polkadot-protocol/glossary#full-node), they offer significant advantages for applications requiring a secure alternative to running a full node:\n\n| Full Node | Light Client |\n| :---------------------------------------------------------------------------------------------: | :------------------------------------------------------------: |\n| Fully verifies all blocks of the chain | Verifies only the authenticity of blocks |\n| Stores previous block data and the chain's storage in a database | Does not require a database |\n| Installation, maintenance, and execution are resource-intensive and require technical expertise | No installation is typically included as part of the application |"} -{"page_id": "reference-tools-light-clients", "page_title": "Light Clients", "index": 3, "depth": 2, "title": "Using Light Clients", "anchor": "using-light-clients", "start_char": 4478, "end_char": 4799, "estimated_token_count": 78, "token_estimator": "heuristic-v1", "text": "## Using Light Clients\n\nThe [`smoldot`](https://github.com/smol-dot/smoldot){target=\\_blank} client is the cornerstone of light client implementation for Polkadot SDK-based chains. It provides the primitives needed to build light clients and is also integrated into libraries such as [PAPI](#papi-light-client-support)."} -{"page_id": "reference-tools-light-clients", "page_title": "Light Clients", "index": 4, "depth": 3, "title": "PAPI Light Client Support", "anchor": "papi-light-client-support", "start_char": 4799, "end_char": 5131, "estimated_token_count": 82, "token_estimator": "heuristic-v1", "text": "### PAPI Light Client Support\n\nThe [Polkadot API (PAPI)](/develop/toolkit/api-libraries/papi){target=\\_blank} library natively supports light client configurations powered by [`smoldot`](https://github.com/smol-dot/smoldot){target=\\_blank}. This allows developers to connect to multiple chains simultaneously using a light client."} -{"page_id": "reference-tools-light-clients", "page_title": "Light Clients", "index": 5, "depth": 3, "title": "Substrate Connect - Browser Extension", "anchor": "substrate-connect-browser-extension", "start_char": 5131, "end_char": 5902, "estimated_token_count": 139, "token_estimator": "heuristic-v1", "text": "### Substrate Connect - Browser Extension\n\nThe [Substrate Connect browser extension](https://www.npmjs.com/package/@substrate/connect-extension-protocol){target=\\_blank} enables end-users to interact with applications connected to multiple blockchains or to connect their own blockchains to supported applications.\n\nEstablishing a sufficient number of peers can be challenging due to browser limitations on WebSocket connections from HTTPS pages, as many nodes require TLS. The Substrate Connect browser extension addresses this limitation by keeping chains synced in the background, enabling faster application performance.\n\nSubstrate Connect automatically detects whether the user has the extension installed. If not, an in-page Wasm light client is created for them."} -{"page_id": "reference-tools-light-clients", "page_title": "Light Clients", "index": 6, "depth": 2, "title": "Resources", "anchor": "resources", "start_char": 5902, "end_char": 6490, "estimated_token_count": 163, "token_estimator": "heuristic-v1", "text": "## Resources\n\n- [What is a light client and why you should care?](https://medium.com/paritytech/what-is-a-light-client-and-why-you-should-care-75f813ae2670){target=\\_blank}\n- [Introducing Substrate Connect: Browser-Based Light Clients for Connecting to Substrate Chains](https://www.parity.io/blog/introducing-substrate-connect){target=\\_blank}\n- [Substrate Connect GitHub Repository](https://github.com/paritytech/substrate-connect/tree/master/projects/extension){target=\\_blank}\n- [Light Clients - Polkadot Specification](https://spec.polkadot.network/sect-lightclient){target=\\_blank}"} -{"page_id": "reference-tools-moonwall", "page_title": "E2E Testing with Moonwall", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 29, "end_char": 786, "estimated_token_count": 112, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nMoonwall is an end-to-end testing framework designed explicitly for Polkadot SDK-based blockchain networks. It addresses one of the most significant challenges in blockchain development: managing complex test environments and network configurations.\n\nMoonwall consolidates this complexity by providing the following:\n\n- A centralized configuration management system that explicitly defines all network parameters.\n- A standardized approach to environment setup across different Substrate-based chains.\n- Built-in utilities for common testing scenarios and network interactions.\n\nDevelopers can focus on writing meaningful tests rather than managing infrastructure complexities or searching through documentation for configuration options."} -{"page_id": "reference-tools-moonwall", "page_title": "E2E Testing with Moonwall", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 786, "end_char": 1110, "estimated_token_count": 116, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have the following installed:\n\n- [Node.js](https://nodejs.org/en/){target=\\_blank} (version 20.10 or higher).\n- A package manager such as [npm](https://www.npmjs.com/){target=\\_blank}, [yarn](https://yarnpkg.com/){target=\\_blank}, or [pnpm](https://pnpm.io/){target=\\_blank}."} -{"page_id": "reference-tools-moonwall", "page_title": "E2E Testing with Moonwall", "index": 2, "depth": 2, "title": "Install Moonwall", "anchor": "install-moonwall", "start_char": 1110, "end_char": 1450, "estimated_token_count": 63, "token_estimator": "heuristic-v1", "text": "## Install Moonwall\n\nMoonwall can be installed globally for system-wide access or locally within specific projects. This section covers both installation methods.\n\n!!! tip\n This documentation corresponds to Moonwall version `5.15.0`. To avoid compatibility issues with the documented features, ensure you're using the matching version."} -{"page_id": "reference-tools-moonwall", "page_title": "E2E Testing with Moonwall", "index": 3, "depth": 3, "title": "Global Installation", "anchor": "global-installation", "start_char": 1450, "end_char": 1955, "estimated_token_count": 132, "token_estimator": "heuristic-v1", "text": "### Global Installation\n\nGlobal installation provides system-wide access to the Moonwall CLI, making it ideal for developers working across multiple blockchain projects. Install it by running one of the following commands:\n\n=== \"npm\"\n\n ```bash\n npm install -g @moonwall/cli@5.15.0\n ```\n\n=== \"pnpm\"\n\n ```bash\n pnpm -g install @moonwall/cli@5.15.0\n ```\n\n=== \"yarn\"\n\n ```bash\n yarn global add @moonwall/cli@5.15.0\n ```\n\nNow, you can run the `moonwall` command from your terminal."} -{"page_id": "reference-tools-moonwall", "page_title": "E2E Testing with Moonwall", "index": 4, "depth": 3, "title": "Local Installation", "anchor": "local-installation", "start_char": 1955, "end_char": 2448, "estimated_token_count": 134, "token_estimator": "heuristic-v1", "text": "### Local Installation\n\nLocal installation is recommended for better dependency management and version control within a specific project. First, initialize your project:\n\n```bash\nmkdir my-moonwall-project\ncd my-moonwall-project\nnpm init -y\n```\n\nThen, install it as a local dependency:\n\n=== \"npm\"\n\n ```bash\n npm install @moonwall/cli@5.15.0\n ```\n\n=== \"pnpm\"\n\n ```bash\n pnpm install @moonwall/cli@5.15.0\n ```\n\n=== \"yarn\"\n\n ```bash\n yarn add @moonwall/cli@5.15.0\n ```"} -{"page_id": "reference-tools-moonwall", "page_title": "E2E Testing with Moonwall", "index": 5, "depth": 2, "title": "Initialize Moonwall", "anchor": "initialize-moonwall", "start_char": 2448, "end_char": 5873, "estimated_token_count": 767, "token_estimator": "heuristic-v1", "text": "## Initialize Moonwall\n\nThe `moonwall init` command launches an interactive wizard to create your configuration file:\n\n```bash\nmoonwall init\n```\n\nDuring setup, you will see prompts for the following parameters:\n\n- **`label`**: Identifies your test configuration.\n- **`global timeout`**: Maximum time (ms) for test execution.\n- **`environment name`**: Name for your testing environment.\n- **`network foundation`**: Type of blockchain environment to use.\n- **`tests directory`**: Location of your test files.\n\nSelect `Enter` to accept defaults or input custom values. You should see something like this:\n\n
    \n moonwall init\n ✔ Provide a label for the config file moonwall_config\n ✔ Provide a global timeout value 30000\n ✔ Provide a name for this environment default_env\n ✔ What type of network foundation is this? dev\n ✔ Provide the path for where tests for this environment are kept tests/\n ? Would you like to generate this config? (no to restart from beginning) (Y/n)\n
    \n\nThe wizard generates a `moonwall.config` file:\n\n```json\n{\n \"label\": \"moonwall_config\",\n \"defaultTestTimeout\": 30000,\n \"environments\": [\n {\n \"name\": \"default_env\",\n \"testFileDir\": [\"tests/\"],\n \"foundation\": {\n \"type\": \"dev\"\n }\n }\n ]\n}\n\n```\n\nThe default configuration requires specific details about your blockchain node and test requirements:\n\n- The `foundation` object defines how your test blockchain node will be launched and managed. The dev foundation, which runs a local node binary, is used for local development.\n\n For more information about available options, check the [Foundations](https://moonsong-labs.github.io/moonwall/guide/intro/foundations.html){target=\\_blank} section.\n\n- The `connections` array specifies how your tests will interact with the blockchain node. This typically includes provider configuration and endpoint details.\n\n A provider is a tool that allows you or your application to connect to a blockchain network and simplifies the low-level details of the process. A provider handles submitting transactions, reading state, and more. For more information on available providers, check the [Providers supported](https://moonsong-labs.github.io/moonwall/guide/intro/providers.html#providers-supported){target=\\_blank} page in the Moonwall documentation.\n\nHere's a complete configuration example for testing a local node using Polkadot.js as a provider:\n\n```json\n{\n \"label\": \"moonwall_config\",\n \"defaultTestTimeout\": 30000,\n \"environments\": [\n {\n \"name\": \"default_env\",\n \"testFileDir\": [\"tests/\"],\n \"foundation\": {\n \"launchSpec\": [\n {\n \"binPath\": \"./node-template\",\n \"newRpcBehaviour\": true,\n \"ports\": { \"rpcPort\": 9944 }\n }\n ],\n \"type\": \"dev\"\n },\n \"connections\": [\n {\n \"name\": \"myconnection\",\n \"type\": \"polkadotJs\",\n \"endpoints\": [\"ws://127.0.0.1:9944\"]\n }\n ]\n }\n ]\n}\n\n```"} -{"page_id": "reference-tools-moonwall", "page_title": "E2E Testing with Moonwall", "index": 6, "depth": 2, "title": "Writing Tests", "anchor": "writing-tests", "start_char": 5873, "end_char": 8602, "estimated_token_count": 649, "token_estimator": "heuristic-v1", "text": "## Writing Tests\n\nMoonwall uses the [`describeSuite`](https://github.com/Moonsong-Labs/moonwall/blob/7568048c52e9f7844f38fb4796ae9e1b9205fdaa/packages/cli/src/lib/runnerContext.ts#L65){target=\\_blank} function to define test suites, like using [Mocha](https://mochajs.org/){target=\\_blank}. Each test suite requires the following:\n\n- **`id`**: Unique identifier for the suite.\n- **`title`**: Descriptive name for the suite.\n- **`foundationMethods`**: Specifies the testing environment (e.g., `dev` for local node testing).\n- **`testCases`**: A callback function that houses the individual test cases of this suite.\n\nThe following example shows how to test a balance transfer between two accounts:\n\n```ts\nimport '@polkadot/api-augment';\nimport { describeSuite, expect } from '@moonwall/cli';\nimport { Keyring } from '@polkadot/api';\n\ndescribeSuite({\n id: 'D1',\n title: 'Demo suite',\n foundationMethods: 'dev',\n testCases: ({ it, context, log }) => {\n it({\n id: 'T1',\n title: 'Test Case',\n test: async () => {\n // Set up polkadot.js API and testing accounts\n let api = context.polkadotJs();\n let alice = new Keyring({ type: 'sr25519' }).addFromUri('//Alice');\n let charlie = new Keyring({ type: 'sr25519' }).addFromUri('//Charlie');\n\n // Query Charlie's account balance before transfer\n const balanceBefore = (await api.query.system.account(charlie.address))\n .data.free;\n\n // Before transfer, Charlie's account balance should be 0\n expect(balanceBefore.toString()).toEqual('0');\n log('Balance before: ' + balanceBefore.toString());\n\n // Transfer from Alice to Charlie\n const amount = 1000000000000000;\n await api.tx.balances\n .transferAllowDeath(charlie.address, amount)\n .signAndSend(alice);\n\n // Wait for the transaction to be included in a block.\n // This is necessary because the balance is not updated immediately.\n // Block time is 6 seconds.\n await new Promise((resolve) => setTimeout(resolve, 6000));\n\n // Query Charlie's account balance after transfer\n const balanceAfter = (await api.query.system.account(charlie.address))\n .data.free;\n\n // After transfer, Charlie's account balance should be 1000000000000000\n expect(balanceAfter.toString()).toEqual(amount.toString());\n log('Balance after: ' + balanceAfter.toString());\n },\n });\n },\n});\n\n```\n\nThis test demonstrates several key concepts:\n\n- Initializing the Polkadot.js API through Moonwall's context and setting up test accounts.\n- Querying on-chain state.\n- Executing transactions.\n- Waiting for block inclusion.\n- Verifying results using assertions."} -{"page_id": "reference-tools-moonwall", "page_title": "E2E Testing with Moonwall", "index": 7, "depth": 2, "title": "Running the Tests", "anchor": "running-the-tests", "start_char": 8602, "end_char": 10012, "estimated_token_count": 426, "token_estimator": "heuristic-v1", "text": "## Running the Tests\n\nExecute your tests using the `test` Moonwall CLI command. For the default environment setup run:\n\n```bash\nmoonwall test default_env -c moonwall.config\n```\n\nThe test runner will output detailed results showing:\n\n- Test suite execution status.\n- Individual test case results.\n- Execution time.\n- Detailed logs and error messages (if any).\n\nExample output:\n
    \n moonwall test default_env -c moonwall.config\n stdout | tests/test1.ts > 🗃️ D1 Demo suite > 📁 D1T1 Test Case\n 2025-01-21T19:27:55.624Z test:default_env Balance before: 0\n \n stdout | tests/test1.ts > 🗃️ D1 Demo suite > 📁 D1T1 Test Case\n 2025-01-21T19:28:01.637Z test:default_env Balance after: 1000000000000000\n \n ✓ default_env tests/test1.ts (1 test) 6443ms\n ✓ 🗃️ D1 Demo suite > 📁 D1T1 Test Case 6028ms\n \n Test Files 1 passed (1)\n Tests 1 passed (1)\n Start at 16:27:53\n Duration 7.95s (transform 72ms, setup 0ms, collect 1.31s, tests 6.44s, environment 0ms, prepare 46ms)\n \n ✅ All tests passed\n
    "} -{"page_id": "reference-tools-moonwall", "page_title": "E2E Testing with Moonwall", "index": 8, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 10012, "end_char": 10240, "estimated_token_count": 54, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor a comprehensive guide to Moonwall's full capabilities, available configurations, and advanced usage, see the official [Moonwall](https://moonsong-labs.github.io/moonwall/){target=\\_blank} documentation."} -{"page_id": "reference-tools-omninode", "page_title": "Polkadot Omni Node", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 22, "end_char": 985, "estimated_token_count": 205, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe [`polkadot-omni-node`](https://crates.io/crates/polkadot-omni-node/0.7.0){target=\\_blank} crate is a versatile, pre-built binary designed to simplify running parachains in the Polkadot ecosystem. Unlike traditional node binaries that are tightly coupled to specific runtime code, the `polkadot-omni-node` operates using an external [chain specification](/polkadot-protocol/glossary#chain-specification){target=\\_blank} file, allowing it to adapt dynamically to different parachains.\n\nThis approach enables it to act as a white-labeled node binary, capable of running most parachains that do not require custom node-level logic or extensions. Developers can leverage this flexibility to test, deploy, or operate parachain nodes without maintaining a dedicated codebase for each network.\n\nThis guide provides step-by-step instructions for installing the `polkadot-omni-node`, obtaining a chain specification, and spinning up a parachain node."} -{"page_id": "reference-tools-omninode", "page_title": "Polkadot Omni Node", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 985, "end_char": 1307, "estimated_token_count": 87, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore getting started, ensure you have the following prerequisites:\n\n- **[Rust](https://rust-lang.org/tools/install/){target=\\_blank}**: Required to build and install the `polkadot-omni-node` binary.\n\nEnsure Rust's `cargo` command is available in your terminal by running:\n\n```bash\ncargo --version\n```"} -{"page_id": "reference-tools-omninode", "page_title": "Polkadot Omni Node", "index": 2, "depth": 2, "title": "Install Polkadot Omni Node", "anchor": "install-polkadot-omni-node", "start_char": 1307, "end_char": 1745, "estimated_token_count": 107, "token_estimator": "heuristic-v1", "text": "## Install Polkadot Omni Node\n\nTo install `polkadot-omni-node` globally using `cargo`, run:\n\n```bash\ncargo install --locked polkadot-omni-node@0.7.0\n```\n\nThis command downloads and installs version 0.7.0 of the binary, making it available system-wide.\n\nTo confirm the installation, run:\n\n```bash\npolkadot-omni-node --version\n```\n\nYou should see the installed version number printed to the terminal, confirming a successful installation."} -{"page_id": "reference-tools-omninode", "page_title": "Polkadot Omni Node", "index": 3, "depth": 2, "title": "Obtain Chain Specifications", "anchor": "obtain-chain-specifications", "start_char": 1745, "end_char": 2581, "estimated_token_count": 202, "token_estimator": "heuristic-v1", "text": "## Obtain Chain Specifications\n\nThe `polkadot-omni-node` binary uses a chain specification file to configure and launch a parachain node. This file defines the parachain's genesis state and network settings.\n\nThe most common source for official chain specifications is the [`paritytech/chainspecs`](https://github.com/paritytech/chainspecs){target=\\_blank} repository. These specifications are also browsable in a user-friendly format via the [Chainspec Collection](https://paritytech.github.io/chainspecs/){target=\\_blank} website.\n\nTo obtain a chain specification:\n\n1. Visit the [Chainspec Collection](https://paritytech.github.io/chainspecs/){target=\\_blank} website.\n2. Find the parachain you want to run.\n3. Click the chain spec to open it.\n4. Copy the JSON content and save it locally as a `.json` file, e.g., `chain_spec.json`."} -{"page_id": "reference-tools-omninode", "page_title": "Polkadot Omni Node", "index": 4, "depth": 2, "title": "Run a Parachain Full Node", "anchor": "run-a-parachain-full-node", "start_char": 2581, "end_char": 3712, "estimated_token_count": 241, "token_estimator": "heuristic-v1", "text": "## Run a Parachain Full Node\n\nOnce you've installed `polkadot-omni-node` and saved the appropriate chain specification file, you can start a full node for your chosen parachain.\n\nTo see all available flags and configuration options, run:\n\n```bash\npolkadot-omni-node --help\n```\n\nTo launch the node, run the following command, replacing `./INSERT_PARACHAIN_CHAIN_SPEC.json` with the actual path to your saved chain spec file.\n\nThis command will:\n\n- Load the chain specification.\n- Initialize the node using the provided network configuration.\n- Begin syncing with the parachain network.\n\n```bash\npolkadot-omni-node --chain ./INSERT_PARACHAIN_CHAIN_SPEC.json --sync warp\n```\n\n- The `--chain` flag tells the `polkadot-omni-node` which parachain to run by pointing to its chain specification file.\n- The `--sync warp` flag enables warp sync, allowing the node to quickly catch up to the latest finalized state. Historical blocks are fetched in the background as the node continues operating.\n\nOnce started, the node will begin connecting to peers and syncing with the network. You’ll see logs in your terminal reflecting its progress."} -{"page_id": "reference-tools-omninode", "page_title": "Polkadot Omni Node", "index": 5, "depth": 2, "title": "Interact with the Node", "anchor": "interact-with-the-node", "start_char": 3712, "end_char": 4274, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "## Interact with the Node\n\nBy default, `polkadot-omni-node` exposes a WebSocket endpoint at `ws://localhost:9944`, which you can use to interact with the running node. You can connect using:\n\n- **[Polkadot.js Apps](https://polkadot.js.org/apps/#/explorer){target=\\_blank}**: A web-based interface for exploring and interacting with Polkadot SDK-based chains.\n- Custom scripts using compatible [libraries](/develop/toolkit/api-libraries/){target=\\_blank}.\n\nOnce connected, you can review blocks, call extrinsics, inspect storage, and interact with the runtime."} -{"page_id": "reference-tools-omninode", "page_title": "Polkadot Omni Node", "index": 6, "depth": 2, "title": "Parachain Compatibility", "anchor": "parachain-compatibility", "start_char": 4274, "end_char": 5088, "estimated_token_count": 170, "token_estimator": "heuristic-v1", "text": "## Parachain Compatibility\n\nThe `polkadot-omni-node` is designed to work with most parachains out of the box; however, your parachain's runtime must meet specific requirements and follow certain conventions to be compatible. This section outlines what your runtime needs to implement and configure to work seamlessly with the `polkadot-omni-node`:\n\n- Your runtime must implement the required runtime APIs (see below).\n- Your runtime must include and configure the required pallets.\n\nThe [`parachain-template`](https://github.com/paritytech/polkadot-sdk-parachain-template/tree/v0.0.4){target=_blank} provides a complete reference implementation that is fully compatible with the `polkadot-omni-node`. You can use it as a starting point or reference for ensuring your runtime meets all compatibility requirements."} -{"page_id": "reference-tools-omninode", "page_title": "Polkadot Omni Node", "index": 7, "depth": 3, "title": "Required Runtime APIs", "anchor": "required-runtime-apis", "start_char": 5088, "end_char": 6424, "estimated_token_count": 295, "token_estimator": "heuristic-v1", "text": "### Required Runtime APIs\n\nYour parachain runtime must implement the following runtime APIs for the `polkadot-omni-node` to function properly:\n\n- **GetParachainInfo Runtime API**: The omni-node requires the [`GetParachainInfo`](https://paritytech.github.io/polkadot-sdk/master/cumulus_primitives_core/trait.GetParachainInfo.html){target=\\_blank} runtime API to identify and configure the parachain correctly. This API provides the parachain ID to the node.\n\n ```rust title=\"runtime/src/apis.rs\"\n impl cumulus_primitives_core::GetParachainInfo for Runtime {\n fn parachain_id() -> cumulus_primitives_core::ParaId {\n // Return your parachain ID\n ParachainInfo::parachain_id()\n }\n }\n ```\n\n- **Aura Runtime API**: For consensus, the `polkadot-omni-node` expects the [Aura runtime API](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/runtime/apis/trait.AuraApi.html){target=\\_blank} to be implemented.\n\n ```rust title=\"runtime/src/apis.rs\"\n impl sp_consensus_aura::AuraApi for Runtime {\n fn slot_duration() -> sp_consensus_aura::SlotDuration {\n sp_consensus_aura::SlotDuration::from_millis(SLOT_DURATION)\n }\n\n fn authorities() -> Vec {\n Aura::authorities().into_inner()\n }\n }\n ```"} -{"page_id": "reference-tools-omninode", "page_title": "Polkadot Omni Node", "index": 8, "depth": 3, "title": "Required Pallets", "anchor": "required-pallets", "start_char": 6424, "end_char": 8913, "estimated_token_count": 566, "token_estimator": "heuristic-v1", "text": "### Required Pallets\n\nYour runtime must include and properly configure the following pallets:\n\n- **System Pallet**: The System pallet ([`frame-system`](https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_frame/prelude/frame_system/index.html){target=\\_blank}) is fundamental and must be configured with appropriate types.\n\n ```rust title=\"runtime/src/lib.rs\"\n #[frame_support::runtime]\n impl frame_system::Config for Runtime {\n type Block = Block;\n type BlockNumber = BlockNumber;\n // ... other configurations\n }\n\n // Must be named \"System\" for omni-node compatibility\n pub type System = frame_system::Pallet;\n ```\n\n- **ParachainSystem Pallet**: This pallet ([`cumulus-pallet-parachain-system`](https://paritytech.github.io/polkadot-sdk/master/cumulus_pallet_parachain_system/index.html){target=\\_blank}) enables parachain functionality and handles low-level details of being a parachain.\n\n ```rust title=\"runtime/src/lib.rs\"\n impl cumulus_pallet_parachain_system::Config for Runtime {\n type RuntimeEvent = RuntimeEvent;\n type OnSystemEvent = ();\n // ... other configurations\n }\n\n // Must be named \"ParachainSystem\" for omni-node compatibility \n pub type ParachainSystem = cumulus_pallet_parachain_system::Pallet;\n ```\n\n- **Aura Pallet**: For block authoring consensus ([`pallet-aura`](https://paritytech.github.io/polkadot-sdk/master/pallet_aura/index.html){target=\\_blank}).\n\n ```rust title=\"runtime/src/lib.rs\"\n impl pallet_aura::Config for Runtime {\n type AuthorityId = AuraId;\n type DisabledValidators = ();\n type MaxAuthorities = MaxAuthorities;\n type AllowMultipleBlocksPerSlot = ConstBool;\n }\n\n pub type Aura = pallet_aura::Pallet;\n ```\n\n- **ParachainInfo Pallet**: Provides parachain metadata ([`parachain-info`](https://paritytech.github.io/polkadot-sdk/master/staging_parachain_info/index.html){target=\\_blank}).\n\n ```rust title=\"runtime/src/lib.rs\"\n impl parachain_info::Config for Runtime {}\n\n pub type ParachainInfo = parachain_info::Pallet;\n ```\n\nIf you're migrating an existing parachain to use the `polkadot-omni-node`, you may need to perform runtime upgrades to add the required runtime APIs and pallets. Follow the standard parachain [runtime upgrade](/parachains/runtime-maintenance/runtime-upgrades/){target=\\_blank} procedures to implement these changes on your live network."} -{"page_id": "reference-tools-papi", "page_title": "Polkadot-API", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 16, "end_char": 1133, "estimated_token_count": 207, "token_estimator": "heuristic-v1", "text": "## Introduction\n\n[Polkadot-API](https://github.com/polkadot-api/polkadot-api){target=\\_blank} (PAPI) is a set of libraries built to be modular, composable, and grounded in a “light-client first” approach. Its primary aim is to equip dApp developers with an extensive toolkit for building fully decentralized applications.\n\nPAPI is optimized for light-client functionality, using the new JSON-RPC spec to support decentralized interactions fully. It provides strong TypeScript support with types and documentation generated directly from on-chain metadata, and it offers seamless access to storage reads, constants, transactions, events, and runtime calls. Developers can connect to multiple chains simultaneously and prepare for runtime updates through multi-descriptor generation and compatibility checks. PAPI is lightweight and performant, leveraging native BigInt, dynamic imports, and modular subpaths to avoid bundling unnecessary assets. It supports promise-based and observable-based APIs, integrates easily with Polkadot.js extensions, and offers signing options through browser extensions or private keys."} -{"page_id": "reference-tools-papi", "page_title": "Polkadot-API", "index": 1, "depth": 2, "title": "Get Started", "anchor": "get-started", "start_char": 1133, "end_char": 1149, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Get Started"} -{"page_id": "reference-tools-papi", "page_title": "Polkadot-API", "index": 2, "depth": 3, "title": "API Instantiation", "anchor": "api-instantiation", "start_char": 1149, "end_char": 6190, "estimated_token_count": 1162, "token_estimator": "heuristic-v1", "text": "### API Instantiation\n\nTo instantiate the API, you can install the package by using the following command:\n\n=== \"npm\"\n\n ```bash\n npm i polkadot-api@1.17.2\n ```\n\n=== \"pnpm\"\n\n ```bash\n pnpm add polkadot-api@1.17.2\n ```\n\n=== \"yarn\"\n\n ```bash\n yarn add polkadot-api@1.17.2\n ```\n\nThen, obtain the latest metadata from the target chain and generate the necessary types:\n\n```bash\n# Add the target chain\nnpx papi add dot -n polkadot\n```\n\nThe `papi add` command initializes the library by generating the corresponding types needed for the chain used. It assigns the chain a custom name and specifies downloading metadata from the Polkadot chain. You can replace `dot` with the name you prefer or with another chain if you want to add a different one. Once the latest metadata is downloaded, generate the required types:\n\n```bash\n# Generate the necessary types\nnpx papi\n```\n\nYou can now set up a [`PolkadotClient`](https://github.com/polkadot-api/polkadot-api/blob/main/packages/client/src/types.ts#L153){target=\\_blank} with your chosen provider to begin interacting with the API. Choose from Smoldot via WebWorker, Node.js, or direct usage, or connect through the WSS provider. The examples below show how to configure each option for your setup.\n\n=== \"Smoldot (WebWorker)\"\n\n ```typescript\n // `dot` is the identifier assigned during `npx papi add`\n import { dot } from '@polkadot-api/descriptors';\n import { createClient } from 'polkadot-api';\n import { getSmProvider } from 'polkadot-api/sm-provider';\n import { chainSpec } from 'polkadot-api/chains/polkadot';\n import { startFromWorker } from 'polkadot-api/smoldot/from-worker';\n import SmWorker from 'polkadot-api/smoldot/worker?worker';\n\n const worker = new SmWorker();\n const smoldot = startFromWorker(worker);\n const chain = await smoldot.addChain({ chainSpec });\n\n // Establish connection to the Polkadot relay chain\n const client = createClient(getSmProvider(chain));\n\n // To interact with the chain, obtain the `TypedApi`, which provides\n // the necessary types for every API call on this chain\n const dotApi = client.getTypedApi(dot);\n\n ```\n\n=== \"Smoldot (Node.js)\"\n\n ```typescript\n // `dot` is the alias assigned during `npx papi add`\n import { dot } from '@polkadot-api/descriptors';\n import { createClient } from 'polkadot-api';\n import { getSmProvider } from 'polkadot-api/sm-provider';\n import { chainSpec } from 'polkadot-api/chains/polkadot';\n import { startFromWorker } from 'polkadot-api/smoldot/from-node-worker';\n import { fileURLToPath } from 'url';\n import { Worker } from 'worker_threads';\n\n // Get the path for the worker file in ESM\n const workerPath = fileURLToPath(\n import.meta.resolve('polkadot-api/smoldot/node-worker'),\n );\n\n const worker = new Worker(workerPath);\n const smoldot = startFromWorker(worker);\n const chain = await smoldot.addChain({ chainSpec });\n\n // Set up a client to connect to the Polkadot relay chain\n const client = createClient(getSmProvider(chain));\n\n // To interact with the chain's API, use `TypedApi` for access to\n // all the necessary types and calls associated with this chain\n const dotApi = client.getTypedApi(dot);\n\n ```\n\n=== \"Smoldot\"\n\n ```typescript\n // `dot` is the alias assigned when running `npx papi add`\n import { dot } from '@polkadot-api/descriptors';\n import { createClient } from 'polkadot-api';\n import { getSmProvider } from 'polkadot-api/sm-provider';\n import { chainSpec } from 'polkadot-api/chains/polkadot';\n import { start } from 'polkadot-api/smoldot';\n\n // Initialize Smoldot client\n const smoldot = start();\n const chain = await smoldot.addChain({ chainSpec });\n\n // Set up a client to connect to the Polkadot relay chain\n const client = createClient(getSmProvider(chain));\n\n // Access the `TypedApi` to interact with all available chain calls and types\n const dotApi = client.getTypedApi(dot);\n\n ```\n\n=== \"WSS\"\n\n ```typescript\n // `dot` is the identifier assigned when executing `npx papi add`\n import { dot } from '@polkadot-api/descriptors';\n import { createClient } from 'polkadot-api';\n // Use this import for Node.js environments\n import { getWsProvider } from 'polkadot-api/ws-provider/web';\n import { withPolkadotSdkCompat } from 'polkadot-api/polkadot-sdk-compat';\n\n // Establish a connection to the Polkadot relay chain\n const client = createClient(\n // The Polkadot SDK nodes may have compatibility issues; using this enhancer is recommended.\n // Refer to the Requirements page for additional details\n withPolkadotSdkCompat(getWsProvider('wss://dot-rpc.stakeworld.io')),\n );\n\n // To interact with the chain, obtain the `TypedApi`, which provides\n // the types for all available calls in that chain\n const dotApi = client.getTypedApi(dot);\n\n ```\n\nNow that you have set up the client, you can interact with the chain by reading and sending transactions."} -{"page_id": "reference-tools-papi", "page_title": "Polkadot-API", "index": 3, "depth": 3, "title": "Reading Chain Data", "anchor": "reading-chain-data", "start_char": 6190, "end_char": 7140, "estimated_token_count": 216, "token_estimator": "heuristic-v1", "text": "### Reading Chain Data\n\nThe `TypedApi` provides a streamlined way to read blockchain data through three main interfaces, each designed for specific data access patterns:\n\n- **Constants**: Access fixed values or configurations on the blockchain using the `constants` interface.\n\n ```typescript\n const version = await typedApi.constants.System.Version();\n ```\n\n- **Storage queries**: Retrieve stored values by querying the blockchain’s storage via the `query` interface.\n\n ```typescript\n const asset = await api.query.ForeignAssets.Asset.getValue(\n token.location,\n { at: 'best' },\n );\n ```\n\n- **Runtime APIs**: Interact directly with runtime APIs using the `apis` interface.\n\n ```typescript\n const metadata = await typedApi.apis.Metadata.metadata();\n ```\n\nTo learn more about the different actions you can perform with the `TypedApi`, refer to the [TypedApi reference](https://papi.how/typed){target=\\_blank}."} -{"page_id": "reference-tools-papi", "page_title": "Polkadot-API", "index": 4, "depth": 3, "title": "Sending Transactions", "anchor": "sending-transactions", "start_char": 7140, "end_char": 8815, "estimated_token_count": 355, "token_estimator": "heuristic-v1", "text": "### Sending Transactions\n\nIn PAPI, the `TypedApi` provides the `tx` and `txFromCallData` methods to send transactions. \n\n- The `tx` method allows you to directly send a transaction with the specified parameters by using the `typedApi.tx.Pallet.Call` pattern:\n\n ```typescript\n const tx: Transaction = typedApi.tx.Pallet.Call({arg1, arg2, arg3});\n ``` \n\n For instance, to execute the `balances.transferKeepAlive` call, you can use the following snippet:\n\n ```typescript\n import { MultiAddress } from '@polkadot-api/descriptors';\n\n const tx: Transaction = typedApi.tx.Balances.transfer_keep_alive({\n dest: MultiAddress.Id('INSERT_DESTINATION_ADDRESS'),\n value: BigInt(INSERT_VALUE),\n });\n\n ```\n\n Ensure you replace `INSERT_DESTINATION_ADDRESS` and `INSERT_VALUE` with the actual destination address and value, respectively.\n\n- The `txFromCallData` method allows you to send a transaction using the call data. This option accepts binary call data and constructs the transaction from it. It validates the input upon creation and will throw an error if invalid data is provided. The pattern is as follows:\n\n ```typescript\n const callData = Binary.fromHex('0x...');\n const tx: Transaction = typedApi.txFromCallData(callData);\n ``` \n\n For instance, to execute a transaction using the call data, you can use the following snippet:\n\n ```typescript\n const callData = Binary.fromHex('0x00002470617065726d6f6f6e');\n const tx: Transaction = typedApi.txFromCallData(callData);\n ```\n\nFor more information about sending transactions, refer to the [Transactions](https://papi.how/typed/tx#transactions){target=\\_blank} page."} -{"page_id": "reference-tools-papi", "page_title": "Polkadot-API", "index": 5, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 8815, "end_char": 8957, "estimated_token_count": 43, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor an in-depth guide on how to use PAPI, refer to the official [PAPI](https://papi.how/){target=\\_blank} documentation."} -{"page_id": "reference-tools-paraspell", "page_title": "ParaSpell XCM SDK", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 21, "end_char": 2383, "estimated_token_count": 522, "token_estimator": "heuristic-v1", "text": "## Introduction\n\n[ParaSpell](https://paraspell.github.io/docs/){target=\\_blank} is a comprehensive suite of open-source tools designed to simplify cross-chain interactions within the Polkadot ecosystem. At its core, ParaSpell is dedicated to enhancing the functionality of the [XCM (Cross-Consensus Messaging)](/parachains/interoperability/get-started/){target=\\_blank} protocol by providing developers with a unified and streamlined experience for building interoperable decentralized applications (dApps).\n\nThe primary goal of ParaSpell is to abstract away the complexities of the XCM protocol. While XCM is a powerful feature of the Polkadot network, its implementation can vary significantly between different parachains. ParaSpell addresses this challenge by providing a standardized set of tools that enable developers to easily integrate cross-chain functionality into their applications, saving valuable time and effort. ParaSpell is a \"common good\" software, meaning it is free, open-source, and dedicated to the growth of the Polkadot ecosystem.\n\nThe ParaSpell suite includes:\n\n- **[XCM SDK](https://paraspell.xyz/#xcm-sdk){target=\\_blank}**: Provides a unified layer to incorporate XCM into decentralized applications, simplifying complex cross-chain interactions.\n- **[XCM API](https://paraspell.xyz/#xcm-api){target=\\_blank}**: Offers an efficient, package-free approach to integrating XCM functionality while offloading heavy computing tasks, minimizing costs and improving application performance.\n- **[XCM Router](https://paraspell.xyz/#xcm-router){target=\\_blank}**: Enables cross-chain asset swaps in a single command, allowing developers to send one asset type (such as DOT on Polkadot) and receive a different asset on another chain (like ASTR on Astar).\n- **[XCM Analyser](https://paraspell.xyz/#xcm-analyser){target=\\_blank}**: Decodes and translates complex XCM multilocation data into readable information, supporting easier troubleshooting and debugging.\n- **[XCM Visualizator](https://paraspell.xyz/#xcm-visualizator){target=\\_blank}**: A tool designed to give developers a clear, interactive view of XCM activity across the Polkadot ecosystem, providing insights into cross-chain communication flow.\n- **[XCM Playground](https://paraspell.xyz/#try-it){target=\\_blank}**: An interactive playground for testing different XCM scenarios."} -{"page_id": "reference-tools-paraspell", "page_title": "ParaSpell XCM SDK", "index": 1, "depth": 3, "title": "ParaSpell XCM SDK", "anchor": "paraspell-xcm-sdk", "start_char": 2383, "end_char": 3290, "estimated_token_count": 171, "token_estimator": "heuristic-v1", "text": "### ParaSpell XCM SDK\n\nThe [ParaSpell XCM SDK](https://paraspell.github.io/docs/sdk/getting-started.html){target=\\_blank} is a core component of the ParaSpell toolset and a foundational library for developers looking to leverage XCM in their applications. It is the first and only XCM SDK in the ecosystem to support both PolkadotJS and Polkadot API, providing developers with flexibility and choice.\n\nThe SDK simplifies the process of creating and sending XCM messages by providing a user-friendly builder pattern. This allows developers to construct complex XCM calls with just a few lines of code, reducing the likelihood of errors and ensuring that messages are constructed correctly.\n\nBy using the ParaSpell XCM SDK, developers can significantly accelerate their development workflow and build powerful, interoperable dApps that take full advantage of the Polkadot network's cross-chain capabilities."} -{"page_id": "reference-tools-paraspell", "page_title": "ParaSpell XCM SDK", "index": 2, "depth": 2, "title": "Install ParaSpell", "anchor": "install-paraspell", "start_char": 3290, "end_char": 3634, "estimated_token_count": 103, "token_estimator": "heuristic-v1", "text": "## Install ParaSpell\n\nIf you want to use ParaSpell in your project you can add it as a dependency with the following command:\n\n=== \"npm\"\n\n ```bash\n npm install --save @paraspell/sdk@11.12.6\n ```\n\n=== \"pnpm\"\n\n ```bash\n pnpm add @paraspell/sdk@11.12.6\n ```\n\n=== \"yarn\"\n\n ```bash\n yarn add @paraspell/sdk@11.12.6\n ```"} -{"page_id": "reference-tools-paraspell", "page_title": "ParaSpell XCM SDK", "index": 3, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 3634, "end_char": 4043, "estimated_token_count": 92, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nExplore more about ParaSpell through these resources:\n\n
    \n\n- Tutorial __Transfer Assets Between Parachains__\n\n ---\n\n Learn how to transfer assets across chains with ParaSpell.\n\n [:octicons-arrow-right-24: Get Started](/chain-interactions/send-transactions/interoperability/transfer-assets-parachains/)\n\n
    "} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 0, "depth": 2, "title": "Installation", "anchor": "installation", "start_char": 454, "end_char": 1089, "estimated_token_count": 147, "token_estimator": "heuristic-v1", "text": "## Installation\n\nAdd Polkadart to your `pubspec.yaml`:\n\n=== \"All packages\"\n\n ```bash\n dart pub add polkadart polkadart_cli polkadart_keyring polkadart_scale_codec secp256k1_ecdsa sr25519 ss58 substrate_bip39 substrate_metadata\n ```\n\n=== \"Core only\"\n\n ```bash\n dart pub add polkadart polkadart_cli polkadart_keyring\n ```\n\nFor type-safe API generation, add the following to your `pubspec.yaml`:\n\n{% raw %}\n```yaml title=\"pubspec.yaml\"\npolkadart:\n output_dir: lib/generated\n chains:\n polkadot: wss://rpc.polkadot.io\n kusama: wss://kusama-rpc.polkadot.io\n custom: wss://your-node.example.com\n```\n{% endraw %}"} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 1, "depth": 2, "title": "Get Started", "anchor": "get-started", "start_char": 1089, "end_char": 1105, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Get Started"} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 2, "depth": 3, "title": "Type Generation", "anchor": "type-generation", "start_char": 1105, "end_char": 1354, "estimated_token_count": 45, "token_estimator": "heuristic-v1", "text": "### Type Generation\n\nPolkadart provides a CLI tool to generate type definitions from any Polkadot-SDK compatible blockchain network. This allows you to build type-safe Dart applications without dealing with the low-level details of the blockchain."} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 3, "depth": 3, "title": "Run Generator", "anchor": "run-generator", "start_char": 1354, "end_char": 1421, "estimated_token_count": 19, "token_estimator": "heuristic-v1", "text": "### Run Generator\n\n```bash\ndart run polkadart_cli:generate -v\n```"} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 4, "depth": 3, "title": "Use Generated Types", "anchor": "use-generated-types", "start_char": 1421, "end_char": 1964, "estimated_token_count": 138, "token_estimator": "heuristic-v1", "text": "### Use Generated Types\n\n```dart\nimport 'package:your_app/generated/polkadot/polkadot.dart';\nimport 'package:polkadart/polkadart.dart';\nimport 'package:ss58/ss58.dart';\n\nfinal provider = Provider.fromUri(Uri.parse('wss://rpc.polkadot.io'));\nfinal polkadot = Polkadot(provider);\n \n// Account from SS58 address\nfinal account = Address.decode('19t9Q2ay58hMDaeg6eeBhqmHsRnc2jDMV3cYYw9zbc59HLj');\n\n// Retrieve Account Balance\nfinal accountInfo = await polkadot.query.system.account(account.pubkey);\nprint('Balance: ${accountInfo.data.free}')\n```"} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 5, "depth": 3, "title": "Creating an API Instance", "anchor": "creating-an-api-instance", "start_char": 1964, "end_char": 2413, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "### Creating an API Instance\n\nAn API instance is required to interact with the blockchain. Polkadart provides a `Provider` class that allows you to connect to any network.\n\n```dart\nimport 'package:demo/generated/polkadot/polkadot.dart';\nimport 'package:polkadart/provider.dart';\n\nFuture main(List arguments) async {\n final provider = Provider.fromUri(Uri.parse('wss://rpc.polkadot.io'));\n final polkadot = Polkadot(provider);\n}\n```"} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 6, "depth": 3, "title": "Reading Chain Data", "anchor": "reading-chain-data", "start_char": 2413, "end_char": 2909, "estimated_token_count": 111, "token_estimator": "heuristic-v1", "text": "### Reading Chain Data\n\nBesides querying the data using the `query` from the generated API, you can also use the State API for querying storage data, metadata, runtime information, and other chain information.\n\n```dart\nfinal stateApi = StateApi(provider);\n\n// Get current runtime version\nfinal runtimeVersion = await stateApi.getRuntimeVersion();\nprint(runtimeVersion.toJson());\n\n// Get metadata\nfinal metadata = await stateApi.getMetadata();\nprint('Metadata version: ${metadata.version}');\n```"} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 7, "depth": 3, "title": "Subscribe to New Blocks", "anchor": "subscribe-to-new-blocks", "start_char": 2909, "end_char": 3197, "estimated_token_count": 74, "token_estimator": "heuristic-v1", "text": "### Subscribe to New Blocks\n\nYou can subscribe to new blocks on the blockchain using the `subscribe` method.\n\n```dart\nfinal subscription = await provider.subscribe('chain_subscribeNewHeads', []);\n\nsubscription.stream.forEach((response) {\n print('New head: ${response.result}');\n});\n```"} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 8, "depth": 3, "title": "Send a Transaction", "anchor": "send-a-transaction", "start_char": 3197, "end_char": 4956, "estimated_token_count": 380, "token_estimator": "heuristic-v1", "text": "### Send a Transaction\n\nPerhaps the most common operation done in any blockchain is transferring funds. Here you can see how that can be done using Polkadart:\n\n```dart\nfinal wallet = await KeyPair.sr25519.fromUri(\"//Alice\");\nprint('Alice\\' wallet: ${wallet.address}');\n\n// Get information necessary to build a proper extrinsic\nfinal runtimeVersion = await polkadot.rpc.state.getRuntimeVersion();\nfinal currentBlockNumber = (await polkadot.query.system.number()) - 1;\nfinal currentBlockHash = await polkadot.query.system.blockHash(currentBlockNumber);\nfinal genesisHash = await polkadot.query.system.blockHash(0);\nfinal nonce = await polkadot.rpc.system.accountNextIndex(wallet.address);\n\n// Make the encoded call\nfinal multiAddress = $MultiAddress().id(wallet.publicKey.bytes);\nfinal transferCall = polkadot.tx.balances.transferKeepAlive(dest: multiAddress, value: BigInt.one).encode();\n\n// Make the payload\nfinal payload = SigningPayload(\n method: transferCall,\n specVersion: runtimeVersion.specVersion,\n transactionVersion: runtimeVersion.transactionVersion,\n genesisHash: encodeHex(genesisHash),\n blockHash: encodeHex(currentBlockHash),\n blockNumber: currentBlockNumber,\n eraPeriod: 64,\n nonce: nonce,\n tip: 0,\n).encode(polkadot.registry);\n\n// Sign the payload and build the final extrinsic\nfinal signature = wallet.sign(payload);\nfinal extrinsic = ExtrinsicPayload(\n signer: wallet.bytes(),\n method: transferCall,\n signature: signature,\n eraPeriod: 64,\n blockNumber: currentBlockNumber,\n nonce: nonce,\n tip: 0,\n).encode(polkadot.registry, SignatureType.sr25519);\n\n// Send the extrinsic to the blockchain\nfinal author = AuthorApi(provider);\nawait author.submitAndWatchExtrinsic(extrinsic, (data) {\n print(data);\n});\n```"} -{"page_id": "reference-tools-polkadart", "page_title": "Polkadart", "index": 9, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 4956, "end_char": 5178, "estimated_token_count": 51, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nTo dive deeper into Polkadart, refer to the [official Polkadart documentation](https://polkadart.dev/){target=\\_blank}, where you can find comprehensive guides for common use cases and advanced usage."} -{"page_id": "reference-tools-polkadot-js-api", "page_title": "Polkadot.js API", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 385, "end_char": 669, "estimated_token_count": 68, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe [Polkadot.js API](https://github.com/polkadot-js/api){target=\\_blank} uses JavaScript/TypeScript to interact with Polkadot SDK-based chains. It allows you to query nodes, read chain state, and submit transactions through a dynamic, auto-generated API interface."} -{"page_id": "reference-tools-polkadot-js-api", "page_title": "Polkadot.js API", "index": 1, "depth": 3, "title": "Dynamic API Generation", "anchor": "dynamic-api-generation", "start_char": 669, "end_char": 1033, "estimated_token_count": 85, "token_estimator": "heuristic-v1", "text": "### Dynamic API Generation\n\nUnlike traditional static APIs, the Polkadot.js API generates its interfaces automatically when connecting to a node. Here's what happens when you connect:\n\n1. The API connects to your node.\n2. It retrieves the chain's metadata.\n3. Based on this metadata, it creates specific endpoints in this format: `api...
    `."} -{"page_id": "reference-tools-polkadot-js-api", "page_title": "Polkadot.js API", "index": 2, "depth": 3, "title": "Available API Categories", "anchor": "available-api-categories", "start_char": 1033, "end_char": 1888, "estimated_token_count": 248, "token_estimator": "heuristic-v1", "text": "### Available API Categories\n\nYou can access three main categories of chain interactions:\n\n- **[Runtime constants](https://polkadot.js.org/docs/api/start/api.consts){target=\\_blank}** (`api.consts`):\n\n - Access runtime constants directly.\n - Returns values immediately without function calls.\n - **Example**: `api.consts.balances.existentialDeposit`\n\n- **[State queries](https://polkadot.js.org/docs/api/start/api.query/){target=\\_blank}** (`api.query`):\n\n - Read chain state.\n - **Example**: `api.query.system.account(accountId)`\n\n- **[Transactions](https://polkadot.js.org/docs/api/start/api.tx/){target=\\_blank}** (`api.tx`):\n - Submit extrinsics (transactions).\n - **Example**: `api.tx.balances.transfer(accountId, value)`\n\nThe available methods and interfaces will automatically reflect what's possible on your connected chain."} -{"page_id": "reference-tools-polkadot-js-api", "page_title": "Polkadot.js API", "index": 3, "depth": 2, "title": "Installation", "anchor": "installation", "start_char": 1888, "end_char": 2441, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Installation\n\nTo add the Polkadot.js API to your project, use the following command to install the version `16.4.7` which supports any Polkadot SDK-based chain:\n\n=== \"npm\"\n ```bash\n npm i @polkadot/api@16.4.7\n ```\n\n=== \"pnpm\"\n ```bash\n pnpm add @polkadot/api@16.4.7\n ```\n\n=== \"yarn\"\n ```bash\n yarn add @polkadot/api@16.4.7\n ```\n\nFor more detailed information about installation, see the [Installation](https://polkadot.js.org/docs/api/start/install/){target=\\_blank} section in the official Polkadot.js API documentation."} -{"page_id": "reference-tools-polkadot-js-api", "page_title": "Polkadot.js API", "index": 4, "depth": 2, "title": "Get Started", "anchor": "get-started", "start_char": 2441, "end_char": 2457, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Get Started"} -{"page_id": "reference-tools-polkadot-js-api", "page_title": "Polkadot.js API", "index": 5, "depth": 3, "title": "Creating an API Instance", "anchor": "creating-an-api-instance", "start_char": 2457, "end_char": 3226, "estimated_token_count": 175, "token_estimator": "heuristic-v1", "text": "### Creating an API Instance\n\nTo interact with a Polkadot SDK-based chain, you must establish a connection through an API instance. The API provides methods for querying chain state, sending transactions, and subscribing to updates.\n\nTo create an API connection:\n\n```js\nimport { ApiPromise, WsProvider } from '@polkadot/api';\n\n// Create a WebSocket provider\nconst wsProvider = new WsProvider('wss://rpc.polkadot.io');\n\n// Initialize the API\nconst api = await ApiPromise.create({ provider: wsProvider });\n\n// Verify the connection by getting the chain's genesis hash\nconsole.log('Genesis Hash:', api.genesisHash.toHex());\n\n```\n\n!!!warning\n All `await` operations must be wrapped in an async function or block since the API uses promises for asynchronous operations."} -{"page_id": "reference-tools-polkadot-js-api", "page_title": "Polkadot.js API", "index": 6, "depth": 3, "title": "Reading Chain Data", "anchor": "reading-chain-data", "start_char": 3226, "end_char": 4066, "estimated_token_count": 187, "token_estimator": "heuristic-v1", "text": "### Reading Chain Data\n\nThe API provides several ways to read data from the chain. You can access:\n\n- **Constants**: Values that are fixed in the runtime and don't change without a runtime upgrade.\n\n ```js\n // Get the minimum balance required for a new account\n const minBalance = api.consts.balances.existentialDeposit.toNumber();\n\n ```\n\n- **State**: Current chain state that updates with each block.\n\n ```js\n // Example address\n const address = '5DTestUPts3kjeXSTMyerHihn1uwMfLj8vU8sqF7qYrFabHE';\n\n // Get current timestamp\n const timestamp = await api.query.timestamp.now();\n\n // Get account information\n const { nonce, data: balance } = await api.query.system.account(address);\n\n console.log(`\n Timestamp: ${timestamp}\n Free Balance: ${balance.free}\n Nonce: ${nonce}\n `);\n\n ```"} -{"page_id": "reference-tools-polkadot-js-api", "page_title": "Polkadot.js API", "index": 7, "depth": 3, "title": "Sending Transactions", "anchor": "sending-transactions", "start_char": 4066, "end_char": 4881, "estimated_token_count": 194, "token_estimator": "heuristic-v1", "text": "### Sending Transactions\n\nTransactions (also called extrinsics) modify the chain state. Before sending a transaction, you need:\n\n- A funded account with sufficient balance to pay transaction fees.\n- The account's keypair for signing.\n\nTo make a transfer:\n\n```js\n// Assuming you have an `alice` keypair from the Keyring\nconst recipient = 'INSERT_RECIPIENT_ADDRESS';\nconst amount = 'INSERT_VALUE'; // Amount in the smallest unit (e.g., Planck for DOT)\n\n// Sign and send a transfer\nconst txHash = await api.tx.balances\n .transfer(recipient, amount)\n .signAndSend(alice);\n\nconsole.log('Transaction Hash:', txHash);\n\n```\n\nThe `alice` keypair in the example comes from a `Keyring` object. For more details about managing keypairs, see the [Keyring documentation](https://polkadot.js.org/docs/keyring){target=\\_blank}."} -{"page_id": "reference-tools-polkadot-js-api", "page_title": "Polkadot.js API", "index": 8, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 4881, "end_char": 5042, "estimated_token_count": 44, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor more detailed information about the Polkadot.js API, check the [official documentation](https://polkadot.js.org/docs/){target=\\_blank}."} -{"page_id": "reference-tools-py-substrate-interface", "page_title": "Python Substrate Interface", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 30, "end_char": 484, "estimated_token_count": 87, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe [Python Substrate Interface](https://github.com/polkascan/py-substrate-interface){target=\\_blank} is a powerful library that enables interaction with Polkadot SDK-based chains. It provides essential functionality for:\n\n- Querying on-chain storage.\n- Composing and submitting extrinsics.\n- SCALE encoding/decoding.\n- Interacting with Substrate runtime metadata.\n- Managing blockchain interactions through convenient utility methods."} -{"page_id": "reference-tools-py-substrate-interface", "page_title": "Python Substrate Interface", "index": 1, "depth": 2, "title": "Installation", "anchor": "installation", "start_char": 484, "end_char": 791, "estimated_token_count": 72, "token_estimator": "heuristic-v1", "text": "## Installation\n\nInstall the library using `pip`:\n\n```py\npip install substrate-interface\n```\n\nFor more installation details, see the [Installation](https://jamdottech.github.io/py-polkadot-sdk/getting-started/installation/){target=\\_blank} section in the official Python Substrate Interface documentation."} -{"page_id": "reference-tools-py-substrate-interface", "page_title": "Python Substrate Interface", "index": 2, "depth": 2, "title": "Get Started", "anchor": "get-started", "start_char": 791, "end_char": 971, "estimated_token_count": 32, "token_estimator": "heuristic-v1", "text": "## Get Started\n\nThis guide will walk you through the basic operations with the Python Substrate Interface: connecting to a node, reading chain state, and submitting transactions."} -{"page_id": "reference-tools-py-substrate-interface", "page_title": "Python Substrate Interface", "index": 3, "depth": 3, "title": "Establishing Connection", "anchor": "establishing-connection", "start_char": 971, "end_char": 1488, "estimated_token_count": 130, "token_estimator": "heuristic-v1", "text": "### Establishing Connection\n\nThe first step is to establish a connection to a Polkadot SDK-based node. You can connect to either a local or remote node:\n\n```py\nfrom substrateinterface import SubstrateInterface\n\n# Connect to a node using websocket\nsubstrate = SubstrateInterface(\n # For local node: \"ws://127.0.0.1:9944\"\n # For Polkadot: \"wss://rpc.polkadot.io\"\n # For Kusama: \"wss://kusama-rpc.polkadot.io\"\n url=\"INSERT_WS_URL\"\n)\n\n# Verify connection\nprint(f\"Connected to chain: {substrate.chain}\")\n\n```"} -{"page_id": "reference-tools-py-substrate-interface", "page_title": "Python Substrate Interface", "index": 4, "depth": 3, "title": "Reading Chain State", "anchor": "reading-chain-state", "start_char": 1488, "end_char": 2506, "estimated_token_count": 242, "token_estimator": "heuristic-v1", "text": "### Reading Chain State\n\nYou can query various on-chain storage items. To retrieve data, you need to specify three key pieces of information:\n\n- **Pallet name**: Module or pallet that contains the storage item you want to access.\n- **Storage item**: Specific storage entry you want to query within the pallet.\n- **Required parameters**: Any parameters needed to retrieve the desired data.\n\nHere's an example of how to check an account's balance and other details:\n\n```py\n# ...\n\n# Query account balance and info\naccount_info = substrate.query(\n module=\"System\", # The pallet name\n storage_function=\"Account\", # The storage item\n params=[\"INSERT_ADDRESS\"], # Account address in SS58 format\n)\n\n# Access account details from the result\nfree_balance = account_info.value[\"data\"][\"free\"]\nreserved = account_info.value[\"data\"][\"reserved\"]\nnonce = account_info.value[\"nonce\"]\n\nprint(\n f\"\"\"\n Account Details:\n - Free Balance: {free_balance}\n - Reserved: {reserved} \n - Nonce: {nonce}\n \"\"\"\n)\n\n```"} -{"page_id": "reference-tools-py-substrate-interface", "page_title": "Python Substrate Interface", "index": 5, "depth": 3, "title": "Submitting Transactions", "anchor": "submitting-transactions", "start_char": 2506, "end_char": 3899, "estimated_token_count": 294, "token_estimator": "heuristic-v1", "text": "### Submitting Transactions\n\nTo modify the chain state, you need to submit transactions (extrinsics). Before proceeding, ensure you have:\n\n- A funded account with sufficient balance to pay transaction fees.\n- Access to the account's keypair.\n\nHere's how to create and submit a balance transfer:\n\n```py\n#...\n\n# Compose the transfer call\ncall = substrate.compose_call(\n call_module=\"Balances\", # The pallet name\n call_function=\"transfer_keep_alive\", # The extrinsic function\n call_params={\n 'dest': 'INSERT_ADDRESS', # Recipient's address\n 'value': 'INSERT_VALUE' # Amount in smallest unit (e.g., Planck for DOT)\n }\n)\n\n# Create a signed extrinsic\nextrinsic = substrate.create_signed_extrinsic(\n call=call, keypair=keypair # Your keypair for signing\n)\n\n# Submit and wait for inclusion\nreceipt = substrate.submit_extrinsic(\n extrinsic, wait_for_inclusion=True # Wait until the transaction is in a block\n)\n\nif receipt.is_success:\n print(\n f\"\"\"\n Transaction successful:\n - Extrinsic Hash: {receipt.extrinsic_hash}\n - Block Hash: {receipt.block_hash}\n \"\"\"\n )\nelse:\n print(f\"Transaction failed: {receipt.error_message}\")\n\n```\n\nThe `keypair` object is essential for signing transactions. See the [Keypair](https://jamdottech.github.io/py-polkadot-sdk/reference/keypair/){target=\\_blank} documentation for more details."} -{"page_id": "reference-tools-py-substrate-interface", "page_title": "Python Substrate Interface", "index": 6, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 3899, "end_char": 4302, "estimated_token_count": 85, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nNow that you understand the basics, you can:\n\n- Explore more complex queries and transactions.\n- Learn about batch transactions and utility functions.\n- Discover how to work with custom pallets and types.\n\nFor comprehensive reference materials and advanced features, see the [Python Substrate Interface](https://jamdottech.github.io/py-polkadot-sdk/){target=\\_blank} documentation."} -{"page_id": "reference-tools-sidecar", "page_title": "Sidecar REST API", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 15, "end_char": 1185, "estimated_token_count": 228, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe [Sidecar REST API](https://github.com/paritytech/substrate-api-sidecar){target=\\_blank} is a service that provides a REST interface for interacting with Polkadot SDK-based blockchains. With this API, developers can easily access a broad range of endpoints for nodes, accounts, transactions, parachains, and more.\n\nSidecar functions as a caching layer between your application and a Polkadot SDK-based node, offering standardized REST endpoints that simplify interactions without requiring complex, direct RPC calls. This approach is especially valuable for developers who prefer REST APIs or build applications in languages with limited WebSocket support.\n\nSome of the key features of the Sidecar API include:\n\n- **REST API interface**: Provides a familiar REST API interface for interacting with Polkadot SDK-based chains.\n- **Standardized endpoints**: Offers consistent endpoint formats across different chain implementations.\n- **Caching layer**: Acts as a caching layer to improve performance and reduce direct node requests.\n- **Multiple chain support**: Works with any Polkadot SDK-based chain, including Polkadot, Kusama, and custom chains."} -{"page_id": "reference-tools-sidecar", "page_title": "Sidecar REST API", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 1185, "end_char": 1484, "estimated_token_count": 80, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nSidecar API requires Node.js version 18.14 LTS or higher. Verify your Node.js version:\n\n```bash\nnode --version\n```\n\nIf you need to install or update Node.js, visit the [official Node.js website](https://nodejs.org/){target=\\_blank} to download and install the latest LTS version."} -{"page_id": "reference-tools-sidecar", "page_title": "Sidecar REST API", "index": 2, "depth": 2, "title": "Installation", "anchor": "installation", "start_char": 1484, "end_char": 2137, "estimated_token_count": 171, "token_estimator": "heuristic-v1", "text": "## Installation\n\nTo install Substrate API Sidecar, use one of the following commands:\n\n=== \"npm\"\n\n ```bash\n npm install -g @substrate/api-sidecar\n ```\n\n=== \"pnpm\"\n\n ```bash\n pnpm install -g @substrate/api-sidecar\n ```\n\n=== \"yarn\"\n\n ```bash\n yarn global add @substrate/api-sidecar\n ```\n\nYou can confirm the installation by running:\n\n```bash\nsubstrate-api-sidecar --version\n```\n\nFor more information about the Sidecar API installation, see the [installation and usage](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#npm-package-installation-and-usage){target=\\_blank} section of the Sidecar API README."} -{"page_id": "reference-tools-sidecar", "page_title": "Sidecar REST API", "index": 3, "depth": 2, "title": "Usage", "anchor": "usage", "start_char": 2137, "end_char": 5688, "estimated_token_count": 1005, "token_estimator": "heuristic-v1", "text": "## Usage\n\nTo use the Sidecar API, you have two options:\n\n- **Local node**: Run a node locally, which Sidecar will connect to by default, requiring no additional configuration. To start, run the following:\n\n ```bash\n substrate-api-sidecar\n ```\n\n- **Remote node**: Connect Sidecar to a remote node by specifying the RPC endpoint for that chain. For example, to gain access to the Polkadot Asset Hub associated endpoints.\n\n ```bash\n SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io substrate-api-sidecar\n ```\n\n For more configuration details, see the [Configuration](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#configuration){target=\\_blank} section of the Sidecar API documentation.\n\nOnce the Sidecar API is running, you’ll see output similar to this:\n\n
    \n SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io substrate-api-sidecar\n
    \n SAS:\n 📦 LOG:\n ✅ LEVEL: \"info\"\n ✅ JSON: false\n ✅ FILTER_RPC: false\n ✅ STRIP_ANSI: false\n ✅ WRITE: false\n ✅ WRITE_PATH: \"/opt/homebrew/lib/node_modules/@substrate/api-sidecar/build/src/logs\"\n ✅ WRITE_MAX_FILE_SIZE: 5242880\n ✅ WRITE_MAX_FILES: 5\n 📦 SUBSTRATE:\n ✅ URL: \"wss://polkadot-asset-hub-rpc.polkadot.io\"\n ✅ TYPES_BUNDLE: undefined\n ✅ TYPES_CHAIN: undefined\n ✅ TYPES_SPEC: undefined\n ✅ TYPES: undefined\n ✅ CACHE_CAPACITY: undefined\n 📦 EXPRESS:\n ✅ BIND_HOST: \"127.0.0.1\"\n ✅ PORT: 8080\n ✅ KEEP_ALIVE_TIMEOUT: 5000\n 📦 METRICS:\n ✅ ENABLED: false\n ✅ PROM_HOST: \"127.0.0.1\"\n ✅ PROM_PORT: 9100\n ✅ LOKI_HOST: \"127.0.0.1\"\n ✅ LOKI_PORT: 3100\n ✅ INCLUDE_QUERYPARAMS: false\n
    \n 2024-11-06 08:06:01 info: Version: 19.3.0\n 2024-11-06 08:06:02 warn: API/INIT: RPC methods not decorated: chainHead_v1_body, chainHead_v1_call, chainHead_v1_continue, chainHead_v1_follow, chainHead_v1_header, chainHead_v1_stopOperation, chainHead_v1_storage, chainHead_v1_unfollow, chainHead_v1_unpin, chainSpec_v1_chainName, chainSpec_v1_genesisHash, chainSpec_v1_properties, transactionWatch_v1_submitAndWatch, transactionWatch_v1_unwatch, transaction_v1_broadcast, transaction_v1_stop\n 2024-11-06 08:06:02 info: Connected to chain Polkadot Asset Hub on the statemint client at wss://polkadot-asset-hub-rpc.polkadot.io\n 2024-11-06 08:06:02 info: Listening on http://127.0.0.1:8080/\n 2024-11-06 08:06:02 info: Check the root endpoint (http://127.0.0.1:8080/) to see the available endpoints for the current node\n
    \nWith Sidecar running, you can access the exposed endpoints via a browser, [`Postman`](https://www.postman.com/){target=\\_blank}, [`curl`](https://curl.se/){target=\\_blank}, or your preferred tool."} -{"page_id": "reference-tools-sidecar", "page_title": "Sidecar REST API", "index": 4, "depth": 3, "title": "Endpoints", "anchor": "endpoints", "start_char": 5688, "end_char": 7028, "estimated_token_count": 394, "token_estimator": "heuristic-v1", "text": "### Endpoints\n\nSidecar API provides a set of REST endpoints that allow you to query different aspects of the chain, including blocks, accounts, and transactions. Each endpoint offers specific insights into the chain’s state and activities.\n\nFor example, to retrieve the version of the node, use the `/node/version` endpoint:\n\n```bash\ncurl -X 'GET' \\\n 'http://127.0.0.1:8080/node/version' \\\n -H 'accept: application/json'\n```\n\nAlternatively, you can access `http://127.0.0.1:8080/node/version` directly in a browser since it’s a `GET` request.\n\nIn response, you’ll see output similar to this (assuming you’re connected to Polkadot Asset Hub):\n\n
    \n curl -X 'GET' 'http://127.0.0.1:8080/node/version' -H 'accept: application/json'\n
    \n {\n \"clientVersion\": \"1.16.1-835e0767fe8\",\n \"clientImplName\": \"statemint\",\n \"chain\": \"Polkadot Asset Hub\"\n }\n
    \nFor a complete list of available endpoints and their documentation, visit the [Sidecar API list endpoints](https://paritytech.github.io/substrate-api-sidecar/dist/){target=\\_blank}. You can learn about the endpoints and how to use them in your applications."} -{"page_id": "reference-tools-sidecar", "page_title": "Sidecar REST API", "index": 5, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 7028, "end_char": 7309, "estimated_token_count": 67, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nTo dive deeper, refer to the [official Sidecar documentation](https://github.com/paritytech/substrate-api-sidecar?tab=readme-ov-file#substrateapi-sidecar){target=\\_blank}. This provides a comprehensive guide to the available configurations and advanced usage."} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 18, "end_char": 403, "estimated_token_count": 68, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nSubxt is a Rust library designed to interact with Polkadot SDK-based blockchains. It provides a type-safe interface for submitting transactions, querying on-chain state, and performing other blockchain interactions. By leveraging Rust's strong type system, subxt ensures that your code is validated at compile time, reducing runtime errors and improving reliability."} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 403, "end_char": 734, "estimated_token_count": 80, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore using subxt, ensure you have the following requirements:\n\n- Rust and Cargo installed on your system. You can install them using [Rustup](https://rustup.rs/){target=\\_blank}.\n- A Rust project initialized. If you don't have one, create it with:\n ```bash\n cargo new my_project && cd my_project\n ```"} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 2, "depth": 2, "title": "Installation", "anchor": "installation", "start_char": 734, "end_char": 2796, "estimated_token_count": 510, "token_estimator": "heuristic-v1", "text": "## Installation\n\nTo use subxt in your project, you must install the necessary dependencies. Each plays a specific role in enabling interaction with the blockchain:\n\n1. **Install the subxt CLI**: [`subxt-cli`](https://crates.io/crates/subxt-cli){target=\\_blank} is a command-line tool that provides utilities for working with Polkadot SDK metadata. In the context of subxt, it is essential to download chain metadata, which is required to generate type-safe Rust interfaces for interacting with the blockchain. Install it using the following:\n\n ```bash\n cargo install subxt-cli@0.44.0\n ```\n\n2. **Add core dependencies**: These dependencies are essential for interacting with the blockchain.\n\n - **[subxt](https://crates.io/crates/subxt){target=\\_blank}**: The main library for communicating with Polkadot SDK nodes. It handles RPC requests, encoding/decoding, and type generation.\n\n ```bash\n cargo add subxt@0.44.0\n ```\n\n - **[subxt-signer](https://crates.io/crates/subxt-signer){target=\\_blank}**: Provides cryptographic functionality for signing transactions. Without this, you can only read data but cannot submit transactions.\n\n ```bash\n cargo add subxt-signer@0.44.0\n ```\n\n - **[tokio](https://crates.io/crates/tokio){target=\\_blank}**: An asynchronous runtime for Rust. Since blockchain operations are async, Tokio enables the efficient handling of network requests. The `rt` feature enables Tokio's runtime, including the current-thread single-threaded scheduler, which is necessary for async execution. The `macros` feature provides procedural macros like `#[tokio::main]` to simplify runtime setup.\n\n ```bash\n cargo add tokio@1.44.2 --features rt,macros\n ```\n\n After adding the dependencies, your `Cargo.toml` should look like this:\n\n ```toml\n [package]\n name = \"my_project\"\n version = \"0.1.0\"\n edition = \"2021\"\n\n [dependencies]\n subxt = \"0.41.0\"\n subxt-signer = \"0.41.0\"\n tokio = { version = \"1.44.2\", features = [\"rt\", \"macros\"] }\n\n ```"} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 3, "depth": 2, "title": "Get Started", "anchor": "get-started", "start_char": 2796, "end_char": 2973, "estimated_token_count": 29, "token_estimator": "heuristic-v1", "text": "## Get Started\n\nThis guide will walk you through the fundamental operations of subxt, from setting up your environment to executing transactions and querying blockchain state."} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 4, "depth": 3, "title": "Download Chain Metadata", "anchor": "download-chain-metadata", "start_char": 2973, "end_char": 3364, "estimated_token_count": 78, "token_estimator": "heuristic-v1", "text": "### Download Chain Metadata\n\nBefore interacting with a blockchain, you need to retrieve its metadata. This metadata defines storage structures, extrinsics, and other runtime details. Use the `subxt-cli` tool to download the metadata, replacing `INSERT_NODE_URL` with the URL of the node you want to interact with:\n\n```bash\nsubxt metadata --url INSERT_NODE_URL > polkadot_metadata.scale\n```"} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 5, "depth": 3, "title": "Generate Type-Safe Interfaces", "anchor": "generate-type-safe-interfaces", "start_char": 3364, "end_char": 5229, "estimated_token_count": 529, "token_estimator": "heuristic-v1", "text": "### Generate Type-Safe Interfaces\n\nUse the `#[subxt::subxt]` macro to generate a type-safe Rust interface from the downloaded metadata:\n\n```rust\n// Generate an interface that we can use from the node's metadata.\n#[subxt::subxt(runtime_metadata_path = \"./polkadot_metadata.scale\")]\npub mod polkadot {}\n```\n\nOnce subxt interfaces are generated, you can interact with your node in the following ways. You can use the links below to view the related subxt documentation:\n\n- **[Transactions](https://docs.rs/subxt/latest/subxt/book/usage/transactions/index.html){target=\\_blank}**: Builds and submits transactions, monitors their inclusion in blocks, and retrieves associated events.\n- **[Storage](https://docs.rs/subxt/latest/subxt/book/usage/storage/index.html){target=\\_blank}**: Enables querying of node storage data.\n- **[Events](https://docs.rs/subxt/latest/subxt/book/usage/events/index.html){target=\\_blank}**: Retrieves events emitted from recent blocks.\n- **[Constants](https://docs.rs/subxt/latest/subxt/book/usage/constants/index.html){target=\\_blank}**: Accesses constant values stored in nodes that remain unchanged across a specific runtime version.\n- **[Blocks](https://docs.rs/subxt/latest/subxt/book/usage/blocks/index.html){target=\\_blank}**: Loads recent blocks or subscribes to new/finalized blocks, allowing examination of extrinsics, events, and storage at those blocks.\n- **[Runtime APIs](https://docs.rs/subxt/latest/subxt/book/usage/runtime_apis/index.html){target=\\_blank}**: Makes calls into pallet runtime APIs to fetch data.\n- **[Custom values](https://docs.rs/subxt/latest/subxt/book/usage/custom_values/index.html){target=\\_blank}**: Accesses \"custom values\" contained within metadata.\n- **[Raw RPC calls](https://docs.rs/subxt/latest/subxt/book/usage/rpc/index.html){target=\\_blank}**: Facilitates raw RPC requests to compatible nodes."} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 6, "depth": 3, "title": "Initialize the Subxt Client", "anchor": "initialize-the-subxt-client", "start_char": 5229, "end_char": 6115, "estimated_token_count": 229, "token_estimator": "heuristic-v1", "text": "### Initialize the Subxt Client\n\nTo interact with a blockchain node using subxt, create an asynchronous main function and initialize the client. Replace `INSERT_NODE_URL` with the URL of your target node:\n\n```rust\nuse std::str::FromStr;\nuse subxt::utils::AccountId32;\nuse subxt::{OnlineClient, PolkadotConfig};\nuse subxt_signer::{bip39::Mnemonic,sr25519::Keypair};\n\n// Generate an interface that we can use from the node's metadata.\n#[subxt::subxt(runtime_metadata_path = \"./polkadot_metadata.scale\")]\npub mod polkadot {}\n\n#[tokio::main(flavor = \"current_thread\")]\nasync fn main() -> Result<(), Box> {\n // Define the node URL.\n const NODE_URL: &str = \"INSERT_NODE_URL\";\n\n // Initialize the Subxt client to interact with the blockchain.\n let api = OnlineClient::::from_url(NODE_URL).await?;\n\n // Your code here...\n\n Ok(())\n}\n```"} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 7, "depth": 3, "title": "Read Chain Data", "anchor": "read-chain-data", "start_char": 6115, "end_char": 7470, "estimated_token_count": 296, "token_estimator": "heuristic-v1", "text": "### Read Chain Data\n\nsubxt provides multiple ways to access on-chain data:\n\n- **Constants**: Constants are predefined values in the runtime that remain unchanged unless modified by a runtime upgrade.\n\n For example, to retrieve the existential deposit, use:\n \n ```rust\n // A query to obtain some constant.\n let constant_query = polkadot::constants().balances().existential_deposit();\n\n // Obtain the value.\n let value = api.constants().at(&constant_query)?;\n\n println!(\"Existential deposit: {:?}\", value);\n ```\n\n- **State**: State refers to the current chain data, which updates with each block.\n\n To fetch account information, replace `INSERT_ADDRESS` with the address you want to fetch data from and use:\n\n ```rust\n // Define the target account address.\n const ADDRESS: &str = \"INSERT_ADDRESS\";\n let account = AccountId32::from_str(ADDRESS).unwrap();\n\n // Build a storage query to access account information.\n let storage_query = polkadot::storage().system().account(&account.into());\n\n // Fetch the latest state for the account.\n let result = api\n .storage()\n .at_latest()\n .await?\n .fetch(&storage_query)\n .await?\n .unwrap();\n\n println!(\"Account info: {:?}\", result);\n ```"} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 8, "depth": 3, "title": "Submit Transactions", "anchor": "submit-transactions", "start_char": 7470, "end_char": 8944, "estimated_token_count": 311, "token_estimator": "heuristic-v1", "text": "### Submit Transactions\n\nTo submit a transaction, you must construct an extrinsic, sign it with your private key, and send it to the blockchain. Replace `INSERT_DEST_ADDRESS` with the recipient's address, `INSERT_AMOUNT` with the amount to transfer, and `INSERT_SECRET_PHRASE` with the sender's mnemonic phrase:\n\n```rust\n // Define the recipient address and transfer amount.\n const DEST_ADDRESS: &str = \"INSERT_DEST_ADDRESS\";\n const AMOUNT: u128 = INSERT_AMOUNT;\n\n // Convert the recipient address into an `AccountId32`.\n let dest = AccountId32::from_str(DEST_ADDRESS).unwrap();\n\n // Build the balance transfer extrinsic.\n let balance_transfer_tx = polkadot::tx()\n .balances()\n .transfer_allow_death(dest.into(), AMOUNT);\n\n // Load the sender's keypair from a mnemonic phrase.\n const SECRET_PHRASE: &str = \"INSERT_SECRET_PHRASE\";\n let mnemonic = Mnemonic::parse(SECRET_PHRASE).unwrap();\n let sender_keypair = Keypair::from_phrase(&mnemonic, None).unwrap();\n\n // Sign and submit the extrinsic, then wait for it to be finalized.\n let events = api\n .tx()\n .sign_and_submit_then_watch_default(&balance_transfer_tx, &sender_keypair)\n .await?\n .wait_for_finalized_success()\n .await?;\n\n // Check for a successful transfer event.\n if let Some(event) = events.find_first::()? {\n println!(\"Balance transfer successful: {:?}\", event);\n }\n```"} -{"page_id": "reference-tools-subxt", "page_title": "Subxt Rust API", "index": 9, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 8944, "end_char": 9174, "estimated_token_count": 57, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nNow that you've covered the basics dive into the official [subxt documentation](https://docs.rs/subxt/latest/subxt/book/index.html){target=\\_blank} for comprehensive reference materials and advanced features."} -{"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 13, "end_char": 787, "estimated_token_count": 134, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nAs described in the [Interoperability](/develop/interoperability){target=\\_blank} section, XCM (Cross-Consensus Messaging) is a protocol used in the Polkadot and Kusama ecosystems to enable communication and interaction between chains. It facilitates cross-chain communication, allowing assets, data, and messages to flow seamlessly across the ecosystem.\n\nAs XCM is central to enabling communication between blockchains, developers need robust tools to help interact with, build, and test XCM messages. Several XCM tools simplify working with the protocol by providing libraries, frameworks, and utilities that enhance the development process, ensuring that applications built within the Polkadot ecosystem can efficiently use cross-chain functionalities."} -{"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 1, "depth": 2, "title": "Popular XCM Tools", "anchor": "popular-xcm-tools", "start_char": 787, "end_char": 809, "estimated_token_count": 5, "token_estimator": "heuristic-v1", "text": "## Popular XCM Tools"} -{"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 2, "depth": 3, "title": "Moonsong Labs XCM Tools", "anchor": "moonsong-labs-xcm-tools", "start_char": 809, "end_char": 2190, "estimated_token_count": 333, "token_estimator": "heuristic-v1", "text": "### Moonsong Labs XCM Tools\n\n[Moonsong Labs XCM Tools](https://github.com/Moonsong-Labs/xcm-tools){target=\\_blank} provides a collection of scripts for managing and testing XCM operations between Polkadot SDK-based runtimes. These tools allow performing tasks like asset registration, channel setup, and XCM initialization. Key features include:\n\n- **Asset registration**: Registers assets, setting units per second (up-front fees), and configuring error (revert) codes.\n- **XCM initializer**: Initializes XCM, sets default XCM versions, and configures revert codes for XCM-related precompiles.\n- **HRMP manipulator**: Manages HRMP channel actions, including opening, accepting, or closing channels.\n- **XCM-Transactor-Info-Setter**: Configures transactor information, including extra weight and fee settings.\n- **Decode XCM**: Decodes XCM messages on the relay chain or parachains to help interpret cross-chain communication.\n\nTo get started, clone the repository and install the required dependencies:\n\n```bash\ngit clone https://github.com/Moonsong-Labs/xcm-tools && \ncd xcm-tools &&\nyarn install\n```\n\nFor a full overview of each script, visit the [scripts](https://github.com/Moonsong-Labs/xcm-tools/tree/main/scripts){target=\\_blank} directory or refer to the [official documentation](https://github.com/Moonsong-Labs/xcm-tools/blob/main/README.md){target=\\_blank} on GitHub."} -{"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 3, "depth": 3, "title": "ParaSpell", "anchor": "paraspell", "start_char": 2190, "end_char": 2667, "estimated_token_count": 86, "token_estimator": "heuristic-v1", "text": "### ParaSpell\n\n[ParaSpell](/reference/tools/paraspell/){target=\\_blank} is a collection of open-source XCM tools that streamline cross-chain asset transfers and interactions across the Polkadot and Kusama ecosystems. It provides developers with an intuitive interface to build, test, and deploy interoperable dApps, featuring message composition, decoding, and practical utilities for parachain interactions that simplify debugging and cross-chain communication optimization."} -{"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 4, "depth": 3, "title": "Astar XCM Tools", "anchor": "astar-xcm-tools", "start_char": 2667, "end_char": 4207, "estimated_token_count": 369, "token_estimator": "heuristic-v1", "text": "### Astar XCM Tools\n\nThe [Astar parachain](https://github.com/AstarNetwork/Astar/tree/master){target=\\_blank} offers a crate with a set of utilities for interacting with the XCM protocol. The [xcm-tools](https://github.com/AstarNetwork/Astar/tree/master/bin/xcm-tools){target=\\_blank} crate provides a straightforward method for users to locate a sovereign account or calculate an XC20 asset ID. Some commands included by the xcm-tools crate allow users to perform the following tasks:\n\n- **Sovereign accounts**: Obtain the sovereign account address for any parachain, either on the Relay Chain or for sibling parachains, using a simple command.\n- **XC20 EVM addresses**: Generate XC20-compatible Ethereum addresses for assets by entering the asset ID, making it easy to integrate assets across Ethereum-compatible environments.\n- **Remote accounts**: Retrieve remote account addresses needed for multi-location compatibility, using flexible options to specify account types and parachain IDs.\n\nTo start using these tools, clone the [Astar repository](https://github.com/AstarNetwork/Astar){target=\\_blank} and compile the xcm-tools package:\n\n```bash\ngit clone https://github.com/AstarNetwork/Astar &&\ncd Astar &&\ncargo build --release -p xcm-tools\n```\n\nAfter compiling, verify the setup with the following command:\n\n```bash\n./target/release/xcm-tools --help\n```\nFor more details on using Astar xcm-tools, consult the [official documentation](https://docs.astar.network/docs/learn/interoperability/xcm/integration/tools/){target=\\_blank}."} -{"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 5, "depth": 3, "title": "Chopsticks", "anchor": "chopsticks", "start_char": 4207, "end_char": 4517, "estimated_token_count": 65, "token_estimator": "heuristic-v1", "text": "### Chopsticks\n\nThe Chopsticks library provides XCM functionality for testing XCM messages across networks, enabling you to fork multiple parachains along with a relay chain. For further details, see the [Chopsticks documentation](/tutorials/polkadot-sdk/testing/fork-live-chains/){target=\\_blank} about XCM."} -{"page_id": "reference-tools-xcm-tools", "page_title": "XCM Tools", "index": 6, "depth": 3, "title": "Moonbeam XCM SDK", "anchor": "moonbeam-xcm-sdk", "start_char": 4517, "end_char": 6146, "estimated_token_count": 385, "token_estimator": "heuristic-v1", "text": "### Moonbeam XCM SDK\n\nThe [Moonbeam XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk){target=\\_blank} enables developers to easily transfer assets between chains, either between parachains or between a parachain and the relay chain, within the Polkadot/Kusama ecosystem. With the SDK, you don't need to worry about determining the [Multilocation](https://github.com/polkadot-fellows/xcm-format?tab=readme-ov-file#7-universal-consensus-location-identifiers){target=\\_blank} of the origin or destination assets or which extrinsics are used on which networks.\n\nThe SDK consists of two main packages:\n\n- **[XCM SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/sdk){target=\\_blank}**: Core SDK for executing XCM transfers between chains in the Polkadot/Kusama ecosystem.\n- **[MRL SDK](https://github.com/moonbeam-foundation/xcm-sdk/tree/main/packages/mrl){target=\\_blank}**: Extension of the XCM SDK for transferring liquidity into and across the Polkadot ecosystem from other ecosystems like Ethereum.\n\nKey features include:\n\n- **Simplified asset transfers**: Abstracts away complex multilocation determinations and extrinsic selection.\n- **Cross-ecosystem support**: Enables transfers between Polkadot/Kusama chains and external ecosystems.\n- **Developer-friendly API**: Provides intuitive interfaces for cross-chain functionality.\n- **Comprehensive documentation**: Includes usage guides and API references for both packages.\n\nFor detailed usage examples and API documentation, visit the [official Moonbeam XCM SDK documentation](https://moonbeam-foundation.github.io/xcm-sdk/latest/){target=\\_blank}."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 0, "end_char": 1097, "estimated_token_count": 199, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe Technical Reference section provides comprehensive documentation of Polkadot's architecture, core concepts, and development tooling. Whether you're exploring how Polkadot's relay chain coordinates parachains, understanding governance mechanisms, or building applications on the network, this reference covers the technical foundations you need.\n\nPolkadot is a multi-chain network that enables diverse, interconnected blockchains to share security and communicate seamlessly. Understanding how these components interact from the [relay chain](/polkadot-protocol/glossary#relay-chain){target=\\_blank} that validates [parachains](/polkadot-protocol/glossary#parachain){target=\\_blank} to the [governance](/reference/glossary#governance){target=\\_blank} mechanisms that evolve the protocol is essential for developers, validators, and network participants.\n\nThis guide organizes technical documentation across five core areas: Polkadot Hub, Parachains, On-Chain Governance, Glossary, and Tools, each providing detailed information on different aspects of the Polkadot ecosystem."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 1, "depth": 2, "title": "Polkadot Hub", "anchor": "polkadot-hub", "start_char": 1097, "end_char": 2378, "estimated_token_count": 247, "token_estimator": "heuristic-v1", "text": "## Polkadot Hub\n\n[Polkadot Hub](/reference/polkadot-hub/){target=\\_blank} is the entry point to Polkadot for all users and application developers. It provides access to essential Web3 services, including smart contracts, staking, governance, identity management, and cross-ecosystem interoperability—without requiring you to deploy or manage a parachain.\n\nThe Hub encompasses a set of core functionality that enables developers and users to build and interact with applications on Polkadot. Key capabilities include:\n\n- **Smart contracts**: Deploy Ethereum-compatible smart contracts and build decentralized applications.\n- **Assets and tokens**: Create, manage, and transfer fungible tokens and NFTs across the ecosystem.\n- **Staking**: Participate in network security and earn rewards by staking DOT.\n- **Governance**: Vote on proposals and participate in Polkadot's decentralized decision-making through OpenGov.\n- **Identity services**: Register and manage on-chain identities, enabling access to governance roles and network opportunities.\n- **Cross-chain interoperability**: Leverage XCM messaging to interact securely with other chains in the Polkadot ecosystem.\n- **Collectives and DAOs**: Participate in governance collectives and decentralized autonomous organizations."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 2, "depth": 2, "title": "Parachains", "anchor": "parachains", "start_char": 2378, "end_char": 3697, "estimated_token_count": 293, "token_estimator": "heuristic-v1", "text": "## Parachains\n\n[Parachains](/reference/parachains/){target=\\_blank} are specialized blockchains that connect to the Polkadot relay chain, inheriting its security while maintaining their own application-specific logic. The parachains documentation covers:\n\n- **Accounts**: Deep dive into account types, storage, and management on parachains.\n- **Blocks, transactions and fees**: Understand block production, transaction inclusion, and fee mechanisms.\n- **Consensus**: Learn how parachain blocks are validated and finalized through the relay chain's consensus.\n- **Chain data**: Explore data structures, storage layouts, and state management.\n- **Cryptography**: Study cryptographic primitives used in Polkadot SDK-based chains.\n- **Data encoding**: Understand how data is encoded and decoded for blockchain compatibility.\n- **Networks**: Learn about networking protocols and peer-to-peer communication.\n- **Interoperability**: Discover [Cross-Consensus Messaging (XCM)](/parachains/interoperability/get-started/){target=\\_blank}, the standard for cross-chain communication.\n- **Randomness**: Understand how randomness is generated and used in Polkadot chains.\n- **Node and runtime**: Learn about parachain nodes, runtime environments, and the [Polkadot SDK](https://github.com/paritytech/polkadot-sdk){target=\\_blank}."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 3, "depth": 2, "title": "On-Chain Governance", "anchor": "on-chain-governance", "start_char": 3697, "end_char": 4577, "estimated_token_count": 170, "token_estimator": "heuristic-v1", "text": "## On-Chain Governance\n\n[On-Chain governance](/reference/governance/){target=\\_blank} is the decentralized decision-making mechanism for the Polkadot network. It manages the evolution and modification of the network's runtime logic, enabling community oversight and approval for proposed changes. The governance documentation details:\n\n- **OpenGov framework**: Understand Polkadot's next-generation governance system with enhanced delegation, flexible tracks, and simultaneous referendums.\n- **Origins and tracks**: Learn how governance proposals are categorized, prioritized, and executed based on their privilege level and complexity.\n- **Voting and delegation**: Explore conviction voting, vote delegation, and how token holders participate in governance.\n- **Governance evolution**: See how Polkadot's governance has evolved from Governance V1 to the current OpenGov system."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 4, "depth": 2, "title": "Glossary", "anchor": "glossary", "start_char": 4577, "end_char": 5018, "estimated_token_count": 90, "token_estimator": "heuristic-v1", "text": "## Glossary\n\nThe [Glossary](/reference/glossary/){target=\\_blank} provides quick-reference definitions for Polkadot-specific terminology. Essential terms include:\n\n- Blockchain concepts (blocks, transactions, state)\n- Consensus mechanisms (validators, collators, finality)\n- Polkadot-specific terms (relay chain, parachain, XCM, FRAME)\n- Network components (nodes, runtimes, storage)\n- Governance terminology (origins, tracks, referendums)"} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 5, "depth": 2, "title": "Tools", "anchor": "tools", "start_char": 5018, "end_char": 6285, "estimated_token_count": 349, "token_estimator": "heuristic-v1", "text": "## Tools\n\nThe [Tools](/reference/tools/){target=\\_blank} section documents essential development and interaction tools for the Polkadot ecosystem:\n\n- **Light clients**: Lightweight solutions for interacting with the network without running full nodes.\n- **JavaScript/TypeScript tools**: Libraries like [Polkadot.js API](/reference/tools/polkadot-js-api/){target=\\_blank} and [PAPI](/reference/tools/papi/){target=\\_blank} for building applications.\n- **Rust tools**: [Polkadart](/reference/tools/polkadart/){target=\\_blank} and other Rust-based libraries for SDK development.\n- **Python tools**: [py-substrate-interface](/reference/tools/py-substrate-interface/){target=\\_blank} for Python developers.\n- **Testing and development**: Tools like [Moonwall](/reference/tools/moonwall/){target=\\_blank}, [Chopsticks](/reference/tools/chopsticks/){target=\\_blank}, and [Omninode](/reference/tools/omninode/){target=\\_blank} for smart contract and parachain testing.\n- **Indexing and monitoring**: [Sidecar](/reference/tools/sidecar/){target=\\_blank} for data indexing and [Dedot](/reference/tools/dedot/){target=\\_blank} for substrate interaction.\n- **Cross-chain tools**: [ParaSpell](/reference/tools/paraspell/){target=\\_blank} for XCM integration and asset transfers."} -{"page_id": "reference", "page_title": "Technical Reference Overview", "index": 6, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 6285, "end_char": 7648, "estimated_token_count": 334, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor detailed exploration of specific areas, proceed to any of the main sections:\n\n
    \n\n- Learn **Polkadot Hub**\n\n ---\n\n Understand the relay chain's role in coordinating parachains, providing shared security, and enabling governance.\n\n [:octicons-arrow-right-24: Reference](/reference/polkadot-hub/)\n\n- Learn **Parachains**\n\n ---\n\n Deep dive into parachain architecture, consensus, data structures, and building application-specific blockchains.\n\n [:octicons-arrow-right-24: Reference](/reference/parachains/)\n\n- Learn **On-Chain Governance**\n\n ---\n\n Explore Polkadot's decentralized governance framework and how to participate in network decision-making.\n\n [:octicons-arrow-right-24: Reference](/reference/governance/)\n\n- Guide **Glossary**\n\n ---\n\n Quick reference for Polkadot-specific terminology and concepts used throughout the documentation.\n\n [:octicons-arrow-right-24: Reference](/reference/glossary/)\n\n- Guide **Tools**\n\n ---\n\n Discover development tools, libraries, and frameworks for building and interacting with Polkadot.\n\n [:octicons-arrow-right-24: Reference](/reference/tools/)\n\n
    "} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 37, "end_char": 1215, "estimated_token_count": 242, "token_estimator": "heuristic-v1", "text": "## Introduction\n\n[Chopsticks](https://github.com/AcalaNetwork/chopsticks/){target=\\_blank}, developed by the [Acala Foundation](https://github.com/AcalaNetwork){target=\\_blank}, is a versatile tool tailored for developers working on Polkadot SDK-based blockchains. With Chopsticks, you can fork live chains locally, replay blocks to analyze extrinsics, and simulate complex scenarios like XCM interactions all without deploying to a live network.\n\nThis guide walks you through installing Chopsticks and provides information on configuring a local blockchain fork. By streamlining testing and experimentation, Chopsticks empowers developers to innovate and accelerate their blockchain projects within the Polkadot ecosystem.\n\nFor additional support and information, please reach out through [GitHub Issues](https://github.com/AcalaNetwork/chopsticks/issues){target=_blank}.\n\n!!! warning\n Chopsticks uses [Smoldot](https://github.com/smol-dot/smoldot){target=_blank} light client, which only supports the native Polkadot SDK API. Consequently, a Chopsticks-based fork doesn't support Ethereum JSON-RPC calls, meaning you cannot use it to fork your chain and connect Metamask."} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 1215, "end_char": 1522, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore you begin, ensure you have the following installed:\n\n- [Node.js](https://nodejs.org/en/){target=\\_blank}.\n- A package manager such as [npm](https://www.npmjs.com/){target=\\_blank}, which should be installed with Node.js by default, or [Yarn](https://yarnpkg.com/){target=\\_blank}."} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 2, "depth": 2, "title": "Install Chopsticks", "anchor": "install-chopsticks", "start_char": 1522, "end_char": 1814, "estimated_token_count": 55, "token_estimator": "heuristic-v1", "text": "## Install Chopsticks\n\nYou can install Chopsticks globally or locally in your project. Choose the option that best fits your development workflow. This documentation explains the features of Chopsticks version `1.2.2`. Make sure you're using the correct version to match these instructions."} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 3, "depth": 3, "title": "Global Installation", "anchor": "global-installation", "start_char": 1814, "end_char": 2057, "estimated_token_count": 61, "token_estimator": "heuristic-v1", "text": "### Global Installation\n\nTo install Chopsticks globally, allowing you to use it across multiple projects, run:\n\n```bash\nnpm i -g @acala-network/chopsticks@1.2.2\n```\n\nNow, you should be able to run the `chopsticks` command from your terminal."} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 4, "depth": 3, "title": "Local Installation", "anchor": "local-installation", "start_char": 2057, "end_char": 2546, "estimated_token_count": 128, "token_estimator": "heuristic-v1", "text": "### Local Installation\n\nTo use Chopsticks in a specific project, first create a new directory and initialize a Node.js project:\n\n```bash\nmkdir my-chopsticks-project\ncd my-chopsticks-project\nnpm init -y\n```\n\nThen, install Chopsticks as a local dependency:\n\n```bash\nnpm i @acala-network/chopsticks@1.2.2\n```\n\nFinally, you can run Chopsticks using the `npx` command. To see all available options and commands, run it with the `--help` flag:\n\n```bash\nnpx @acala-network/chopsticks --help\n```"} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 5, "depth": 2, "title": "Configure Chopsticks", "anchor": "configure-chopsticks", "start_char": 2546, "end_char": 3895, "estimated_token_count": 360, "token_estimator": "heuristic-v1", "text": "## Configure Chopsticks\n\nTo run Chopsticks, you need to configure some parameters. This can be set either through using a configuration file or the command line interface (CLI). The parameters that can be configured are as follows:\n\n- **`genesis`**: The link to a parachain's raw genesis file to build the fork from, instead of an endpoint.\n- **`timestamp`**: Timestamp of the block to fork from.\n- **`endpoint`**: The endpoint of the parachain to fork.\n- **`block`**: Use to specify at which block hash or number to replay the fork.\n- **`wasm-override`**: Path of the Wasm to use as the parachain runtime, instead of an endpoint's runtime.\n- **`db`**: Path to the name of the file that stores or will store the parachain's database.\n- **`config`**: Path or URL of the config file.\n- **`port`**: The port to expose an endpoint on.\n- **`build-block-mode`**: How blocks should be built in the fork: batch, manual, instant.\n- **`import-storage`**: A pre-defined JSON/YAML storage path to override in the parachain's storage.\n- **`allow-unresolved-imports`**: Whether to allow Wasm unresolved imports when using a Wasm to build the parachain.\n- **`html`**: Include to generate storage diff preview between blocks.\n- **`mock-signature-host`**: Mock signature host so that any signature starts with `0xdeadbeef` and filled by `0xcd` is considered valid."} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 6, "depth": 3, "title": "Configuration File", "anchor": "configuration-file", "start_char": 3895, "end_char": 5094, "estimated_token_count": 271, "token_estimator": "heuristic-v1", "text": "### Configuration File\n\nThe Chopsticks source repository includes a collection of [YAML](https://yaml.org/){target=\\_blank} files that can be used to set up various Polkadot SDK chains locally. You can download these configuration files from the [repository's `configs` folder](https://github.com/AcalaNetwork/chopsticks/tree/master/configs){target=\\_blank}.\n\nAn example of a configuration file for Polkadot is as follows:\n\n{% raw %}\n```yaml\nendpoint:\n - wss://rpc.ibp.network/polkadot\n - wss://polkadot-rpc.dwellir.com\nmock-signature-host: true\nblock: ${env.POLKADOT_BLOCK_NUMBER}\ndb: ./db.sqlite\nruntime-log-level: 5\n\nimport-storage:\n System:\n Account:\n - - - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\n - providers: 1\n data:\n free: '10000000000000000000'\n ParasDisputes:\n $removePrefix: ['disputes'] # those can makes block building super slow\n\n```\n{% endraw %}\n\nThe configuration file allows you to modify the storage of the forked network by rewriting the pallet, state component and value that you want to change. For example, Polkadot's file rewrites Alice's `system.Account` storage so that the free balance is set to `10000000000000000000`."} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 7, "depth": 3, "title": "CLI Flags", "anchor": "cli-flags", "start_char": 5094, "end_char": 5275, "estimated_token_count": 35, "token_estimator": "heuristic-v1", "text": "### CLI Flags\n\nAlternatively, all settings (except for genesis and timestamp) can be configured via command-line flags, providing a comprehensive method to set up the environment."} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 8, "depth": 2, "title": "WebSocket Commands", "anchor": "websocket-commands", "start_char": 5275, "end_char": 10559, "estimated_token_count": 1272, "token_estimator": "heuristic-v1", "text": "## WebSocket Commands\n\nChopstick's internal WebSocket server has special endpoints that allow the manipulation of the local Polkadot SDK chain.\n\nThese are the methods that can be invoked and their parameters:\n\n- **dev_newBlock** (newBlockParams): Generates one or more new blocks.\n\n === \"Parameters\"\n\n - **`newBlockParams` ++\"NewBlockParams\"++**: The parameters to build the new block with. Where the `NewBlockParams` interface includes the following properties.\n\n - **`count` ++\"number\"++**: The number of blocks to build.\n - **`dmp` ++\"{ msg: string, sentAt: number }[]\"++**: The downward messages to include in the block.\n - **`hrmp` ++\"Record\"++**: The horizontal messages to include in the block.\n - **`to` ++\"number\"++**: The block number to build to.\n - **`transactions` ++\"string[]\"++**: The transactions to include in the block.\n - **`ump` ++\"Record\"++**: The upward messages to include in the block.\n - **`unsafeBlockHeight` ++\"number\"++**: Build block using a specific block height (unsafe).\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_newBlock', { count: 1 });\n }\n\n main();\n\n ```\n\n- **dev_setBlockBuildMode** (buildBlockMode): Sets block build mode.\n\n === \"Parameter\"\n \n - **`buildBlockMode` ++\"BuildBlockMode\"++**: The build mode. Can be any of the following modes:\n\n ```ts\n export enum BuildBlockMode {\n Batch = 'Batch', /** One block per batch (default) */\n Instant = 'Instant', /** One block per transaction */\n Manual = 'Manual', /** Only build when triggered */\n }\n ```\n \n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_setBlockBuildMode', 'Instant');\n }\n\n main();\n\n ```\n\n- **dev_setHead** (hashOrNumber): Sets the head of the blockchain to a specific hash or number.\n\n === \"Parameter\"\n\n - **`hashOrNumber` ++\"string | number\"++**: The block hash or number to set as head.\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_setHead', 500);\n }\n\n main();\n\n ```\n\n- **dev_setRuntimeLogLevel** (runtimeLogLevel): Sets the runtime log level.\n\n === \"Parameter\"\n\n - **`runtimeLogLevel` ++\"number\"++**: The runtime log level to set.\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_setRuntimeLogLevel', 1);\n }\n\n main();\n\n ```\n\n- **dev_setStorage** (values, blockHash): Creates or overwrites the value of any storage.\n\n === \"Parameters\"\n\n - **`values` ++\"object\"++**: JSON object resembling the path to a storage value.\n - **`blockHash` ++\"string\"++**: The block hash to set the storage value.\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n import { Keyring } from '@polkadot/keyring';\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n const keyring = new Keyring({ type: 'ed25519' });\n const bob = keyring.addFromUri('//Bob');\n const storage = {\n System: {\n Account: [[[bob.address], { data: { free: 100000 }, nonce: 1 }]],\n },\n };\n await api.rpc('dev_setStorage', storage);\n }\n\n main();\n\n ```\n\n- **dev_timeTravel** (date): Sets the timestamp of the block to a specific date\".\n\n === \"Parameter\"\n\n - **`date` ++\"string\"++**: Timestamp or date string to set. All future blocks will be sequentially created after this point in time.\n\n === \"Example\"\n\n ```js\n import { ApiPromise, WsProvider } from '@polkadot/api';\n\n async function main() {\n const wsProvider = new WsProvider('ws://localhost:8000');\n const api = await ApiPromise.create({ provider: wsProvider });\n await api.isReady;\n await api.rpc('dev_timeTravel', '2030-08-15T00:00:00');\n }\n\n main();\n\n ```"} +{"page_id": "parachains-testing-fork-a-parachain", "page_title": "Fork a Parachain Using Chopsticks", "index": 9, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 10559, "end_char": 10916, "estimated_token_count": 91, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
    \n\n- Tutorial __Fork a Chain with Chopsticks__\n\n ---\n\n Visit this guide for step-by-step instructions for configuring and interacting with your forked chain.\n\n [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/fork-live-chains/)\n\n
    "} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 43, "end_char": 795, "estimated_token_count": 125, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nZombienet is a robust testing framework designed for Polkadot SDK-based blockchain networks. It enables developers to efficiently deploy and test ephemeral blockchain environments on platforms like Kubernetes, Podman, and native setups. With its simple and versatile CLI, Zombienet provides an all-in-one solution for spawning networks, running tests, and validating performance.\n\nThis guide will outline the different installation methods for Zombienet, provide step-by-step instructions for setting up on various platforms, and highlight essential provider-specific features and requirements.\n\nBy following this guide, Zombienet will be up and running quickly, ready to streamline your blockchain testing and development workflows."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 1, "depth": 2, "title": "Install Zombienet", "anchor": "install-zombienet", "start_char": 795, "end_char": 5049, "estimated_token_count": 901, "token_estimator": "heuristic-v1", "text": "## Install Zombienet\n\nZombienet releases are available on the [Zombienet repository](https://github.com/paritytech/zombienet){target=\\_blank}.\n\nMultiple options are available for installing Zombienet, depending on the user's preferences and the environment where it will be used. The following section will guide you through the installation process for each option.\n\n=== \"Use the executable\"\n\n Install Zombienet using executables by visiting the [latest release](https://github.com/paritytech/zombienet/releases){target=\\_blank} page and selecting the appropriate asset for your operating system. You can download the executable and move it to a directory in your PATH. \n\n Each release includes executables for Linux and macOS. Executables are generated using [pkg](https://github.com/vercel/pkg){target=\\_blank}, which allows the Zombienet CLI to operate without requiring Node.js to be installed. \n\n Then, ensure the downloaded file is executable:\n\n ```bash\n chmod +x zombienet-macos-arm64\n ```\n\n Finally, you can run the following command to check if the installation was successful. If so, it will display the version of the installed Zombienet:\n\n ```bash\n ./zombienet-macos-arm64 version\n ```\n\n If you want to add the `zombienet` executable to your PATH, you can move it to a directory in your PATH, such as `/usr/local/bin`:\n\n ```bash\n mv zombienet-macos-arm64 /usr/local/bin/zombienet\n ```\n\n Now you can refer to the `zombienet` executable directly.\n\n ```bash\n zombienet version\n ```\n\n=== \"Use Nix\"\n\n For Nix users, the Zombienet repository provides a [`flake.nix`](https://github.com/paritytech/zombienet/blob/main/flake.nix){target=\\_blank} file to install Zombienet making it easy to incorporate Zombienet into Nix-based projects.\n \n To install Zombienet utilizing Nix, users can run the following command, triggering the fetching of the flake and subsequently installing the Zombienet package:\n\n ```bash\n nix run github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION -- \\\n spawn INSERT_ZOMBIENET_CONFIG_FILE_NAME.toml\n ```\n\n Replace the `INSERT_ZOMBIENET_VERSION` with the desired version of Zombienet and the `INSERT_ZOMBIENET_CONFIG_FILE_NAME` with the name of the configuration file you want to use.\n\n To run the command above, you need to have [Flakes](https://nixos.wiki/wiki/Flakes#Enable_flakes){target=\\_blank} enabled.\n\n Alternatively, you can also include the Zombienet binary in the PATH for the current shell using the following command:\n \n ```bash\n nix shell github:paritytech/zombienet/INSERT_ZOMBIENET_VERSION\n ```\n\n=== \"Use Docker\"\n\n Zombienet can also be run using Docker. The Zombienet repository provides a Docker image that can be used to run the Zombienet CLI. To run Zombienet using Docker, you can use the following command:\n\n ```bash\n docker run -it --rm \\\n -v $(pwd):/home/nonroot/zombie-net/host-current-files \\\n paritytech/zombienet\n ```\n\n The command above will run the Zombienet CLI inside a Docker container and mount the current directory to the `/home/nonroot/zombie-net/host-current-files` directory. This allows Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path.\n\n Inside the Docker container, you can run the Zombienet CLI commands. First, you need to set up Zombienet to download the necessary binaries:\n\n ```bash\n npm run zombie -- setup polkadot polkadot-parachain\n ```\n\n After that, you need to add those binaries to the PATH:\n\n ```bash\n export PATH=/home/nonroot/zombie-net:$PATH\n ```\n\n Finally, you can run the Zombienet CLI commands. For example, to spawn a network using a specific configuration file, you can run the following command:\n\n ```bash\n npm run zombie -- -p native spawn host-current-files/minimal.toml\n ```\n\n The command above mounts the current directory to the `/workspace` directory inside the Docker container, allowing Zombienet to access the configuration file and other files in the current directory. If you want to mount a different directory, replace `$(pwd)` with the desired directory path."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 2, "depth": 2, "title": "Providers", "anchor": "providers", "start_char": 5049, "end_char": 5832, "estimated_token_count": 185, "token_estimator": "heuristic-v1", "text": "## Providers\n\nZombienet supports different backend providers for running the nodes. At this moment, [Kubernetes](https://kubernetes.io/){target=\\_blank}, [Podman](https://podman.io/){target=\\_blank}, and local providers are supported, which can be declared as `kubernetes`, `podman`, or `native`, respectively.\n\nTo use a particular provider, you can specify it in the network file or use the `--provider` flag in the CLI:\n\n```bash\nzombienet spawn network.toml --provider INSERT_PROVIDER\n```\n\nAlternatively, you can set the provider in the network file:\n\n```toml\n[settings]\nprovider = \"INSERT_PROVIDER\"\n...\n```\n\nIt's important to note that each provider has specific requirements and associated features. The following sections cover each provider's requirements and added features."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 3, "depth": 3, "title": "Kubernetes", "anchor": "kubernetes", "start_char": 5832, "end_char": 7361, "estimated_token_count": 329, "token_estimator": "heuristic-v1", "text": "### Kubernetes\n\nKubernetes is a portable, extensible, open-source platform for managing containerized workloads and services. Zombienet is designed to be compatible with a variety of Kubernetes clusters, including: \n\n- [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine){target=\\_blank}\n- [Docker Desktop](https://docs.docker.com/desktop/features/kubernetes/){target=\\_blank}\n- [kind](https://kind.sigs.k8s.io/){target=\\_blank}\n\n#### Requirements\n \nTo effectively interact with your cluster, you'll need to ensure that [`kubectl`](https://kubernetes.io/docs/reference/kubectl/){target=\\_blank} is installed on your system. This Kubernetes command-line tool allows you to run commands against Kubernetes clusters. If you don't have `kubectl` installed, you can follow the instructions provided in the [Kubernetes documentation](https://kubernetes.io/docs/tasks/tools/#kubectl){target=\\_blank}.\n\nTo create resources such as namespaces, pods, and CronJobs within the target cluster, you must grant your user or service account the appropriate permissions. These permissions are essential for managing and deploying applications effectively within Kubernetes.\n\n#### Features\n \nIf available, Zombienet uses the Prometheus operator to oversee monitoring and visibility. This configuration ensures that only essential networking-related pods are deployed. Using the Prometheus operator, Zombienet improves its ability to monitor and manage network activities within the Kubernetes cluster efficiently."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 4, "depth": 3, "title": "Podman", "anchor": "podman", "start_char": 7361, "end_char": 8957, "estimated_token_count": 374, "token_estimator": "heuristic-v1", "text": "### Podman\n\nPodman is a daemonless container engine for developing, managing, and running Open Container Initiative (OCI) containers and container images on Linux-based systems. Zombienet supports Podman rootless as a provider on Linux machines. Although Podman has support for macOS through an internal virtual machine (VM), the Zombienet provider code requires Podman to run natively on Linux.\n\n#### Requirements\n \nTo use Podman as a provider, you need to have Podman installed on your system. You can install Podman by following the instructions provided on the [Podman website](https://podman.io/getting-started/installation){target=\\_blank}.\n\n#### Features\n \nUsing Podman, Zombienet deploys additional pods to enhance the monitoring and visibility of the active network. Specifically, pods for [Prometheus](https://prometheus.io/){target=\\_blank}, [Tempo](https://grafana.com/docs/tempo/latest/operations/monitor/){target=\\_blank}, and [Grafana](https://grafana.com/){target=\\_blank} are included in the deployment. Grafana is configured with Prometheus and Tempo as data sources.\n\nUpon launching Zombienet, access to these monitoring services is facilitated through specific URLs provided in the output:\n\n- **Prometheus**: `http://127.0.0.1:34123`\n- **Tempo**: `http://127.0.0.1:34125`\n- **Grafana**: `http://127.0.0.1:41461`\n\nIt's important to note that Grafana is deployed with default administrator access. \n \nWhen network operations cease, either from halting a running spawn with the `Ctrl+C` command or test completion, Zombienet automatically removes all associated pods."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 5, "depth": 3, "title": "Local Provider", "anchor": "local-provider", "start_char": 8957, "end_char": 10917, "estimated_token_count": 420, "token_estimator": "heuristic-v1", "text": "### Local Provider\n\nThe Zombienet local provider, also called native, enables you to run nodes as local processes in your environment.\n\n#### Requirements\n \nYou must have the necessary binaries for your network (such as `polkadot` and `polkadot-parachain`). These binaries should be available in your PATH, allowing Zombienet to spawn the nodes as local processes.\n\nTo install the necessary binaries, you can use the Zombienet CLI command:\n\n```bash\nzombienet setup polkadot polkadot-parachain\n```\n\nThis command will download and prepare the necessary binaries for Zombienet's use.\n\nIf you need to use a custom binary, ensure the binary is available in your PATH. You can also specify the binary path in the network configuration file. The following example uses the custom [OpenZeppelin template](https://github.com/OpenZeppelin/polkadot-runtime-templates){target=\\_blank}:\n\nFirst, clone the OpenZeppelin template repository using the following command:\n\n```bash\ngit clone https://github.com/OpenZeppelin/polkadot-runtime-templates \\\n&& cd polkadot-runtime-templates/generic-template\n```\n\nNext, run the command to build the custom binary:\n\n```bash\ncargo build --release\n```\n\nFinally, add the custom binary to your PATH as follows:\n\n```bash\nexport PATH=$PATH:INSERT_PATH_TO_RUNTIME_TEMPLATES/parachain-template-node/target/release\n```\n\nAlternatively, you can specify the binary path in the network configuration file. The local provider exclusively utilizes the command configuration for nodes, which supports both relative and absolute paths. You can employ the `default_command` configuration to specify the binary for spawning all nodes in the relay chain.\n\n```toml\n[relaychain]\nchain = \"rococo-local\"\ndefault_command = \"./bin-v1.6.0/polkadot\"\n\n[parachain]\nid = 1000\n\n [parachain.collators]\n name = \"collator01\"\n command = \"./target/release/parachain-template-node\"\n```\n\n#### Features\n\nThe local provider does not offer any additional features."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 6, "depth": 2, "title": "Configure Zombienet", "anchor": "configure-zombienet", "start_char": 10917, "end_char": 11529, "estimated_token_count": 99, "token_estimator": "heuristic-v1", "text": "## Configure Zombienet\n\nEffective network configuration is crucial for deploying and managing blockchain systems. Zombienet simplifies this process by offering versatile configuration options in both JSON and TOML formats. Whether setting up a simple test network or a complex multi-node system, Zombienet's tools provide the flexibility to customize every aspect of your network's setup.\n\nThe following sections will explore the structure and usage of Zombienet configuration files, explain key settings for network customization, and walk through CLI commands and flags to optimize your development workflow."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 7, "depth": 3, "title": "Configuration Files", "anchor": "configuration-files", "start_char": 11529, "end_char": 12007, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "### Configuration Files\n\nThe network configuration file can be either JSON or TOML format. The Zombienet repository also provides a collection of [example configuration files](https://github.com/paritytech/zombienet/tree/main/examples){target=\\_blank} that can be used as a reference.\n\nEach section may include provider-specific keys that aren't recognized by other providers. For example, if you use the local provider, any references to images for nodes will be disregarded."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 8, "depth": 3, "title": "CLI Usage", "anchor": "cli-usage", "start_char": 12007, "end_char": 13799, "estimated_token_count": 502, "token_estimator": "heuristic-v1", "text": "### CLI Usage\n\nZombienet provides a CLI that allows interaction with the tool. The CLI can receive commands and flags to perform different kinds of operations. These operations use the following syntax:\n\n```bash\nzombienet \n```\n\nThe following sections will guide you through the primary usage of the Zombienet CLI and the available commands and flags.\n\n#### CLI Commands\n\n- **`spawn `**: Spawn the network defined in the [configuration file](#configuration-files).\n- **`test `**: Run tests on the spawned network using the assertions and tests defined in the [test file](/develop/toolkit/parachains/spawn-chains/zombienet/write-tests/#the-test-file){target=\\_blank}.\n- **`setup `**: Set up the Zombienet development environment to download and use the `polkadot` or `polkadot-parachain` executable.\n- **`convert `**: Transforms a [polkadot-launch](https://github.com/paritytech/polkadot-launch){target=\\_blank} configuration file with a `.js` or `.json` extension into a Zombienet configuration file.\n- **`version`**: Prints Zombienet version.\n- **`help`**: Prints help information.\n\n#### CLI Flags\n\nYou can use the following flags to customize the behavior of the CLI:\n\n- **`-p`, `--provider`**: Override the [provider](#providers) to use.\n- **`-d`, `--dir`**: Specify a directory path for placing the network files instead of using the default temporary path.\n- **`-f`, `--force`**: Force override all prompt commands.\n- **`-l`, `--logType`**: Type of logging on the console. Defaults to `table`.\n- **`-m`, `--monitor`**: Start as monitor and don't auto clean up network.\n- **`-c`, `--spawn-concurrency`**: Number of concurrent spawning processes to launch. Defaults to `1`.\n- **`-h`, `--help`**: Display help for command."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 9, "depth": 3, "title": "Settings", "anchor": "settings", "start_char": 13799, "end_char": 16992, "estimated_token_count": 866, "token_estimator": "heuristic-v1", "text": "### Settings\n\nThrough the keyword `settings`, it's possible to define the general settings for the network. The available keys are:\n\n- **`global_volumes?`** ++\"GlobalVolume[]\"++: A list of global volumes to use.\n\n ??? child \"`GlobalVolume` interface definition\"\n ```js\n export interface GlobalVolume {\n name: string;\n fs_type: string;\n mount_path: string;\n }\n ```\n\n- **`bootnode`** ++\"boolean\"++: Add bootnode to network. Defaults to `true`.\n- **`bootnode_domain?`** ++\"string\"++: Domain to use for bootnode.\n- **`timeout`** ++\"number\"++: Global timeout to use for spawning the whole network.\n- **`node_spawn_timeout?`** ++\"number\"++: Timeout to spawn pod/process.\n- **`grafana?`** ++\"boolean\"++: Deploy an instance of Grafana.\n- **`prometheus?`** ++\"boolean\"++: Deploy an instance of Prometheus.\n- **`telemetry?`** ++\"boolean\"++: Enable telemetry for the network.\n- **`jaeger_agent?`** ++\"string\"++: The Jaeger agent endpoint passed to the nodes. Only available on Kubernetes.\n- **`tracing_collator_url?`** ++\"string\"++: The URL of the tracing collator used to query by the tracing assertion. Should be tempo query compatible.\n- **`tracing_collator_service_name?`** ++\"string\"++: Service name for tempo query frontend. Only available on Kubernetes. Defaults to `tempo-tempo-distributed-query-frontend`.\n- **`tracing_collator_service_namespace?`** ++\"string\"++: Namespace where tempo is running. Only available on Kubernetes. Defaults to `tempo`.\n- **`tracing_collator_service_port?`** ++\"number\"++: Port of the query instance of tempo. Only available on Kubernetes. Defaults to `3100`.\n- **`enable_tracing?`** ++\"boolean\"++: Enable the tracing system. Only available on Kubernetes. Defaults to `true`.\n- **`provider`** ++\"string\"++: Provider to use. Default is `kubernetes`\".\n- **`polkadot_introspector?`** ++\"boolean\"++: Deploy an instance of polkadot-introspector. Only available on Podman and Kubernetes. Defaults to `false`.\n- **`backchannel?`** ++\"boolean\"++: Deploy an instance of backchannel server. Only available on Kubernetes. Defaults to `false`.\n- **`image_pull_policy?`** ++\"string\"++: Image pull policy to use in the network. Possible values are `Always`, `IfNotPresent`, and `Never`.\n- **`local_ip?`** ++\"string\"++: IP used for exposing local services (rpc/metrics/monitors). Defaults to `\"127.0.0.1\"`.\n- **`global_delay_network_global_settings?`** ++\"number\"++: Delay in seconds to apply to the network.\n- **`node_verifier?`** ++\"string\"++: Specify how to verify node readiness or deactivate by using `None`. Possible values are `None` and `Metric`. Defaults to `Metric`.\n\nFor example, the following configuration file defines a minimal example for the settings:\n\n=== \"TOML\"\n\n ```toml title=\"base-example.toml\"\n [settings]\n timeout = 1000\n bootnode = false\n provider = \"kubernetes\"\n backchannel = false\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"base-example.json\"\n {\n \"settings\": {\n \"timeout\": 1000,\n \"bootnode\": false,\n \"provider\": \"kubernetes\",\n \"backchannel\": false,\n \"...\": {}\n },\n \"...\": {}\n }\n\n ```"} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 10, "depth": 3, "title": "Relay Chain Configuration", "anchor": "relay-chain-configuration", "start_char": 16992, "end_char": 28546, "estimated_token_count": 2794, "token_estimator": "heuristic-v1", "text": "### Relay Chain Configuration\n\nYou can use the `relaychain` keyword to define further parameters for the relay chain at start-up. The available keys are:\n\n- **`default_command?`** ++\"string\"++: The default command to run. Defaults to `polkadot`.\n- **`default_image?`** ++\"string\"++: The default Docker image to use.\n- **`default_resources?`** ++\"Resources\"++: Represents the resource limits/reservations the nodes need by default. Only available on Kubernetes.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`default_db_snapshot?`** ++\"string\"++: The default database snapshot to use.\n- **`default_prometheus_prefix`** ++\"string\"++: A parameter for customizing the metric's prefix. Defaults to `substrate`.\n- **`default_substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`default_keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n- **`chain`** ++\"string\"++: The chain name.\n- **`chain_spec_path?`** ++\"string\"++: Path to the chain spec file. Should be the plain version to allow customizations.\n- **`chain_spec_command?`** ++\"string\"++: Command to generate the chain spec. It can't be used in combination with `chain_spec_path`.\n- **`default_args?`** ++\"string[]\"++: An array of arguments to use as default to pass to the command.\n- **`default_overrides?`** ++\"Override[]\"++: An array of overrides to upload to the node.\n\n ??? child \"`Override` interface definition\"\n ```js\n export interface Override {\n local_path: string;\n remote_name: string;\n } \n ```\n\n- **`random_nominators_count?`** ++\"number\"++: If set and the stacking pallet is enabled, Zombienet will generate the input quantity of nominators and inject them into the genesis.\n- **`max_nominations`** ++\"number\"++: The max number of nominations allowed by a nominator. Should match the value set in the runtime. Defaults to `24`.\n- **`nodes?`** ++\"Node[]\"++: An array of nodes to spawn. It is further defined in the [Node Configuration](#node-configuration) section.\n- **`node_groups?`** ++\"NodeGroup[]\"++: An array of node groups to spawn. It is further defined in the [Node Group Configuration](#node-group-configuration) section.\n- **`total_node_in_group?`** ++\"number\"++: The total number of nodes in the group. Defaults to `1`.\n- **`genesis`** ++\"JSON\"++: The genesis configuration.\n- **`default_delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\n#### Node Configuration\n\nOne specific key capable of receiving more subkeys is the `nodes` key. This key is used to define further parameters for the nodes. The available keys:\n\n- **`name`** ++\"string\"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`).\n- **`image?`** ++\"string\"++: Override default Docker image to use for this node.\n- **`command?`** ++\"string\"++: Override default command to run.\n- **`command_with_args?`** ++\"string\"++: Override default command and arguments.\n- **`args?`** ++\"string[]\"++: Arguments to be passed to the command.\n- **`env?`** ++\"envVars[]\"++: Environment variables to set in the container.\n\n ??? child \"`envVars` interface definition\"\n ```js\n export interface EnvVars {\n name: string;\n value: string;\n }\n ```\n\n- **`prometheus_prefix?`** ++\"string\"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`.\n- **`db_snapshot?`** ++\"string\"++: Database snapshot to use.\n- **`substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`resources?`** ++\"Resources\"++: Represent the resources limits/reservations needed by the node.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n- **`validator`** ++\"boolean\"++: Pass the `--validator` flag to the command. Defaults to `true`.\n- **`invulnerable`** ++\"boolean\"++: If true, add the node to invulnerables in the chain spec. Defaults to `false`.\n- **`balance`** ++\"number\"++: Balance to set in balances for node's account. Defaults to `2000000000000`.\n- **`bootnodes?`** ++\"string[]\"++: Array of bootnodes to use.\n- **`add_to_bootnodes?`** ++\"boolean\"++: Add this node to the bootnode list. Defaults to `false`.\n- **`ws_port?`** ++\"number\"++: WS port to use.\n- **`rpc_port?`** ++\"number\"++: RPC port to use.\n- **`prometheus_port?`** ++\"number\"++: Prometheus port to use.\n- **`p2p_cert_hash?`** ++\"string\"++: Libp2p certhash to use with webRTC transport.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\nThe following configuration file defines a minimal example for the relay chain, including the `nodes` key:\n\n=== \"TOML\"\n\n ```toml title=\"relaychain-example-nodes.toml\"\n [relaychain]\n default_command = \"polkadot\"\n default_image = \"polkadot-debug:master\"\n chain = \"rococo-local\"\n chain_spec_path = \"INSERT_PATH_TO_CHAIN_SPEC\"\n default_args = [\"--chain\", \"rococo-local\"]\n\n [[relaychain.nodes]]\n name = \"alice\"\n validator = true\n balance = 1000000000000\n\n [[relaychain.nodes]]\n name = \"bob\"\n validator = true\n balance = 1000000000000\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"relaychain-example-nodes.json\"\n {\n \"relaychain\": {\n \"default_command\": \"polkadot\",\n \"default_image\": \"polkadot-debug:master\",\n \"chain\": \"rococo-local\",\n \"chain_spec_path\": \"INSERT_PATH_TO_CHAIN-SPEC.JSON\",\n \"default_args\": [\"--chain\", \"rococo-local\"],\n \"nodes\": [\n {\n \"name\": \"alice\",\n \"validator\": true,\n \"balance\": 1000000000000\n },\n {\n \"name\": \"bob\",\n \"validator\": true,\n \"balance\": 1000000000000\n }\n ]\n }\n }\n\n ```\n\n#### Node Group Configuration\n\nThe `node_groups` key defines further parameters for the node groups. The available keys are:\n\n- **`name`** ++\"string\"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`).\n- **`image?`** ++\"string\"++: Override default Docker image to use for this node.\n- **`command?`** ++\"string\"++: Override default command to run.\n- **`args?`** ++\"string[]\"++: Arguments to be passed to the command.\n- **`env?`** ++\"envVars[]\"++: Environment variables to set in the container.\n \n ??? child \"`envVars` interface definition\"\n ```js\n export interface EnvVars {\n name: string;\n value: string;\n }\n ```\n\n- **`overrides?`** ++\"Override[]\"++: Array of overrides definitions.\n\n ??? child \"`Override` interface definition\"\n ```js\n export interface Override {\n local_path: string;\n remote_name: string;\n }\n ```\n\n- **`prometheus_prefix?`** ++\"string\"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`.\n- **`db_snapshot?`** ++\"string\"++: Database snapshot to use.\n- **`substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`resources?`** ++\"Resources\"++: Represent the resources limits/reservations needed by the node.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n- **`count`** ++\"number | string\"++: Number of nodes to launch for this group.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\nThe following configuration file defines a minimal example for the relay chain, including the `node_groups` key:\n\n=== \"TOML\"\n\n ```toml title=\"relaychain-example-node-groups.toml\"\n [relaychain]\n default_command = \"polkadot\"\n default_image = \"polkadot-debug:master\"\n chain = \"rococo-local\"\n chain_spec_path = \"INSERT_PATH_TO_CHAIN_SPEC\"\n default_args = [\"--chain\", \"rococo-local\"]\n\n [[relaychain.node_groups]]\n name = \"group-1\"\n count = 2\n image = \"polkadot-debug:master\"\n command = \"polkadot\"\n args = [\"--chain\", \"rococo-local\"]\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"relaychain-example-node-groups.json\"\n {\n \"relaychain\": {\n \"default_command\": \"polkadot\",\n \"default_image\": \"polkadot-debug:master\",\n \"chain\": \"rococo-local\",\n \"chain_spec_path\": \"INSERT_PATH_TO_CHAIN-SPEC.JSON\",\n \"default_args\": [\"--chain\", \"rococo-local\"],\n \"node_groups\": [\n {\n \"name\": \"group-1\",\n \"count\": 2,\n \"image\": \"polkadot-debug:master\",\n \"command\": \"polkadot\",\n \"args\": [\"--chain\", \"rococo-local\"]\n }\n ],\n \"...\": {}\n },\n \"...\": {}\n }\n\n ```"} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 11, "depth": 3, "title": "Parachain Configuration", "anchor": "parachain-configuration", "start_char": 28546, "end_char": 39719, "estimated_token_count": 2716, "token_estimator": "heuristic-v1", "text": "### Parachain Configuration\n\nThe `parachain` keyword defines further parameters for the parachain. The available keys are:\n\n- **`id`** ++\"number\"++: The id to assign to this parachain. Must be unique.\n- **`chain?`** ++\"string\"++: The chain name.\n- **`force_decorator?`** ++\"string\"++: Force the use of a specific decorator.\n- **`genesis?`** ++\"JSON\"++: The genesis configuration.\n- **`balance?`** ++\"number\"++: Balance to set in balances for parachain's account.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\n- **`add_to_genesis?`** ++\"boolean\"++: Flag to add parachain to genesis or register in runtime. Defaults to `true`.\n- **`register_para?`** ++\"boolean\"++: Flag to specify whether the para should be registered. The `add_to_genesis` flag must be set to false for this flag to have any effect. Defaults to `true`.\n- **`onboard_as_parachain?`** ++\"boolean\"++: Flag to specify whether the para should be onboarded as a parachain, rather than remaining a parathread. Defaults to `true`.\n- **`genesis_wasm_path?`** ++\"string\"++: Path to the Wasm file to use.\n- **`genesis_wasm_generator?`** ++\"string\"++: Command to generate the Wasm file.\n- **`genesis_state_path?`** ++\"string\"++: Path to the state file to use.\n- **`genesis_state_generator?`** ++\"string\"++: Command to generate the state file.\n- **`chain_spec_path?`** ++\"string\"++: Path to the chain spec file.\n- **`chain_spec_command?`** ++\"string\"++: Command to generate the chain spec.\n- **`cumulus_based?`** ++\"boolean\"++: Flag to use cumulus command generation. Defaults to `true`.\n- **`bootnodes?`** ++\"string[]\"++: Array of bootnodes to use.\n- **`prometheus_prefix?`** ++\"string\"++: Parameter for customizing the metric's prefix for all parachain nodes/collators. Defaults to `substrate`.\n- **`collator?`** ++\"Collator\"++: Further defined in the [Collator Configuration](#collator-configuration) section.\n- **`collator_groups?`** ++\"CollatorGroup[]\"++: An array of collator groups to spawn. It is further defined in the [Collator Groups Configuration](#collator-groups-configuration) section.\n \nFor example, the following configuration file defines a minimal example for the parachain:\n\n=== \"TOML\"\n\n ```toml title=\"parachain-example.toml\"\n [parachain]\n id = 100\n add_to_genesis = true\n cumulus_based = true\n genesis_wasm_path = \"INSERT_PATH_TO_WASM\"\n genesis_state_path = \"INSERT_PATH_TO_STATE\"\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"parachain-example.json\"\n {\n \"parachain\": {\n \"id\": 100,\n \"add_to_genesis\": true,\n \"cumulus_based\": true,\n \"genesis_wasm_path\": \"INSERT_PATH_TO_WASM\",\n \"genesis_state_path\": \"INSERT_PATH_TO_STATE\",\n \"...\": {}\n },\n \"...\": {}\n }\n\n ```\n\n#### Collator Configuration\n\nOne specific key capable of receiving more subkeys is the `collator` key. This key defines further parameters for the nodes. The available keys are:\n\n- **`name`** ++\"string\"++: Name of the collator. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`).\n- **`image?`** ++\"string\"++: Image to use for the collator.\n- **`command_with_args?`** ++\"string\"++: Overrides both command and arguments for the collator.\n- **`validator`** ++\"boolean\"++: Pass the `--validator` flag to the command. Defaults to `true`.\n- **`invulnerable`** ++\"boolean\"++: If true, add the collator to invulnerables in the chain spec. Defaults to `false`.\n- **`balance`** ++\"number\"++: Balance to set in balances for collator's account. Defaults to `2000000000000`.\n- **`bootnodes?`** ++\"string[]\"++: Array of bootnodes to use.\n- **`add_to_bootnodes?`** ++\"boolean\"++: Add this collator to the bootnode list. Defaults to `false`.\n- **`ws_port?`** ++\"number\"++: WS port to use.\n- **`rpc_port?`** ++\"number\"++: RPC port to use.\n- **`prometheus_port?`** ++\"number\"++: Prometheus port to use.\n- **`p2p_port?`** ++\"number\"++: P2P port to use.\n- **`p2p_cert_hash?`** ++\"string\"++: Libp2p certhash to use with webRTC transport.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\n- **`command?`** ++\"string\"++: Override default command to run.\n- **`args?`** ++\"string[]\"++: Arguments to be passed to the command.\n- **`env?`** ++\"envVars[]\"++: Environment variables to set in the container.\n\n ??? child \"`envVars` interface definition\"\n ```js\n export interface EnvVars {\n name: string;\n value: string;\n }\n ```\n\n- **`overrides?`** ++\"Override[]\"++: Array of overrides definitions.\n\n ??? child \"`Override` interface definition\"\n ```js\n export interface Override {\n local_path: string;\n remote_name: string;\n }\n ```\n\n- **`prometheus_prefix?`** ++\"string\"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`.\n- **`db_snapshot?`** ++\"string\"++: Database snapshot to use.\n- **`substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`resources?`** ++\"Resources\"++: Represent the resources limits/reservations needed by the node.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n\nThe configuration file below defines a minimal example for the collator:\n\n=== \"TOML\"\n\n ```toml title=\"collator-example.toml\"\n [parachain]\n id = 100\n add_to_genesis = true\n cumulus_based = true\n genesis_wasm_path = \"INSERT_PATH_TO_WASM\"\n genesis_state_path = \"INSERT_PATH_TO_STATE\"\n\n [[parachain.collators]]\n name = \"alice\"\n image = \"polkadot-parachain\"\n command = \"polkadot-parachain\"\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"collator-example.json\"\n {\n \"parachain\": {\n \"id\": 100,\n \"add_to_genesis\": true,\n \"cumulus_based\": true,\n \"genesis_wasm_path\": \"INSERT_PATH_TO_WASM\",\n \"genesis_state_path\": \"INSERT_PATH_TO_STATE\",\n \"collators\": [\n {\n \"name\": \"alice\",\n \"image\": \"polkadot-parachain\",\n \"command\": \"polkadot-parachain\",\n \"...\": {}\n }\n ]\n },\n \"...\": {}\n }\n\n ```\n\n#### Collator Groups Configuration\n\nThe `collator_groups` key defines further parameters for the collator groups. The available keys are:\n\n- **`name`** ++\"string\"++: Name of the node. Any whitespace will be replaced with a dash (for example, `new alice` will be converted to `new-alice`).\n- **`image?`** ++\"string\"++: Override default Docker image to use for this node.\n- **`command?`** ++\"string\"++: Override default command to run.\n- **`args?`** ++\"string[]\"++: Arguments to be passed to the command.\n- **`env?`** ++\"envVars[]\"++: Environment variables to set in the container.\n\n ??? child \"`envVars` interface definition\"\n ```js\n export interface EnvVars {\n name: string;\n value: string;\n }\n ```\n\n- **`overrides?`** ++\"Override[]\"++: Array of overrides definitions.\n\n ??? child \"`Override` interface definition\"\n ```js\n export interface Override {\n local_path: string;\n remote_name: string;\n }\n ```\n\n- **`prometheus_prefix?`** ++\"string\"++: Customizes the metric's prefix for the specific node. Defaults to `substrate`.\n- **`db_snapshot?`** ++\"string\"++: Database snapshot to use.\n- **`substrate_cli_args_version?`** ++\"SubstrateCliArgsVersion\"++: Set the Substrate CLI arguments version directly to skip binary evaluation overhead.\n\n ??? child \"`SubstrateCliArgsVersion` enum definition\"\n ```js\n export enum SubstrateCliArgsVersion {\n V0 = 0,\n V1 = 1,\n V2 = 2,\n V3 = 3,\n }\n ```\n\n- **`resources?`** ++\"Resources\"++: Represent the resources limits/reservations needed by the node.\n\n ??? child \"`Resources` interface definition\"\n ```js\n export interface Resources {\n resources: {\n requests?: {\n memory?: string;\n cpu?: string;\n };\n limits?: {\n memory?: string;\n cpu?: string;\n };\n };\n }\n ```\n\n- **`keystore_key_types?`** ++\"string[]\"++: Defines which keystore keys should be created.\n- **`count`** ++\"number | string\"++: Number of nodes to launch for this group.\n- **`delay_network_settings?`** ++\"DelayNetworkSettings\"++: Sets the expected configuration to delay the network.\n\n ??? child \"`DelayNetworkSettings` interface definition\"\n ```js\n export interface DelayNetworkSettings {\n latency: string;\n correlation?: string; // should be parsable as float by k8s\n jitter?: string;\n }\n ```\n\nFor instance, the configuration file below defines a minimal example for the collator groups:\n\n=== \"TOML\"\n\n ```toml title=\"collator-groups-example.toml\"\n [parachain]\n id = 100\n add_to_genesis = true\n cumulus_based = true\n genesis_wasm_path = \"INSERT_PATH_TO_WASM\"\n genesis_state_path = \"INSERT_PATH_TO_STATE\"\n\n [[parachain.collator_groups]]\n name = \"group-1\"\n count = 2\n image = \"polkadot-parachain\"\n command = \"polkadot-parachain\"\n # ...\n\n ```\n\n=== \"JSON\"\n\n ```json title=\"collator-groups-example.json\"\n {\n \"parachain\": {\n \"id\": 100,\n \"add_to_genesis\": true,\n \"cumulus_based\": true,\n \"genesis_wasm_path\": \"INSERT_PATH_TO_WASM\",\n \"genesis_state_path\": \"INSERT_PATH_TO_STATE\",\n \"collator_groups\": [\n {\n \"name\": \"group-1\",\n \"count\": 2,\n \"image\": \"polkadot-parachain\",\n \"command\": \"polkadot-parachain\",\n \"...\": {}\n }\n ]\n },\n \"...\": {}\n }\n\n ```"} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 12, "depth": 3, "title": "XCM Configuration", "anchor": "xcm-configuration", "start_char": 39719, "end_char": 40650, "estimated_token_count": 206, "token_estimator": "heuristic-v1", "text": "### XCM Configuration\n\nYou can use the `hrmp_channels` keyword to define further parameters for the XCM channels at start-up. The available keys are:\n\n- **`hrmp_channels`** ++\"HrmpChannelsConfig[]\"++: Array of Horizontal Relay-routed Message Passing (HRMP) channel configurations.\n\n ??? child \"`HrmpChannelsConfig` interface definition\"\n ```js\n export interface HrmpChannelsConfig {\n sender: number;\n recipient: number;\n max_capacity: number;\n max_message_size: number;\n }\n ```\n Each of the `HrmpChannelsConfig` keys are defined as follows:\n\n - **`sender` ++\"number\"++**: Parachain ID of the sender.\n - **`recipient` ++\"number\"++**: Parachain ID of the recipient.\n - **`max_capacity` ++\"number\"++**: Maximum capacity of the HRMP channel.\n - **`max_message_size` ++\"number\"++**: Maximum message size allowed in the HRMP channel."} +{"page_id": "parachains-testing-run-a-parachain-network", "page_title": "Run a Parachain Network", "index": 13, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 40650, "end_char": 41664, "estimated_token_count": 254, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\n
    \n\n- External __Zombienet Support__\n\n ---\n\n [Parity Technologies](https://www.parity.io/){target=\\_blank} has designed and developed this framework, now maintained by the Zombienet team. \n\n For further support and information, refer to the following contact points:\n\n [:octicons-arrow-right-24: Zombienet repository](https://github.com/paritytech/zombienet){target=\\_blank}\n\n [:octicons-arrow-right-24: Element public channel](https://matrix.to/#/!FWyuEyNvIFygLnWNMh:parity.io?via=parity.io&via=matrix.org&via=web3.foundation){target=\\_blank}\n\n\n- Tutorial __Spawn a Basic Chain with Zombienet__\n\n ---\n\n Learn to spawn, connect to and monitor a basic blockchain network with Zombienet, using customizable configurations for streamlined development and debugging.\n\n [:octicons-arrow-right-24: Reference](/tutorials/polkadot-sdk/testing/spawn-basic-chain/)\n\n
    "} {"page_id": "smart-contracts-connect", "page_title": "Connect to Polkadot", "index": 0, "depth": 2, "title": "Networks Details", "anchor": "networks-details", "start_char": 951, "end_char": 1604, "estimated_token_count": 137, "token_estimator": "heuristic-v1", "text": "## Networks Details\n\nDevelopers can leverage smart contracts across diverse networks, from TestNets to MainNet. This section outlines the network specifications and connection details for each environment.\n\n=== \"Polkadot Hub TestNet\"\n\n Network name\n\n ```text\n Polkadot Hub TestNet\n ```\n\n ---\n\n Currency symbol\n \n ```text\n PAS\n ```\n\n ---\n \n Chain ID\n \n ```text\n 420420422\n ```\n\n ---\n \n RPC URL\n \n ```text\n https://testnet-passet-hub-eth-rpc.polkadot.io\n ```\n\n ---\n \n Block explorer URL\n \n ```text\n https://blockscout-passet-hub.parity-testnet.parity.io/\n ```"} {"page_id": "smart-contracts-connect", "page_title": "Connect to Polkadot", "index": 1, "depth": 2, "title": "Test Tokens", "anchor": "test-tokens", "start_char": 1604, "end_char": 2618, "estimated_token_count": 233, "token_estimator": "heuristic-v1", "text": "## Test Tokens\n\nYou will need testnet tokens to perform transactions and engage with smart contracts on any chain. Here's how to obtain Paseo (PAS) tokens for testing purposes:\n\n1. Navigate to the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank}. If the desired network is not already selected, choose it from the Network drop-down.\n\n2. Copy your address linked to the TestNet and paste it into the designated field.\n\n ![](/images/smart-contracts/connect/connect-to-polkadot-01.webp)\n\n3. Click the **Get Some PASs** button to request free test PAS tokens. These tokens will be sent to your wallet shortly.\n\n ![](/images/smart-contracts/connect/connect-to-polkadot-02.webp)\n\nNow that you have obtained PAS tokens in your wallet, you’re ready to deploy and interact with smart contracts on Polkadot Hub TestNet! These tokens will allow you to pay for gas fees when executing transactions, deploying contracts, and testing your dApp functionality in a secure testnet environment."} {"page_id": "smart-contracts-connect", "page_title": "Connect to Polkadot", "index": 2, "depth": 2, "title": "Where to Go Next", "anchor": "where-to-go-next", "start_char": 2618, "end_char": 3459, "estimated_token_count": 188, "token_estimator": "heuristic-v1", "text": "## Where to Go Next\n\nFor your next steps, explore the various smart contract guides demonstrating how to use and integrate different tools and development environments into your workflow.\n\n
    \n\n- Guide __Deploy your first contract with Remix__\n\n ---\n\n Explore the smart contract development and deployment process on Polkadot Hub using the Remix IDE.\n\n [:octicons-arrow-right-24: Build with Remix IDE](/smart-contracts/dev-environments/remix/get-started/)\n\n- Guide __Interact with the blockchain with viem__\n\n ---\n\n Use viem for interacting with Ethereum-compatible chains, to deploy and interact with smart contracts on Polkadot Hub.\n\n [:octicons-arrow-right-24: Build with viem](/smart-contracts/libraries/viem/)\n\n
    "} @@ -877,7 +411,7 @@ {"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 6, "depth": 3, "title": "Compile the Contract", "anchor": "compile-the-contract", "start_char": 5430, "end_char": 5579, "estimated_token_count": 29, "token_estimator": "heuristic-v1", "text": "### Compile the Contract\n\nCompile your Storage contract:\n\n```bash\nnpx hardhat compile\n```\n\nYou should see output indicating successful compilation."} {"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 7, "depth": 3, "title": "Deploy the Contract", "anchor": "deploy-the-contract", "start_char": 5579, "end_char": 7216, "estimated_token_count": 416, "token_estimator": "heuristic-v1", "text": "### Deploy the Contract\n\nCreate a deployment script in the `ignition/modules` directory called `Storage.ts`:\n\n```typescript title=\"Storage.ts\"\nimport { buildModule } from \"@nomicfoundation/hardhat-ignition/modules\";\n\nexport default buildModule(\"StorageModule\", (m) => {\n const storage = m.contract(\"Storage\");\n\n return { storage };\n});\n```\n\nDeploy the contract to Polkadot Hub TestNet:\n\n```bash\nnpx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotTestNet\n```\n\nYou should see output similar to:\n\n
    \n npx hardhat ignition deploy ./ignition/modules/Storage.ts --network polkadotTestNet\n WARNING: You are using Node.js 23.11.0 which is not supported by Hardhat.\n Please upgrade to 22.10.0 or a later LTS version (even major version number)\n ✔ Confirm deploy to network polkadotTestNet (420420420)? … yes\n Hardhat Ignition 🚀\n Deploying [ StorageModule ]\n Batch #1\n Executed StorageModule#Storage\n [ StorageModule ] successfully deployed 🚀\n Deployed Addresses\n StorageModule#Storage - 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3\n
    \n\n!!! note\n Save the deployed contract address - you'll need it when building your dApp. In the following sections, we'll reference a pre-deployed contract at `0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3`, but you can use your own deployed contract address instead."} {"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 8, "depth": 3, "title": "Export the Contract ABI", "anchor": "export-the-contract-abi", "start_char": 7216, "end_char": 7603, "estimated_token_count": 89, "token_estimator": "heuristic-v1", "text": "### Export the Contract ABI\n\nAfter deployment, you'll need the contract's Application Binary Interface (ABI) for your dApp. You can find it in the `artifacts/contracts/Storage.sol/Storage.json` file generated by Hardhat. You'll use this in the next section when setting up your dApp.\n\nNow that you have your contract deployed, you're ready to build the dApp that will interact with it!"} -{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 9, "depth": 2, "title": "Set Up the dApp Project", "anchor": "set-up-the-dapp-project", "start_char": 7603, "end_char": 7800, "estimated_token_count": 59, "token_estimator": "heuristic-v1", "text": "## Set Up the dApp Project\n\nNavigate to the root of the project, and create a new Next.js project called `dapp`:\n\n```bash\nnpx create-next-app dapp --ts --eslint --tailwind --app --yes\ncd dapp\n```"} +{"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 9, "depth": 2, "title": "Set Up the DApp Project", "anchor": "set-up-the-dapp-project", "start_char": 7603, "end_char": 7800, "estimated_token_count": 59, "token_estimator": "heuristic-v1", "text": "## Set Up the DApp Project\n\nNavigate to the root of the project, and create a new Next.js project called `dapp`:\n\n```bash\nnpx create-next-app dapp --ts --eslint --tailwind --app --yes\ncd dapp\n```"} {"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 10, "depth": 2, "title": "Install Dependencies", "anchor": "install-dependencies", "start_char": 7800, "end_char": 7959, "estimated_token_count": 50, "token_estimator": "heuristic-v1", "text": "## Install Dependencies\n\nInstall viem and related packages:\n\n```bash\nnpm install viem@2.38.5\nnpm install --save-dev typescript@5.9.3 @types/node@22.19.24\n```"} {"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 11, "depth": 2, "title": "Connect to Polkadot Hub", "anchor": "connect-to-polkadot-hub", "start_char": 7959, "end_char": 10056, "estimated_token_count": 509, "token_estimator": "heuristic-v1", "text": "## Connect to Polkadot Hub\n\nTo interact with Polkadot Hub, you need to set up a [Public Client](https://viem.sh/docs/clients/public#public-client){target=\\_blank} that connects to the blockchain. In this example, you will interact with the Polkadot Hub TestNet, to experiment safely. Start by creating a new file called `utils/viem.ts` and add the following code:\n\n```typescript title=\"viem.ts\"\nimport { createPublicClient, http, createWalletClient, custom } from 'viem'\nimport 'viem/window';\n\nconst transport = http('http://127.0.0.1:8545') // TODO: change to the paseo asset hub RPC URL when it's available\n\n// Configure the Polkadot Testnet Hub chain\nexport const polkadotTestnet = {\n id: 420420420,\n name: 'Polkadot Testnet',\n network: 'polkadot-testnet',\n nativeCurrency: {\n decimals: 18,\n name: 'PAS',\n symbol: 'PAS',\n },\n rpcUrls: {\n default: {\n http: ['http://127.0.0.1:8545'], // TODO: change to the paseo asset hub RPC URL\n },\n },\n} as const\n\n// Create a public client for reading data\nexport const publicClient = createPublicClient({\n chain: polkadotTestnet,\n transport\n})\n\n// Create a wallet client for signing transactions\nexport const getWalletClient = async () => {\n if (typeof window !== 'undefined' && window.ethereum) {\n const [account] = await window.ethereum.request({ method: 'eth_requestAccounts' });\n return createWalletClient({\n chain: polkadotTestnet,\n transport: custom(window.ethereum),\n account,\n });\n }\n throw new Error('No Ethereum browser provider detected');\n};\n```\n\nThis file initializes a viem client, providing helper functions for obtaining a Public Client and a [Wallet Client](https://viem.sh/docs/clients/wallet#wallet-client){target=\\_blank}. The Public Client enables reading blockchain data, while the Wallet Client allows users to sign and send transactions. Also, note that by importing `viem/window` the global `window.ethereum` will be typed as an `EIP1193Provider`, check the [`window` Polyfill](https://viem.sh/docs/typescript#window-polyfill){target=\\_blank} reference for more information."} {"page_id": "smart-contracts-cookbook-dapps-zero-to-hero", "page_title": "Zero to Hero Smart Contract DApp", "index": 12, "depth": 2, "title": "Set Up the Smart Contract Interface", "anchor": "set-up-the-smart-contract-interface", "start_char": 10056, "end_char": 11947, "estimated_token_count": 415, "token_estimator": "heuristic-v1", "text": "## Set Up the Smart Contract Interface\n\nFor this dApp, you'll use a simple [Storage contract](/tutorials/smart-contracts/launch-your-first-project/create-contracts){target=\\_blank} that's already deployed in the Polkadot Hub TestNet: `0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3`. To interact with it, you need to define the contract interface.\n\nCreate a folder called `abis` at the root of your project, then create a file named `Storage.json` and paste the corresponding ABI of the Storage contract. You can copy and paste the following:\n\n```bash\ncp ./storage-contract/artifacts/contracts/Storage.sol/Storage.json ./dapp/abis/Storage.json\n```\n\nNext, create a file called `utils/contract.ts`:\n\n```typescript title=\"contract.ts\"\nimport { getContract } from 'viem';\nimport { publicClient, getWalletClient } from './viem';\nimport StorageABI from '../abis/Storage.json';\n\nexport const CONTRACT_ADDRESS = '0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3'; // TODO: change when the paseo asset hub RPC URL is available, and the contract is redeployed\nexport const CONTRACT_ABI = StorageABI.abi;\n\n// Create a function to get a contract instance for reading\nexport const getContractInstance = () => {\n return getContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n client: publicClient,\n });\n};\n\n// Create a function to get a contract instance with a signer for writing\nexport const getSignedContract = async () => {\n const walletClient = await getWalletClient();\n return getContract({\n address: CONTRACT_ADDRESS,\n abi: CONTRACT_ABI,\n client: walletClient,\n });\n};\n```\n\nThis file defines the contract address, ABI, and functions to create a viem [contract instance](https://viem.sh/docs/contract/getContract#contract-instances){target=\\_blank} for reading and writing operations. viem's contract utilities enable more efficient, type-safe interaction with smart contracts."} @@ -1022,9 +556,9 @@ {"page_id": "smart-contracts-explorers", "page_title": "Block Explorers", "index": 1, "depth": 2, "title": "Core Functionality", "anchor": "core-functionality", "start_char": 497, "end_char": 1187, "estimated_token_count": 139, "token_estimator": "heuristic-v1", "text": "## Core Functionality\n\nThese block explorers provide essential capabilities for interacting with smart contracts in Polkadot Hub:\n\n- **Transaction tracking**: Monitor transaction status, confirmations, fees, and metadata.\n- **Address analysis**: View account balances, transaction history, and associated contracts.\n- **Block information**: Examine block contents.\n- **Smart contract interaction**: Review contract code, verification status, and interaction history.\n- **Token tracking**: Monitor ERC-20, ERC-721, and other token standards with transfer history and holder analytics.\n- **Network statistics**: Access metrics on transaction volume, gas usage, and other network parameters."} {"page_id": "smart-contracts-explorers", "page_title": "Block Explorers", "index": 2, "depth": 2, "title": "Available Block Explorers", "anchor": "available-block-explorers", "start_char": 1187, "end_char": 1399, "estimated_token_count": 30, "token_estimator": "heuristic-v1", "text": "## Available Block Explorers\n\nThe following block explorers are available for PolkaVM smart contracts, providing specialized tools for monitoring and analyzing contract activity within the Polkadot ecosystem:"} {"page_id": "smart-contracts-explorers", "page_title": "Block Explorers", "index": 3, "depth": 3, "title": "BlockScout", "anchor": "blockscout", "start_char": 1399, "end_char": 1793, "estimated_token_count": 91, "token_estimator": "heuristic-v1", "text": "### BlockScout\n\nBlockScout is an open-source explorer platform with a user-friendly interface adapted for PolkaVM contracts. It excels at detailed contract analytics and provides developers with comprehensive API access.\n\n- [Polkadot Hub TestNet BlockScout](https://blockscout-passet-hub.parity-testnet.parity.io/){target=\\_blank}\n\n![](/images/smart-contracts/explorers/block-explorers-2.webp)"} -{"page_id": "smart-contracts-faucet", "page_title": "Faucet", "index": 0, "depth": 2, "title": "Get Test Tokens", "anchor": "get-test-tokens", "start_char": 473, "end_char": 1160, "estimated_token_count": 182, "token_estimator": "heuristic-v1", "text": "## Get Test Tokens\n\nFor Polkadot Hub TestNet, you can use the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank} to obtain test tokens. Here's how to do it:\n\n1. Navigate to the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank}. If the desired network is not already selected, choose it from the **Network** drop-down. This example uses the Polkadot Hub TestNet.\n2. Copy your address linked to the TestNet and paste it into the designated field.\n3. Click the **Get Some PASs** button to request free test PAS tokens. These tokens will be sent to your wallet shortly.\n\n![Polkadot Faucet](/images/smart-contracts/faucet/faucet-1.gif)"} -{"page_id": "smart-contracts-faucet", "page_title": "Faucet", "index": 1, "depth": 2, "title": "Things to Consider", "anchor": "things-to-consider", "start_char": 1160, "end_char": 1584, "estimated_token_count": 79, "token_estimator": "heuristic-v1", "text": "## Things to Consider\n\n!!! info \"Rate Limiting\"\n Faucets typically implement rate limiting to prevent abuse. You may need to wait between requests if you've recently obtained tokens from the same faucet.\n\n!!! warning \"Network Compatibility\"\n Ensure your wallet is connected to the correct network (Polkadot Hub TestNet) before requesting tokens. Tokens sent to addresses on different networks will not be accessible."} -{"page_id": "smart-contracts-faucet", "page_title": "Faucet", "index": 2, "depth": 2, "title": "Using Your Test Tokens", "anchor": "using-your-test-tokens", "start_char": 1584, "end_char": 1890, "estimated_token_count": 52, "token_estimator": "heuristic-v1", "text": "## Using Your Test Tokens\n\nGetting started with test tokens is the first step in your Polkadot development journey. These free resources enable you to build, experiment with, and refine your applications without financial constraints, ensuring your projects are robust and ready for deployment on MainNet."} +{"page_id": "smart-contracts-faucet", "page_title": "Get Tokens from the Official Faucet", "index": 0, "depth": 2, "title": "Get Test Tokens", "anchor": "get-test-tokens", "start_char": 473, "end_char": 1160, "estimated_token_count": 182, "token_estimator": "heuristic-v1", "text": "## Get Test Tokens\n\nFor Polkadot Hub TestNet, you can use the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank} to obtain test tokens. Here's how to do it:\n\n1. Navigate to the [Polkadot Faucet](https://faucet.polkadot.io/?parachain=1111){target=\\_blank}. If the desired network is not already selected, choose it from the **Network** drop-down. This example uses the Polkadot Hub TestNet.\n2. Copy your address linked to the TestNet and paste it into the designated field.\n3. Click the **Get Some PASs** button to request free test PAS tokens. These tokens will be sent to your wallet shortly.\n\n![Polkadot Faucet](/images/smart-contracts/faucet/faucet-1.gif)"} +{"page_id": "smart-contracts-faucet", "page_title": "Get Tokens from the Official Faucet", "index": 1, "depth": 2, "title": "Things to Consider", "anchor": "things-to-consider", "start_char": 1160, "end_char": 1584, "estimated_token_count": 79, "token_estimator": "heuristic-v1", "text": "## Things to Consider\n\n!!! info \"Rate Limiting\"\n Faucets typically implement rate limiting to prevent abuse. You may need to wait between requests if you've recently obtained tokens from the same faucet.\n\n!!! warning \"Network Compatibility\"\n Ensure your wallet is connected to the correct network (Polkadot Hub TestNet) before requesting tokens. Tokens sent to addresses on different networks will not be accessible."} +{"page_id": "smart-contracts-faucet", "page_title": "Get Tokens from the Official Faucet", "index": 2, "depth": 2, "title": "Using Your Test Tokens", "anchor": "using-your-test-tokens", "start_char": 1584, "end_char": 1890, "estimated_token_count": 52, "token_estimator": "heuristic-v1", "text": "## Using Your Test Tokens\n\nGetting started with test tokens is the first step in your Polkadot development journey. These free resources enable you to build, experiment with, and refine your applications without financial constraints, ensuring your projects are robust and ready for deployment on MainNet."} {"page_id": "smart-contracts-for-eth-devs-accounts", "page_title": "Accounts in Asset Hub Smart Contracts", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 211, "end_char": 1055, "estimated_token_count": 149, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nAsset Hub natively utilizes Polkadot's 32-byte account system while providing interoperability with Ethereum's 20-byte addresses through an automatic conversion system. When interacting with smart contracts:\n\n- Ethereum-compatible wallets (like MetaMask) can use their familiar 20-byte addresses.\n- Polkadot accounts continue using their native 32-byte format.\n- The Asset Hub chain automatically handles conversion between the two formats behind the scenes:\n\n - 20-byte Ethereum addresses are padded with `0xEE` bytes to create valid 32-byte Polkadot accounts.\n - 32-byte Polkadot accounts can optionally register a mapping to a 20-byte address for Ethereum compatibility.\n\nThis dual-format approach enables Asset Hub to maintain compatibility with Ethereum tooling while fully integrating with the Polkadot ecosystem."} {"page_id": "smart-contracts-for-eth-devs-accounts", "page_title": "Accounts in Asset Hub Smart Contracts", "index": 1, "depth": 2, "title": "Address Types and Mappings", "anchor": "address-types-and-mappings", "start_char": 1055, "end_char": 1352, "estimated_token_count": 77, "token_estimator": "heuristic-v1", "text": "## Address Types and Mappings\n\nThe platform handles two distinct address formats:\n\n- [Ethereum-style addresses (20 bytes)](https://ethereum.org/developers/docs/accounts/#account-creation){target=\\_blank}\n- [Polkadot native account IDs (32 bytes)](/reference/parachains/accounts/){target=\\_blank}"} {"page_id": "smart-contracts-for-eth-devs-accounts", "page_title": "Accounts in Asset Hub Smart Contracts", "index": 2, "depth": 3, "title": "Ethereum to Polkadot Mapping", "anchor": "ethereum-to-polkadot-mapping", "start_char": 1352, "end_char": 2397, "estimated_token_count": 237, "token_estimator": "heuristic-v1", "text": "### Ethereum to Polkadot Mapping\n\nThe [`AccountId32Mapper`](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/struct.AccountId32Mapper.html){target=\\_blank} implementation in [`pallet_revive`](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/index.html){target=\\_blank} handles the core address conversion logic. For converting a 20-byte Ethereum address to a 32-byte Polkadot address, the pallet uses a simple concatenation approach:\n\n- [**Core mechanism**](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/trait.AddressMapper.html#tymethod.to_fallback_account_id){target=\\_blank}: Takes a 20-byte Ethereum address and extends it to 32 bytes by adding twelve `0xEE` bytes at the end. The key benefits of this approach are:\n - Able to fully revert, allowing a smooth transition back to the Ethereum format.\n - Provides clear identification of Ethereum-controlled accounts through the `0xEE` suffix pattern.\n - Maintains cryptographic security with a `2^96` difficulty for pattern reproduction."} @@ -1061,13 +595,13 @@ {"page_id": "smart-contracts-for-eth-devs-dual-vm-stack", "page_title": "Dual Virtual Machine Stack", "index": 4, "depth": 3, "title": "Revive Pallet", "anchor": "revive-pallet", "start_char": 2844, "end_char": 4123, "estimated_token_count": 232, "token_estimator": "heuristic-v1", "text": "### Revive Pallet\n\n[**`pallet_revive`**](https://paritytech.github.io/polkadot-sdk/master/pallet_revive/index.html){target=\\_blank} is a runtime module that executes smart contracts by adding extrinsics, runtime APIs, and logic to convert Ethereum-style transactions into formats compatible with Polkadot SDK-based blockchains. It processes Ethereum-style transactions through the following workflow:\n\n```mermaid\nsequenceDiagram\n participant User as User/dApp\n participant Proxy as Ethereum JSON RPC Proxy\n participant Chain as Blockchain Node\n participant Pallet as pallet_revive\n \n User->>Proxy: Submit Ethereum Transaction\n Proxy->>Chain: Repackage as Polkadot Compatible Transaction\n Chain->>Pallet: Process Transaction\n Pallet->>Pallet: Decode Ethereum Transaction\n Pallet->>Pallet: Execute Contract via PolkaVM\n Pallet->>Chain: Return Results\n Chain->>Proxy: Forward Results\n Proxy->>User: Return Ethereum-compatible Response\n```\n\nThis proxy-based approach eliminates the need for node binary modifications, maintaining compatibility across different client implementations. Preserving the original Ethereum transaction payload simplifies the adaptation of existing tools, which can continue processing familiar transaction formats."} {"page_id": "smart-contracts-for-eth-devs-dual-vm-stack", "page_title": "Dual Virtual Machine Stack", "index": 5, "depth": 3, "title": "PolkaVM Design Fundamentals", "anchor": "polkavm-design-fundamentals", "start_char": 4123, "end_char": 5067, "estimated_token_count": 185, "token_estimator": "heuristic-v1", "text": "### PolkaVM Design Fundamentals\n\nPolkaVM differs from the EVM in two key ways that make it faster, more hardware-efficient, and easier to extend:\n\n- **Register-based design**: Instead of a stack machine, PolkaVM uses a RISC-V–style register model. This design:\n\n - Uses a fixed set of registers to pass arguments, not an infinite stack.\n - Maps cleanly to real hardware like x86-64.\n - Simplifies compilation and boosts runtime efficiency.\n - Enables tighter control over register allocation and performance tuning.\n\n- **64-bit word size**: PolkaVM runs on a native 64-bit word size, aligning directly with modern CPUs. This design:\n\n - Executes arithmetic operations with direct hardware support.\n - Maintains compatibility with Solidity’s 256-bit types via YUL translation.\n - Accelerates computation-heavy workloads through native word alignment.\n - Integrates easily with low-level, performance-focused components."} {"page_id": "smart-contracts-for-eth-devs-dual-vm-stack", "page_title": "Dual Virtual Machine Stack", "index": 6, "depth": 2, "title": "Where To Go Next", "anchor": "where-to-go-next", "start_char": 5067, "end_char": 5383, "estimated_token_count": 82, "token_estimator": "heuristic-v1", "text": "## Where To Go Next\n\n
    \n\n- Learn __Contract Deployment__\n\n ---\n\n Learn how REVM and PVM compare for compiling and deploying smart contracts.\n\n [:octicons-arrow-right-24: Reference](/smart-contracts/for-eth-devs/contract-deployment/)\n\n
    "} -{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 0, "depth": 2, "title": "Overview", "anchor": "overview", "start_char": 13, "end_char": 290, "estimated_token_count": 49, "token_estimator": "heuristic-v1", "text": "## Overview\n\nThe Polkadot Hub implements a gas model that bridges Ethereum's familiar gas concept with Polkadot's more sophisticated resource metering system. This page explains how gas works in the Polkadot Hub and what developers need to know when building smart contracts."} -{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 1, "depth": 2, "title": "Understanding Resources in the Polkadot Hub", "anchor": "understanding-resources-in-the-polkadot-hub", "start_char": 290, "end_char": 1290, "estimated_token_count": 189, "token_estimator": "heuristic-v1", "text": "## Understanding Resources in the Polkadot Hub\n\nUnlike Ethereum, which uses a single gas value to measure everything, the Polkadot Hub tracks three separate resources:\n\n- **`ref_time`**: Measures computational time. It is the closest equivalent to traditional gas and represents the amount of CPU time your contract execution consumes.\n- **`proof_size`**: Measures the amount of state data that validators need to verify. When your contract reads from storage or makes state queries, this metric tracks the size of the proofs needed to validate those operations.\n- **`storage_deposit`**: Is a native balance that gets temporarily locked when your contract creates new storage entries. This prevents state bloat by requiring contracts to pay for the storage they use. The deposit is returned when the storage is freed.\n\nFor Ethereum wallet compatibility, the Polkadot Hub's RPC layer automatically maps these three dimensions into a single gas value that wallets can understand and display to users."} -{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 2, "depth": 2, "title": "Gas vs Weight", "anchor": "gas-vs-weight", "start_char": 1290, "end_char": 1706, "estimated_token_count": 80, "token_estimator": "heuristic-v1", "text": "## Gas vs Weight\n\nWhen you interact with the Polkadot Hub through an Ethereum wallet, you see familiar gas values. Under the hood, the runtime works with `weight` - a two-dimensional metric that combines `ref_time` and `proof_size`.\n\nThe system continuously translates between these representations: converting `weight` to gas when estimating costs, and converting gas back to `weight` when executing transactions."} -{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 3, "depth": 2, "title": "How Gas Estimation Works", "anchor": "how-gas-estimation-works", "start_char": 1706, "end_char": 2547, "estimated_token_count": 163, "token_estimator": "heuristic-v1", "text": "## How Gas Estimation Works\n\nWhen your wallet requests a gas estimate (`eth_estimateGas`), the Polkadot Hub performs a dry-run of your transaction. This test execution discovers:\n\n- How much computational time the contract will consume (`ref_time`).\n- How much state data needs to be verified (`proof_size`).\n- Whether any storage deposits are required (`storage_deposit`).\n\nThe system then calculates a gas estimate that covers all these costs, including:\n\n- Base transaction overhead (intrinsic costs like signature verification, nonce/account checks, and dispatch setup).\n- Transaction length fees (charges for the transaction size in bytes).\n- The actual contract execution costs.\n- Any storage deposits.\n\nThe gas estimate also includes a small safety buffer to account for slight differences between the test run and actual execution."} -{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 4, "depth": 2, "title": "Dynamic Gas Pricing", "anchor": "dynamic-gas-pricing", "start_char": 2547, "end_char": 3440, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Dynamic Gas Pricing\n\nPallet revive uses dynamic pricing through a \"fee multiplier\" that adjusts based on network congestion:\n\n- When blocks are full, the multiplier increases, making transactions more expensive.\n- When blocks are empty, the multiplier decreases, making transactions cheaper.\n- The multiplier updates after every block based on utilization.\n\nThis creates a market-based pricing mechanism similar to Ethereum's base fee, helping to manage network resources efficiently.\n\nThe gas price returned during estimation is simply the current fee multiplier value.\n\n!!! warning \"Important for Users\"\n Because the fee multiplier can change between when you estimate gas and when your transaction executes, you can add a safety buffer (10-20%) to both your gas limit and gas price. This ensures your transaction will execute successfully even if network conditions change slightly."} -{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 5, "depth": 2, "title": "Transaction Execution Flow", "anchor": "transaction-execution-flow", "start_char": 3440, "end_char": 4936, "estimated_token_count": 353, "token_estimator": "heuristic-v1", "text": "## Transaction Execution Flow\n\nThe following diagram illustrates the complete lifecycle of a transaction from submission to settlement:\n\n```mermaid\ngraph TD\n U[User/Wallet] --> M[Transaction pool]\n M --> P[Pre-dispatch convert gas to weight and create hold]\n P --> C{Sufficient funds}\n C -->|No| R[Rejected]\n C -->|Yes| X[Execute contract within limits]\n X --> S[Settle fee from actual weight and length; refund]\n S --> B[Included in block]\n```\n\nThe transaction execution flow is as follows:\n\n- **Pool and pre-dispatch**: The transaction enters the pool, `gas` is mapped to `weight`, and a temporary hold is created for the maximum fee exposure. Weight is a two-dimensional tuple (`ref_time`, `proof_size`). Each dimension is tracked independently. The [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\\_blank} conversion takes the maximum of the two dimensions (after applying their respective coefficients) to determine the fee.\n- **Funds check**: If the hold is insufficient, the transaction is rejected before any execution.\n- **Execution**: If sufficient, the contract runs within the derived weight limits; a `storage_deposit` may be reserved when new storage is created.\n- **Settlement**: Fees are charged from the actual `weight` used plus the length fee; any unused hold is refunded.\n- **Inclusion**: After settlement, the transaction is included in the block."} -{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 6, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 4936, "end_char": 5234, "estimated_token_count": 51, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nThe Polkadot Hub's gas model is designed to be Ethereum-compatible while providing the flexibility and efficiency of Polkadot's resource metering system. Developers can build on Ethereum tooling while leveraging Polkadot's advanced features like multi-dimensional resource tracking."} +{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 13, "end_char": 294, "estimated_token_count": 49, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nThe Polkadot Hub implements a gas model that bridges Ethereum's familiar gas concept with Polkadot's more sophisticated resource metering system. This page explains how gas works in the Polkadot Hub and what developers need to know when building smart contracts."} +{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 1, "depth": 2, "title": "Understanding Resources in the Polkadot Hub", "anchor": "understanding-resources-in-the-polkadot-hub", "start_char": 294, "end_char": 1294, "estimated_token_count": 189, "token_estimator": "heuristic-v1", "text": "## Understanding Resources in the Polkadot Hub\n\nUnlike Ethereum, which uses a single gas value to measure everything, the Polkadot Hub tracks three separate resources:\n\n- **`ref_time`**: Measures computational time. It is the closest equivalent to traditional gas and represents the amount of CPU time your contract execution consumes.\n- **`proof_size`**: Measures the amount of state data that validators need to verify. When your contract reads from storage or makes state queries, this metric tracks the size of the proofs needed to validate those operations.\n- **`storage_deposit`**: Is a native balance that gets temporarily locked when your contract creates new storage entries. This prevents state bloat by requiring contracts to pay for the storage they use. The deposit is returned when the storage is freed.\n\nFor Ethereum wallet compatibility, the Polkadot Hub's RPC layer automatically maps these three dimensions into a single gas value that wallets can understand and display to users."} +{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 2, "depth": 2, "title": "Gas vs Weight", "anchor": "gas-vs-weight", "start_char": 1294, "end_char": 1710, "estimated_token_count": 80, "token_estimator": "heuristic-v1", "text": "## Gas vs Weight\n\nWhen you interact with the Polkadot Hub through an Ethereum wallet, you see familiar gas values. Under the hood, the runtime works with `weight` - a two-dimensional metric that combines `ref_time` and `proof_size`.\n\nThe system continuously translates between these representations: converting `weight` to gas when estimating costs, and converting gas back to `weight` when executing transactions."} +{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 3, "depth": 2, "title": "How Gas Estimation Works", "anchor": "how-gas-estimation-works", "start_char": 1710, "end_char": 2551, "estimated_token_count": 163, "token_estimator": "heuristic-v1", "text": "## How Gas Estimation Works\n\nWhen your wallet requests a gas estimate (`eth_estimateGas`), the Polkadot Hub performs a dry-run of your transaction. This test execution discovers:\n\n- How much computational time the contract will consume (`ref_time`).\n- How much state data needs to be verified (`proof_size`).\n- Whether any storage deposits are required (`storage_deposit`).\n\nThe system then calculates a gas estimate that covers all these costs, including:\n\n- Base transaction overhead (intrinsic costs like signature verification, nonce/account checks, and dispatch setup).\n- Transaction length fees (charges for the transaction size in bytes).\n- The actual contract execution costs.\n- Any storage deposits.\n\nThe gas estimate also includes a small safety buffer to account for slight differences between the test run and actual execution."} +{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 4, "depth": 2, "title": "Dynamic Gas Pricing", "anchor": "dynamic-gas-pricing", "start_char": 2551, "end_char": 3444, "estimated_token_count": 161, "token_estimator": "heuristic-v1", "text": "## Dynamic Gas Pricing\n\nPallet revive uses dynamic pricing through a \"fee multiplier\" that adjusts based on network congestion:\n\n- When blocks are full, the multiplier increases, making transactions more expensive.\n- When blocks are empty, the multiplier decreases, making transactions cheaper.\n- The multiplier updates after every block based on utilization.\n\nThis creates a market-based pricing mechanism similar to Ethereum's base fee, helping to manage network resources efficiently.\n\nThe gas price returned during estimation is simply the current fee multiplier value.\n\n!!! warning \"Important for Users\"\n Because the fee multiplier can change between when you estimate gas and when your transaction executes, you can add a safety buffer (10-20%) to both your gas limit and gas price. This ensures your transaction will execute successfully even if network conditions change slightly."} +{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 5, "depth": 2, "title": "Transaction Execution Flow", "anchor": "transaction-execution-flow", "start_char": 3444, "end_char": 4940, "estimated_token_count": 353, "token_estimator": "heuristic-v1", "text": "## Transaction Execution Flow\n\nThe following diagram illustrates the complete lifecycle of a transaction from submission to settlement:\n\n```mermaid\ngraph TD\n U[User/Wallet] --> M[Transaction pool]\n M --> P[Pre-dispatch convert gas to weight and create hold]\n P --> C{Sufficient funds}\n C -->|No| R[Rejected]\n C -->|Yes| X[Execute contract within limits]\n X --> S[Settle fee from actual weight and length; refund]\n S --> B[Included in block]\n```\n\nThe transaction execution flow is as follows:\n\n- **Pool and pre-dispatch**: The transaction enters the pool, `gas` is mapped to `weight`, and a temporary hold is created for the maximum fee exposure. Weight is a two-dimensional tuple (`ref_time`, `proof_size`). Each dimension is tracked independently. The [`WeightToFee`](https://docs.rs/pallet-transaction-payment/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee){target=\\_blank} conversion takes the maximum of the two dimensions (after applying their respective coefficients) to determine the fee.\n- **Funds check**: If the hold is insufficient, the transaction is rejected before any execution.\n- **Execution**: If sufficient, the contract runs within the derived weight limits; a `storage_deposit` may be reserved when new storage is created.\n- **Settlement**: Fees are charged from the actual `weight` used plus the length fee; any unused hold is refunded.\n- **Inclusion**: After settlement, the transaction is included in the block."} +{"page_id": "smart-contracts-for-eth-devs-gas-model", "page_title": "Gas Model on the Polkadot Hub", "index": 6, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 4940, "end_char": 5238, "estimated_token_count": 51, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nThe Polkadot Hub's gas model is designed to be Ethereum-compatible while providing the flexibility and efficiency of Polkadot's resource metering system. Developers can build on Ethereum tooling while leveraging Polkadot's advanced features like multi-dimensional resource tracking."} {"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 187, "end_char": 679, "estimated_token_count": 115, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nPolkadot Hub provides Ethereum compatibility through its JSON-RPC interface, allowing developers to interact with the chain using familiar Ethereum tooling and methods. This document outlines the supported [Ethereum JSON-RPC methods](https://ethereum.org/developers/docs/apis/json-rpc/#json-rpc-methods){target=\\_blank} and provides examples of how to use them.\n\nThis guide uses the Polkadot Hub TestNet endpoint:\n\n```text\nhttps://testnet-passet-hub-eth-rpc.polkadot.io\n```"} {"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 1, "depth": 2, "title": "Available Methods", "anchor": "available-methods", "start_char": 679, "end_char": 701, "estimated_token_count": 4, "token_estimator": "heuristic-v1", "text": "## Available Methods"} {"page_id": "smart-contracts-for-eth-devs-json-rpc-apis", "page_title": "JSON-RPC APIs", "index": 2, "depth": 3, "title": "eth_accounts", "anchor": "eth_accounts", "start_char": 701, "end_char": 1132, "estimated_token_count": 146, "token_estimator": "heuristic-v1", "text": "### eth_accounts\n\nReturns a list of addresses owned by the client. [Reference](https://ethereum.org/developers/docs/apis/json-rpc/#eth_accounts){target=\\_blank}.\n\n**Parameters**:\n\nNone.\n\n**Example**:\n\n```bash title=\"eth_accounts\"\ncurl -X POST https://testnet-passet-hub-eth-rpc.polkadot.io \\\n-H \"Content-Type: application/json\" \\\n--data '{\n \"jsonrpc\":\"2.0\",\n \"method\":\"eth_accounts\",\n \"params\":[],\n \"id\":1\n}'\n```\n\n---"} diff --git a/llms.txt b/llms.txt index 07e029294..6146be985 100644 --- a/llms.txt +++ b/llms.txt @@ -6,36 +6,19 @@ This directory lists URLs for raw Markdown pages that complement the rendered pages on the documentation site. Use these Markdown files to retain semantic context when prompting models while avoiding passing HTML elements. ## Metadata -- Documentation pages: 145 -- Categories: 13 +- Documentation pages: 88 +- Categories: 11 ## Docs This section lists documentation pages by category. Each entry links to a raw markdown version of the page and includes a short description. A page may appear in multiple categories. Docs: Basics -- [Register a Local Asset](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md): Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. - [Add Pallets to the Runtime](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime-pallet-development-add-pallet-to-runtime.md): Add pallets to your runtime for custom functionality. Learn to configure and integrate pallets in Polkadot SDK-based blockchains. - [Overview of FRAME](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-customize-runtime.md): Learn how Polkadot SDK’s FRAME framework simplifies blockchain development with modular pallets and support libraries for efficient runtime design. - [Get Started with Parachain Development](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-get-started.md): Practical examples and tutorials for building and deploying Polkadot parachains, covering everything from launch to customization and cross-chain messaging. - [Install Polkadot SDK](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-install-polkadot-sdk.md): Install all required Polkadot SDK dependencies, set up the SDK itself, and verify that it runs correctly on your machine. -- [Introduction to XCM](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md): Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. +- [Get Started with XCM](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md): Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. - [Set Up the Polkadot SDK Parachain Template](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-launch-a-parachain-set-up-the-parachain-template.md): Learn how to set up and run the Polkadot SDK Parachain Template locally, creating a ready-to-customize foundation for your parachain. -- [On-Chain Governance Overview](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md): Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. -- [Polkadot SDK Accounts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md): Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. -- [Blocks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md): Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. -- [Transactions Weights and Fees](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md): Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. -- [Transactions](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md): Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. -- [Chain Data](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md): Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. -- [Cryptography](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md): A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. -- [Data Encoding](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md): SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. -- [Interoperability](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md): Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. -- [Networks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md): Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. -- [Node and Runtime](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md): Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. -- [Randomness](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md): Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. -- [Parachains Overview](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md): Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. -- [Overview of the Polkadot Relay Chain](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md): Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. -- [XCM Tools](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md): Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. -- [Technical Reference Overview](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md): Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. - [Deploy an ERC-20 to Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-hardhat.md): Deploy an ERC-20 token on Polkadot Hub using PolkaVM. This guide covers contract creation, compilation, deployment, and interaction via Hardhat. - [Deploy an ERC-20 to Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-erc20-erc20-remix.md): Deploy an ERC-20 token contract on Polkadot Hub. This guide covers contract creation, compilation, deployment, and interaction via the Remix IDE. - [Deploy an NFT to Polkadot Hub with Foundry](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-smart-contracts-deploy-nft-.foundry.md): Learn how to deploy an ERC-721 NFT contract to Polkadot Hub using Foundry, a Rust toolkit with high-performance compilation. @@ -67,7 +50,7 @@ Docs: Smart Contracts - [Use the Remix IDE on Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-get-started.md): Explore the smart contract development and deployment process on Polkadot Hub using Remix IDE, a visual IDE for blockchain developers. - [Troubleshooting Remix IDE](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-remix-troubleshooting-faq.md): Common issues related to developing, compiling, and deploying smart contracts using Remix IDE on Polkadot Hub paired with troubleshooting suggestions. - [Block Explorers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-explorers.md): Access PolkaVM explorers like Subscan, BlockScout, and Routescan to track transactions, analyze contracts, and view on-chain data from smart contracts. -- [Faucet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-faucet.md): Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. +- [Get Tokens from the Official Faucet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-faucet.md): Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. - [Contract Deployment](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-contract-deployment.md): Compare deployment flows for REVM and PVM-based smart contracts on the Polkadot Hub. Includes single-step REVM flows and PVM’s two-step deployment model. - [Migration FAQs and Considerations](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-migration.md): Learn how to migrate your existing Ethereum contracts to the Polkadot Hub using REVM and PolkaVM by following these considerations. - [Get Started with Smart Contracts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-get-started.md): Practical examples for building and deploying smart contracts on Polkadot Hub, from connecting and tooling to deployment, integrations, and precompiles. @@ -100,48 +83,15 @@ Docs: Parachains - [Runtime Upgrades](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-runtime-upgrades.md): This page covers how runtime versioning and storage migration support forkless upgrades for Polkadot SDK-based networks and how they factor into chain upgrades. - [Storage Migrations](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-storage-migrations.md): Ensure smooth runtime upgrades with storage migrations, update data formats, and prevent errors. Learn when and how to implement migrations efficiently. - [Unlock a Parachain](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-runtime-maintenance-unlock-parachains.md): Learn how to unlock your parachain. This step-by-step guide covers verifying lock status, preparing calls, and executing the unlock process. -- [Get Started](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md): Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. -- [Get Started](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md): Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. -- [Parachains Overview](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains.md): Learn about parachains, specialized blockchains on Polkadot that gain shared security and interoperability. Discover how they work and the tools to build them. -- [Overview of the Polkadot Relay Chain](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md): Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. -- [Light Clients](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md): Light clients enable secure and efficient blockchain interaction without running a full node. Learn everything you need to know about light clients on Polkadot. -- [E2E Testing with Moonwall](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md): Enhance blockchain end-to-end testing with Moonwall's standardized environment setup, comprehensive configuration management, and simple network interactions. -- [Polkadot Omni Node](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md): Run parachain nodes easily with the polkadot-omni-node, a white-labeled binary that can run parachain nodes using a single pre-built solution. +- [Fork a Parachain Using Chopsticks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md): Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. +- [Run a Parachain Network](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md): Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. Docs: dApps -- [Convert Assets on Asset Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-convert-assets.md): A guide detailing the step-by-step process of converting assets on Asset Hub, helping users efficiently navigate asset management on the platform. -- [Register a Foreign Asset on Asset Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-foreign-asset.md): An in-depth guide to registering a foreign asset on the Asset Hub parachain, providing clear, step-by-step instructions. -- [Register a Local Asset](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-token-operations-register-local-asset.md): Comprehensive guide to registering a local asset on the Asset Hub system parachain, including step-by-step instructions. - [Deploying Uniswap V2 on Polkadot](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md): Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. - [Smart Contracts Cookbook Index](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook.md): Explore our full collection of tutorials and guides to learn step-by-step how to build, deploy, and work with smart contracts on Polkadot. -Docs: Networks -- [Networks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md): Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. - Docs: Polkadot Protocol -- [Introduction to XCM](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md): Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. -- [Origins and Tracks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance-origins-tracks.md): Explore Polkadot's OpenGov origins and tracks system, defining privilege levels, decision processes, and tailored pathways for network proposals. -- [On-Chain Governance Overview](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-governance.md): Discover Polkadot’s cutting-edge OpenGov system, enabling transparent, decentralized decision-making through direct democracy and flexible governance tracks. -- [Polkadot SDK Accounts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-accounts.md): Learn about account structures, balances, and address formats in the Polkadot SDK, including how to manage lifecycle, references, and balances. -- [Blocks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-blocks.md): Understand how blocks are produced, validated, and imported in Polkadot SDK-based blockchains, covering initialization, finalization, and authoring processes. -- [Transactions Weights and Fees](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-fees.md): Overview of transaction weights and fees in Polkadot SDK chains, detailing how fees are calculated using a defined formula and runtime specifics. -- [Transactions](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-blocks-transactions-fees-transactions.md): Learn how to construct, submit, and validate transactions in the Polkadot SDK, covering signed, unsigned, and inherent types of transactions. -- [Chain Data](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-chain-data.md): Learn how to expose and utilize chain data for blockchain applications. Discover runtime metadata, RPC APIs, and tools for efficient development. -- [Elastic Scaling](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-elastic-scaling.md): Learn how elastic scaling in Polkadot boosts parachain throughput, reduces latency, and supports dynamic, cost-efficient resource allocation. -- [Cryptography](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-cryptography.md): A concise guide to cryptography in blockchain, covering hash functions, encryption types, digital signatures, and elliptic curve applications. -- [Data Encoding](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-data-encoding.md): SCALE codec enables fast, efficient data encoding, ideal for resource-constrained environments like Wasm, supporting custom types and compact encoding. -- [Interoperability](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-interoperability.md): Explore the importance of interoperability in the Polkadot ecosystem, covering XCM, bridges, and cross-chain communication. -- [Networks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-networks.md): Explore Polkadot's testing and production networks, including Westend, Kusama, and Paseo, for efficient development, deployment, and testing. -- [Node and Runtime](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-node-and-runtime.md): Learn how Polkadot SDK-based nodes function, how the client and runtime are separated, and how they communicate using SCALE-encoded data. -- [Randomness](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-randomness.md): Explore the importance of randomness in PoS blockchains, focusing on Polkadot’s VRF-based approach to ensure fairness and security in validator selection. -- [Asset Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-assets-and-smart-contracts.md): Learn about Asset Hub in Polkadot, managing on-chain assets, foreign asset integration, and using XCM for cross-chain asset transfers. -- [Bridge Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-bridging.md): Learn about the Bridge Hub system parachain, a parachain that facilitates the interactions from Polkadot to the rest of Web3. -- [Collectives Chain](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-collectives-and-daos.md): Learn how the Collectives chain provides infrastructure for governance organizations, enabling decentralized network stewardship and decision-making. -- [Agile Coretime](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-agile-coretime.md): Explore the efficient scheduling mechanisms to access Polkadot cores to produce blockspace continuously or on-demand. -- [Proof of Stake Consensus](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-pos-consensus.md): Explore Polkadot's consensus protocols for secure, scalable, and decentralized network operation, including NPoS, BABE, GRANDPA, and BEEFY. -- [Overview of the Polkadot Relay Chain](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-consensus-and-security-relay-chain.md): Explore Polkadot's core architecture, including its multi-chain vision, shared security, and the DOT token's governance and staking roles. -- [People Chain](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub-people-and-identity.md): Learn how People chain secures decentralized identity management, empowering users to control and verify digital identities without central authorities. -- [Technical Reference Overview](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md): Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. +- [Get Started with XCM](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-interoperability-get-started.md): Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. - [Accounts in Asset Hub Smart Contracts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-accounts.md): Bridges Ethereum's 20-byte addresses with Polkadot's 32-byte accounts, enabling seamless interaction while maintaining compatibility with Ethereum tooling. - [Transactions and Fees on Asset Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-blocks-transactions-fees.md): Explore how Asset Hub smart contracts handle blocks, transactions, and fees with EVM compatibility, supporting various Ethereum transaction types. - [Dual Virtual Machine Stack](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-dual-vm-stack.md): Compare Polkadot’s dual smart contract VMs—REVM for EVM compatibility and PolkaVM for RISC-V performance, flexibility, and efficiency. @@ -166,19 +116,8 @@ Docs: Tooling - [Indexers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md): Discover blockchain indexers. Enhance data access, enable fast and complex queries, and optimize blockchain data for seamless app performance. - [Oracles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md): Learn about blockchain oracles, the essential bridges connecting blockchains with real-world data for decentralized applications in the Polkadot ecosystem. - [Wallets](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md): Explore blockchain wallets. Securely manage digital assets with hot wallets for online access or cold wallets for offline, enhanced security. -- [Get Started](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md): Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. -- [Get Started](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md): Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. -- [Dedot](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md): Dedot is a next-gen JavaScript client for Polkadot and Polkadot SDK-based blockchains, offering lightweight, tree-shakable APIs with strong TypeScript support. -- [Light Clients](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-light-clients.md): Light clients enable secure and efficient blockchain interaction without running a full node. Learn everything you need to know about light clients on Polkadot. -- [E2E Testing with Moonwall](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-moonwall.md): Enhance blockchain end-to-end testing with Moonwall's standardized environment setup, comprehensive configuration management, and simple network interactions. -- [Polkadot Omni Node](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-omninode.md): Run parachain nodes easily with the polkadot-omni-node, a white-labeled binary that can run parachain nodes using a single pre-built solution. -- [Polkadot-API](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md): Polkadot-API (PAPI) is a modular, composable library set designed for efficient interaction with Polkadot chains, prioritizing a "light-client first" approach. -- [Polkadart](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md): Polkadart is a type-safe, native Dart, SDK for Polkadot and any compatible Polkadot-SDK blockchain network. -- [Polkadot.js API](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md): Interact with Polkadot SDK-based chains easily using the Polkadot.js API. Query chain data, submit transactions, and more via JavaScript or Typescript. -- [Python Substrate Interface](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md): Learn how to connect to Polkadot SDK-based nodes, query data, submit transactions, and manage blockchain interactions using the Python Substrate Interface. -- [Sidecar REST API](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md): Learn about Substrate API Sidecar, a REST service that provides endpoints for interacting with Polkadot SDK-based chains and simplifies blockchain interactions. -- [Subxt Rust API](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md): Subxt is a Rust library for type-safe interaction with Polkadot SDK blockchains, enabling transactions, state queries, runtime API access, and more. -- [XCM Tools](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md): Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. +- [Fork a Parachain Using Chopsticks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-fork-a-parachain.md): Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. +- [Run a Parachain Network](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-testing-run-a-parachain-network.md): Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. - [Zero to Hero Smart Contract DApp](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-dapps-zero-to-hero.md): Learn how to build a decentralized application on Polkadot Hub using Viem and Next.js by creating a simple dApp that interacts with a smart contract. - [Deploying Uniswap V2 on Polkadot](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-cookbook-eth-dapps-uniswap-v2.md): Learn how to deploy and test Uniswap V2 on Polkadot Hub using Hardhat, bringing AMM-based token swaps to the Polkadot ecosystem. - [Use Hardhat with Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-get-started.md): Overview of Hardhat, a powerful development environment for creating, compiling, testing, and deploying smart contracts on Polkadot Hub. @@ -194,58 +133,27 @@ Docs: Tooling - [Web3.py](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-libraries-web3-py.md): Learn how to interact with Polkadot Hub using the Web3 python library, deploying Solidity contracts, and interacting with deployed smart contracts. Docs: Reference -- [Glossary](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-glossary.md): Glossary of terms used within the Polkadot ecosystem, Polkadot SDK, its subsequent libraries, and other relevant Web3 terminology. -- [Technical Reference Overview](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference.md): Learn about Polkadot's technical architecture, governance framework, parachain ecosystem, and the tools you need to build and interact with the network. - [JSON-RPC APIs](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-json-rpc-apis.md): JSON-RPC APIs guide for Polkadot Hub, covering supported methods, parameters, and examples for interacting with the chain. -Docs: Chain Interactions -- [Chain Interactions Overview](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions.md): Learn how to query data, send transactions, enable cross-chain communication, and manage accounts across the Polkadot ecosystem. - Docs: Dapps - [Indexers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-indexers.md): Discover blockchain indexers. Enhance data access, enable fast and complex queries, and optimize blockchain data for seamless app performance. - [Oracles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-oracles.md): Learn about blockchain oracles, the essential bridges connecting blockchains with real-world data for decentralized applications in the Polkadot ecosystem. - [Wallets](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/parachains-integrations-wallets.md): Explore blockchain wallets. Securely manage digital assets with hot wallets for online access or cold wallets for offline, enhanced security. -- [Dedot](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-dedot.md): Dedot is a next-gen JavaScript client for Polkadot and Polkadot SDK-based blockchains, offering lightweight, tree-shakable APIs with strong TypeScript support. -- [Polkadot-API](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-papi.md): Polkadot-API (PAPI) is a modular, composable library set designed for efficient interaction with Polkadot chains, prioritizing a "light-client first" approach. -- [Polkadart](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadart.md): Polkadart is a type-safe, native Dart, SDK for Polkadot and any compatible Polkadot-SDK blockchain network. -- [Polkadot.js API](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-polkadot-js-api.md): Interact with Polkadot SDK-based chains easily using the Polkadot.js API. Query chain data, submit transactions, and more via JavaScript or Typescript. -- [Python Substrate Interface](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-py-substrate-interface.md): Learn how to connect to Polkadot SDK-based nodes, query data, submit transactions, and manage blockchain interactions using the Python Substrate Interface. -- [Sidecar REST API](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-sidecar.md): Learn about Substrate API Sidecar, a REST service that provides endpoints for interacting with Polkadot SDK-based chains and simplifies blockchain interactions. -- [Subxt Rust API](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-subxt.md): Subxt is a Rust library for type-safe interaction with Polkadot SDK blockchains, enabling transactions, state queries, runtime API access, and more. -- [XCM Tools](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-xcm-tools.md): Explore essential XCM tools across Polkadot, crafted to enhance cross-chain functionality and integration within the ecosystem. Docs: Uncategorized -- [chain-interactions-accounts-create-account](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-accounts-create-account.md): No description available. -- [chain-interactions-accounts-query-accounts](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-accounts-query-accounts.md): No description available. -- [chain-interactions-query-data-query-rest](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-query-data-query-rest.md): No description available. -- [chain-interactions-query-data-query-sdks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-query-data-query-sdks.md): No description available. -- [chain-interactions-query-data-runtime-api-calls](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-query-data-runtime-api-calls.md): No description available. -- [chain-interactions-send-transactions-calculate-transaction-fees](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-calculate-transaction-fees.md): No description available. -- [Replay and Dry Run XCMs](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-interoperability-debug-and-preview-xcms.md): Replay and dry-run XCMs using Chopsticks with full logging enabled. Diagnose issues, trace message flow, and debug complex cross-chain interactions. -- [XCM Fee Estimation](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-interoperability-estimate-xcm-fees.md): This tutorial demonstrates how to estimate the fees for teleporting assets from the Paseo Asset Hub parachain to the Paseo Bridge Hub chain. -- [chain-interactions-send-transactions-interoperability-transfer-assets-out-of-polkadot](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-out-of-polkadot.md): No description available. -- [Transfer Assets Between Parachains](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-interoperability-transfer-assets-parachains.md): A step-by-step guide to using the ParaSpell XCM SDK to build, verify, and execute a transfer from one Parachain to another. -- [Send a Transaction While Paying the Fee with a Different Token](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-pay-fees-with-different-tokens.md): This tutorial demonstrates how to send a DOT transfer transaction while paying the fees using a different token on the Asset Hub. -- [chain-interactions-send-transactions-with-sdks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/chain-interactions-send-transactions-with-sdks.md): No description available. - [AI Ready Docs](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-ai-ready-docs.md): Download LLM-optimized files of the Polkadot documentation, including full content and category-specific resources for AI agents. - [Subscribe to Updates](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-explore-resources.md): Find Polkadot developer resources, tutorials, forums, governance proposals, and community platforms like StackExchange, Reddit, and YouTube. - [Get in Touch](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support-get-in-touch.md): Developer support for Polkadot via Telegram, Matrix, and Discord. Get help with parachains, smart contracts, nodes, and ecosystem tools. - [Support](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/get-support.md): Start here to get developer support for Polkadot. Connect with the team, find help, and explore resources beyond the documentation. - [Polkadot Developer Docs](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/index.md): Explore everything you need to start building on top of Polkadot, a protocol that provides parachains with shared security and interoperability using XCM. -- [reference-parachains-consensus-async-backing](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus-async-backing.md): No description available. -- [reference-parachains-consensus](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-parachains-consensus.md): No description available. -- [reference-polkadot-hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-polkadot-hub.md): No description available. -- [reference-tools-chopsticks](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-chopsticks.md): No description available. -- [ParaSpell XCM SDK](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-paraspell.md): A powerful open-source library that simplifies XCM integration, enabling developers to easily build interoperable dApps on Polkadot. -- [reference-tools-zombienet](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/reference-tools-zombienet.md): No description available. - [smart-contracts-dev-environments-hardhat-compile-and-test](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-compile-and-test.md): No description available. - [smart-contracts-dev-environments-hardhat-deploy-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-deploy-a-contract.md): No description available. - [smart-contracts-dev-environments-hardhat-install-and-config](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-install-and-config.md): No description available. - [smart-contracts-dev-environments-hardhat-troubleshooting](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-troubleshooting.md): No description available. - [smart-contracts-dev-environments-hardhat-verify-a-contract](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-dev-environments-hardhat-verify-a-contract.md): No description available. - [Gas Model on the Polkadot Hub](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-for-eth-devs-gas-model.md): Learn how gas estimation, pricing, and weight mapping work in the Polkadot Hub. -- [smart-contracts-integrations-indexers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-indexers.md): No description available. -- [smart-contracts-integrations-oracles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-oracles.md): No description available. +- [smart-contracts-integrations-.indexers](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-.indexers.md): No description available. +- [smart-contracts-integrations-.oracles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-.oracles.md): No description available. - [Advanced Functionalities via Precompiles](https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-precompiles.md): Explores how Polkadot integrates precompiles to run essential functions natively, improving the speed and efficiency of smart contracts on the Hub. Docs: dApp diff --git a/nodes-and-validators/run-a-validator/operational-tasks/general-management.md b/nodes-and-validators/run-a-validator/operational-tasks/general-management.md index dd8a19c29..a6752aaa1 100644 --- a/nodes-and-validators/run-a-validator/operational-tasks/general-management.md +++ b/nodes-and-validators/run-a-validator/operational-tasks/general-management.md @@ -3,6 +3,7 @@ title: General Management description: Optimize your Polkadot validator setup with advanced configuration techniques. Learn how to boost performance, enhance security, and ensure seamless operations. categories: Infrastructure --- + # General Management ## Introduction diff --git a/parachains/.nav.yml b/parachains/.nav.yml index a1683dede..63e728a05 100644 --- a/parachains/.nav.yml +++ b/parachains/.nav.yml @@ -3,7 +3,7 @@ nav: - 'Install Polkadot SDK': install-polkadot-sdk.md - 'Launch a Simple Parachain': launch-a-parachain - 'Customize Your Runtime': customize-runtime - - 'Testing': testing - - 'Runtime Upgrades and Maintenance': runtime-maintenance - - 'Interoperability': interoperability + - 'Test Your Runtime': testing + - 'Maintain and Upgrade Your Runtime': runtime-maintenance + - 'Enable Interoperability': interoperability - 'Integrations': integrations diff --git a/parachains/interoperability/get-started.md b/parachains/interoperability/get-started.md index e328f42df..17543f304 100644 --- a/parachains/interoperability/get-started.md +++ b/parachains/interoperability/get-started.md @@ -1,10 +1,10 @@ --- -title: Introduction to XCM +title: Get Started with XCM description: Unlock blockchain interoperability with XCM — Polkadot's Cross-Consensus Messaging format for cross-chain interactions. categories: Basics, Polkadot Protocol --- -# Introduction to XCM +# Get Started with XCM ## Introduction diff --git a/parachains/testing/fork-a-parachain.md b/parachains/testing/fork-a-parachain.md index 7fd1920d4..2a85b81a5 100644 --- a/parachains/testing/fork-a-parachain.md +++ b/parachains/testing/fork-a-parachain.md @@ -1,10 +1,10 @@ --- -title: Get Started +title: Fork a Parachain Using Chopsticks description: Simplify Polkadot SDK development with Chopsticks. Learn essential features, how to install Chopsticks, and how to configure local blockchain forks. categories: Parachains, Tooling --- -# Get Started +# Fork a Parachain Using Chopsticks ## Introduction diff --git a/parachains/testing/run-a-parachain-network.md b/parachains/testing/run-a-parachain-network.md index ff0fc207c..0c1a2a72b 100644 --- a/parachains/testing/run-a-parachain-network.md +++ b/parachains/testing/run-a-parachain-network.md @@ -1,10 +1,10 @@ --- -title: Get Started +title: Run a Parachain Network description: Quickly install and configure Zombienet to deploy and test Polkadot-based blockchain networks with this comprehensive getting-started guide. categories: Parachains, Tooling --- -# Get Started +# Run a Parachain Network Using Zombienet ## Introduction diff --git a/scripts/llms_config.json b/scripts/llms_config.json index 27bee59c4..4b885cd73 100644 --- a/scripts/llms_config.json +++ b/scripts/llms_config.json @@ -42,7 +42,7 @@ "terms-of-use.md", "privacy-policy.md" ], - "skip_paths": [".snippets", ".github", ".ai", ".venv", "venv"] + "skip_paths": [".snippets", ".github", ".ai", ".venv", "venv", ".reference", ".chain-interactions"] } }, diff --git a/smart-contracts/cookbook/.nav.yml b/smart-contracts/cookbook/.nav.yml index 967a352ff..9f8545e2e 100644 --- a/smart-contracts/cookbook/.nav.yml +++ b/smart-contracts/cookbook/.nav.yml @@ -1,6 +1,6 @@ nav: - 'Overview': index.md # TODO: Update name of page - 'Get Tokens from the Faucet': /smart-contracts/faucet/ -- 'EVM Smart Contracts': smart-contracts +- 'Build Smart Contracts': smart-contracts - 'Create a DApp': dapps - 'Port Ethereum DApps': eth-dapps diff --git a/smart-contracts/cookbook/dapps/zero-to-hero.md b/smart-contracts/cookbook/dapps/zero-to-hero.md index d45dc3a05..e1dd0c582 100644 --- a/smart-contracts/cookbook/dapps/zero-to-hero.md +++ b/smart-contracts/cookbook/dapps/zero-to-hero.md @@ -241,7 +241,7 @@ After deployment, you'll need the contract's Application Binary Interface (ABI) Now that you have your contract deployed, you're ready to build the dApp that will interact with it! -## Set Up the dApp Project +## Set Up the DApp Project Navigate to the root of the project, and create a new Next.js project called `dapp`: diff --git a/smart-contracts/faucet.md b/smart-contracts/faucet.md index 11e0eb3d6..39e70f6d2 100644 --- a/smart-contracts/faucet.md +++ b/smart-contracts/faucet.md @@ -1,5 +1,5 @@ --- -title: Faucet +title: Get Tokens from the Official Faucet description: Learn how to obtain test tokens from Polkadot faucets for development and testing purposes across different networks. tutorial_badge: Beginner categories: Smart Contracts diff --git a/smart-contracts/for-eth-devs/gas-model.md b/smart-contracts/for-eth-devs/gas-model.md index acf8a1d5c..a8df19acb 100644 --- a/smart-contracts/for-eth-devs/gas-model.md +++ b/smart-contracts/for-eth-devs/gas-model.md @@ -5,7 +5,7 @@ description: Learn how gas estimation, pricing, and weight mapping work in the P # Gas Model -## Overview +## Introduction The Polkadot Hub implements a gas model that bridges Ethereum's familiar gas concept with Polkadot's more sophisticated resource metering system. This page explains how gas works in the Polkadot Hub and what developers need to know when building smart contracts. diff --git a/smart-contracts/integrations/indexers.md b/smart-contracts/integrations/.indexers.md similarity index 100% rename from smart-contracts/integrations/indexers.md rename to smart-contracts/integrations/.indexers.md diff --git a/smart-contracts/integrations/.nav.yml b/smart-contracts/integrations/.nav.yml index fdae86b87..8e54f1c2c 100644 --- a/smart-contracts/integrations/.nav.yml +++ b/smart-contracts/integrations/.nav.yml @@ -1,4 +1,4 @@ nav: - 'Wallets': wallets.md - - 'Oracles': oracles.md - - 'Indexers': indexers.md +# - 'Oracles': oracles.md +# - 'Indexers': indexers.md diff --git a/smart-contracts/integrations/oracles.md b/smart-contracts/integrations/.oracles.md similarity index 100% rename from smart-contracts/integrations/oracles.md rename to smart-contracts/integrations/.oracles.md From e6f2c08a46f5e10e61cd5e46fc5cc753c57e100d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hussein?= <80422357+nhussein11@users.noreply.github.com> Date: Tue, 18 Nov 2025 22:49:23 -0300 Subject: [PATCH 12/12] FIX - wallets polkavm disclaimer removed (#1252) * fix: removing polkavm disclaimer * fix: llms --- .ai/categories/smart-contracts.md | 2 -- .ai/categories/tooling.md | 2 -- .ai/pages/smart-contracts-integrations-wallets.md | 2 -- .ai/site-index.json | 8 ++++---- llms-full.jsonl | 12 ++++++------ smart-contracts/integrations/wallets.md | 2 -- 6 files changed, 10 insertions(+), 18 deletions(-) diff --git a/.ai/categories/smart-contracts.md b/.ai/categories/smart-contracts.md index b5f0bfcb7..c3ad3ee60 100644 --- a/.ai/categories/smart-contracts.md +++ b/.ai/categories/smart-contracts.md @@ -7348,8 +7348,6 @@ Page Title: Wallets for Polkadot Hub # Wallets for Polkadot Hub -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction Connecting a compatible wallet is the first essential step for interacting with the Polkadot Hub ecosystem. This guide explores wallet options that support both Substrate and Ethereum compatible layers, enabling transactions and smart contract interactions. Whether you're a developer testing on Polkadot Hub or a user accessing the MainNet, understanding wallet configuration is crucial for accessing the full range of Polkadot Hub's capabilities. diff --git a/.ai/categories/tooling.md b/.ai/categories/tooling.md index f9c835d10..a5d3fcb87 100644 --- a/.ai/categories/tooling.md +++ b/.ai/categories/tooling.md @@ -7557,8 +7557,6 @@ Page Title: Wallets for Polkadot Hub # Wallets for Polkadot Hub -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction Connecting a compatible wallet is the first essential step for interacting with the Polkadot Hub ecosystem. This guide explores wallet options that support both Substrate and Ethereum compatible layers, enabling transactions and smart contract interactions. Whether you're a developer testing on Polkadot Hub or a user accessing the MainNet, understanding wallet configuration is crucial for accessing the full range of Polkadot Hub's capabilities. diff --git a/.ai/pages/smart-contracts-integrations-wallets.md b/.ai/pages/smart-contracts-integrations-wallets.md index 07c441745..5d781e217 100644 --- a/.ai/pages/smart-contracts-integrations-wallets.md +++ b/.ai/pages/smart-contracts-integrations-wallets.md @@ -7,8 +7,6 @@ url: https://docs.polkadot.com/smart-contracts/integrations/wallets/ # Wallets for Polkadot Hub -!!! smartcontract "PolkaVM Preview Release" - PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction Connecting a compatible wallet is the first essential step for interacting with the Polkadot Hub ecosystem. This guide explores wallet options that support both Substrate and Ethereum compatible layers, enabling transactions and smart contract interactions. Whether you're a developer testing on Polkadot Hub or a user accessing the MainNet, understanding wallet configuration is crucial for accessing the full range of Polkadot Hub's capabilities. diff --git a/.ai/site-index.json b/.ai/site-index.json index 46c15edae..72a12d9d2 100644 --- a/.ai/site-index.json +++ b/.ai/site-index.json @@ -4959,7 +4959,7 @@ ], "raw_md_url": "https://raw.githubusercontent.com/polkadot-developers/polkadot-docs/master/.ai/pages/smart-contracts-integrations-wallets.md", "html_url": "https://docs.polkadot.com/smart-contracts/integrations/wallets/", - "preview": "!!! smartcontract \"PolkaVM Preview Release\" PolkaVM smart contracts with Ethereum compatibility are in **early-stage development and may be unstable or incomplete**. ## Introduction", + "preview": "Connecting a compatible wallet is the first essential step for interacting with the Polkadot Hub ecosystem. This guide explores wallet options that support both Substrate and Ethereum compatible layers, enabling transactions and smart contract interactions. Whether you're a developer testing on Polkadot Hub or a user accessing the MainNet, understanding wallet configuration is crucial for accessing the full range of Polkadot Hub's capabilities.", "outline": [ { "depth": 2, @@ -4993,12 +4993,12 @@ } ], "stats": { - "chars": 7340, - "words": 1041, + "chars": 7170, + "words": 1020, "headings": 6, "estimated_token_count_total": 1627 }, - "hash": "sha256:65809486f62f60c6a6ac8109f9f027361683c23f639991a045ec5c057b665026", + "hash": "sha256:d64a3162e12b0224165687558278d5e18e10d1a8c406068250820c3d16233457", "token_estimator": "heuristic-v1" }, { diff --git a/llms-full.jsonl b/llms-full.jsonl index b27c492bd..778092bc8 100644 --- a/llms-full.jsonl +++ b/llms-full.jsonl @@ -656,12 +656,12 @@ {"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 4, "depth": 2, "title": "Libraries", "anchor": "libraries", "start_char": 7141, "end_char": 8154, "estimated_token_count": 317, "token_estimator": "heuristic-v1", "text": "## Libraries\n\nChoose the client libraries that fit your stack for connecting wallets and calling contracts.\n\n| Library | Description |\n|:------------------------------------------------------------------:|:-------------------------------------------------------:|\n| [Ethers.js](/smart-contracts/libraries/ethers-js/){target=\\_blank} | Connect, sign, and interact with contracts using Ethers |\n| [viem](/smart-contracts/libraries/viem/){target=\\_blank} | Type‑safe EVM interactions and utilities |\n| [Wagmi](/smart-contracts/libraries/wagmi/){target=\\_blank} | React hooks for wallet connections and contract calls |\n| [Web3.js](/smart-contracts/libraries/web3-js/){target=\\_blank} | Web3 provider and contract APIs |\n| [Web3.py](/smart-contracts/libraries/web3-py/){target=\\_blank} | Python toolkit for on‑chain interactions and scripts |"} {"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 5, "depth": 2, "title": "Integrations", "anchor": "integrations", "start_char": 8154, "end_char": 8842, "estimated_token_count": 224, "token_estimator": "heuristic-v1", "text": "## Integrations\n\nIntegrate essential services like wallets, indexers, and oracles to round out your dApp.\n\n| Integration | Description |\n|:-------------------------------------------------------------------:|:-----------------------------------------:|\n| [Wallets](/smart-contracts/integrations/wallets/){target=\\_blank} | Supported wallets and configuration notes |\n| [Indexers](/smart-contracts/integrations/indexers/){target=\\_blank} | Index and query blockchain data |\n| [Oracles](/smart-contracts/integrations/oracles/){target=\\_blank} | Bring external data on‑chain |"} {"page_id": "smart-contracts-get-started", "page_title": "Get Started with Smart Contracts", "index": 6, "depth": 2, "title": "Precompiles", "anchor": "precompiles", "start_char": 8842, "end_char": 10103, "estimated_token_count": 362, "token_estimator": "heuristic-v1", "text": "## Precompiles\n\nDiscover precompiled system contracts available on the Hub and how to use them.\n\n| Topic | Description |\n|:------------------------------------------------------------------------:|:---------------------------------------------------:|\n| [Overview of Precompiles](/smart-contracts/precompiles/){target=\\_blank} | What precompiles are available on the Hub |\n| [ETH Native](/smart-contracts/precompiles/eth-native/){target=\\_blank} | EVM precompiles and interfaces |\n| [Staking](/smart-contracts/precompiles/staking/){target=\\_blank} | Interact with staking functionality via precompiles |\n| [XCM](/smart-contracts/precompiles/xcm/){target=\\_blank} | Cross‑chain messaging helpers for contracts |\n\nFrom here, follow the quick starts to get connected, iterate locally with your preferred tools, and use the guides, libraries, integrations, and precompiles as you grow into production‑ready dApps. If you get stuck, [open an issue](https://github.com/polkadot-developers/polkadot-docs/issues/new?template=docs-issue.yml){target=\\_blank} or reach out in the community channels."} -{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 198, "end_char": 665, "estimated_token_count": 75, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nConnecting a compatible wallet is the first essential step for interacting with the Polkadot Hub ecosystem. This guide explores wallet options that support both Substrate and Ethereum compatible layers, enabling transactions and smart contract interactions. Whether you're a developer testing on Polkadot Hub or a user accessing the MainNet, understanding wallet configuration is crucial for accessing the full range of Polkadot Hub's capabilities."} -{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 1, "depth": 2, "title": "Connect Your Wallet", "anchor": "connect-your-wallet", "start_char": 665, "end_char": 689, "estimated_token_count": 5, "token_estimator": "heuristic-v1", "text": "## Connect Your Wallet"} -{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 2, "depth": 3, "title": "MetaMask", "anchor": "metamask", "start_char": 689, "end_char": 2383, "estimated_token_count": 403, "token_estimator": "heuristic-v1", "text": "### MetaMask\n\n[MetaMask](https://metamask.io/){target=\\_blank} is a popular wallet for interacting with Ethereum-compatible chains. It allows users to connect to test networks that support Ethereum-based smart contracts. However, it's important to emphasize that MetaMask primarily facilitates interactions with smart contracts, giving users access to various chain functionalities. \n\nTo get started with MetaMask, you need to install the [MetaMask extension](https://metamask.io/download/){target=\\_blank} and add it to the browser. Once you install MetaMask, you can set up a new wallet and securely store your seed phrase. This phrase is crucial for recovery in case you lose access.\n\nFor example, to connect to the Polkadot Hub TestNet via MetaMask, you need to follow these steps:\n\n1. Open the MetaMask extension and click on the network icon to switch to the Polkadot Hub TestNet.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-1.webp){: .browser-extension}\n\n2. Click on the **Add a custom network** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-2.webp){: .browser-extension}\n\n3. Complete the necessary fields, then click the **Save** button (refer to the [Networks](/smart-contracts/connect/#networks-details){target=\\_blank} section for copy and paste parameters).\n\n ![](/images/smart-contracts/integrations/wallets/wallets-3.webp){: .browser-extension}\n\n4. Click on **Polkadot Hub TestNet** to switch the network.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-4.webp){: .browser-extension}\n\nThe steps in the preceding section can be used to connect to any chain by modifying the network specification and endpoint parameters."} -{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 3, "depth": 3, "title": "SubWallet", "anchor": "subwallet", "start_char": 2383, "end_char": 4969, "estimated_token_count": 613, "token_estimator": "heuristic-v1", "text": "### SubWallet\n\n[SubWallet](https://www.subwallet.app/){target=\\_blank} is a popular non-custodial wallet solution for Polkadot and Ethereum ecosystems. It offers seamless integration with Polkadot SDK-based networks while maintaining Ethereum compatibility, making the wallet an ideal choice for users and developers to interact with Polkadot Hub.\n\nSubWallet now fully supports the [Polkadot Hub TestNet](/polkadot-protocol/smart-contract-basics/networks/#test-networks){target=\\_blank} where developers can deploy and interact with Ethereum-compatible, Solidity smart contracts.\n\nYou can easily view and manage your Paseo native token (PAS) using the Ethereum RPC endpoint (Passet Hub EVM) or the Substrate node RPC endpoint (passet-hub).\n\n??? code \"Polkadot Hub TestNet\"\n You can see support here for Polkadot Hub's TestNet. The **Passet Hub EVM** network uses an ETH RPC endpoint, and the **passet-hub** uses a Substrate endpoint.\n The ETH RPC endpoint will let you send transactions that follow an ETH format, while the Substrate endpoint will follow a Substrate transaction format.\n Note the PAS token, which is the native token of the Polkadot Hub TestNet.\n\n ![](/images/smart-contracts/integrations/wallets/subwallet-PAS.webp){: .browser-extension}\n\nTo connect to Polkadot Hub TestNet using SubWallet, follow these steps:\n\n1. Install the [SubWallet browser extension](https://chromewebstore.google.com/detail/subwallet-polkadot-wallet/onhogfjeacnfoofkfgppdlbmlmnplgbn?hl=en){target=\\_blank} and set up your wallet by following the on-screen instructions, or refer to our [step-by-step guide](https://docs.subwallet.app/main/extension-user-guide/getting-started/install-subwallet){target=\\_blank} for assistance.\n\n2. After setting up your wallet, click the List icon at the top left corner of the extension window to open **Settings**.\n\n ![](/images/smart-contracts/integrations/wallets/subwallet-01.webp){: .browser-extension}\n\n3. Scroll down and select **Manage networks**.\n\n ![](/images/smart-contracts/integrations/wallets/subwallet-02.webp){: .browser-extension}\n\n4. In the Manage network screen, either scroll down or type in the search bar to find the networks. Once done, enable the toggle next to the network name.\n\n ![](/images/smart-contracts/integrations/wallets/subwallet-03.webp){: .browser-extension}\n\n You are now ready to use SubWallet to interact with [Polkadot Hub TestNet](/smart-contracts/connect/#networks-details){target=\\_blank} seamlessly!\n\n![](/images/smart-contracts/integrations/wallets/subwallet-04.webp){: .browser-extension}"} -{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 4, "depth": 3, "title": "Talisman", "anchor": "talisman", "start_char": 4969, "end_char": 6716, "estimated_token_count": 431, "token_estimator": "heuristic-v1", "text": "### Talisman\n\n[Talisman](https://talisman.xyz/){target=\\_blank} is a specialized wallet for the Polkadot ecosystem that supports both Substrate and EVM accounts, making it an excellent choice for Polkadot Hub interactions. Talisman offers a more integrated experience for Polkadot-based chains while still providing Ethereum compatibility.\n\nTo use Talisman with Polkadot Hub TestNet:\n\n1. Install the [Talisman extension](https://talisman.xyz/download){target=\\_blank} and set up your wallet by following the on-screen instructions.\n\n2. Once installed, click on the Talisman icon in your browser extensions and click on the **Settings** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-5.webp){: .browser-extension}\n\n3. Click the button **All settings**.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-6.webp){: .browser-extension}\n\n4. Go to the **Networks & Tokens** section.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-7.webp)\n\n5. Click the **Manage networks** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-8.webp)\n\n6. Click the **+ Add network** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-9.webp)\n\n7. Fill in the form with the required parameters and click the **Add network** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-10.webp)\n\n8. After that, you can switch to the Polkadot Hub TestNet by clicking on the network icon and selecting **Polkadot Hub TestNet**.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-11.webp)\n\nAfter selecting the network, Talisman will automatically configure the necessary RPC URL and chain ID for you. You can now use Talisman to interact with the Polkadot Hub TestNet."} -{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 5, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 6716, "end_char": 7340, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nChoosing the right wallet for Polkadot Hub interactions depends on your specific requirements and familiarity with different interfaces. MetaMask provides a familiar entry point for developers with Ethereum experience, while Talisman offers deeper integration with Polkadot's unique features and native support for both EVM and Substrate accounts. By properly configuring your wallet connection, you gain access to the full spectrum of Polkadot Hub's capabilities.\n\n!!!info\n Remember to always verify network parameters when connecting to ensure a secure and reliable connection to the Polkadot ecosystem."} +{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 28, "end_char": 495, "estimated_token_count": 75, "token_estimator": "heuristic-v1", "text": "## Introduction\n\nConnecting a compatible wallet is the first essential step for interacting with the Polkadot Hub ecosystem. This guide explores wallet options that support both Substrate and Ethereum compatible layers, enabling transactions and smart contract interactions. Whether you're a developer testing on Polkadot Hub or a user accessing the MainNet, understanding wallet configuration is crucial for accessing the full range of Polkadot Hub's capabilities."} +{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 1, "depth": 2, "title": "Connect Your Wallet", "anchor": "connect-your-wallet", "start_char": 495, "end_char": 519, "estimated_token_count": 5, "token_estimator": "heuristic-v1", "text": "## Connect Your Wallet"} +{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 2, "depth": 3, "title": "MetaMask", "anchor": "metamask", "start_char": 519, "end_char": 2213, "estimated_token_count": 403, "token_estimator": "heuristic-v1", "text": "### MetaMask\n\n[MetaMask](https://metamask.io/){target=\\_blank} is a popular wallet for interacting with Ethereum-compatible chains. It allows users to connect to test networks that support Ethereum-based smart contracts. However, it's important to emphasize that MetaMask primarily facilitates interactions with smart contracts, giving users access to various chain functionalities. \n\nTo get started with MetaMask, you need to install the [MetaMask extension](https://metamask.io/download/){target=\\_blank} and add it to the browser. Once you install MetaMask, you can set up a new wallet and securely store your seed phrase. This phrase is crucial for recovery in case you lose access.\n\nFor example, to connect to the Polkadot Hub TestNet via MetaMask, you need to follow these steps:\n\n1. Open the MetaMask extension and click on the network icon to switch to the Polkadot Hub TestNet.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-1.webp){: .browser-extension}\n\n2. Click on the **Add a custom network** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-2.webp){: .browser-extension}\n\n3. Complete the necessary fields, then click the **Save** button (refer to the [Networks](/smart-contracts/connect/#networks-details){target=\\_blank} section for copy and paste parameters).\n\n ![](/images/smart-contracts/integrations/wallets/wallets-3.webp){: .browser-extension}\n\n4. Click on **Polkadot Hub TestNet** to switch the network.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-4.webp){: .browser-extension}\n\nThe steps in the preceding section can be used to connect to any chain by modifying the network specification and endpoint parameters."} +{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 3, "depth": 3, "title": "SubWallet", "anchor": "subwallet", "start_char": 2213, "end_char": 4799, "estimated_token_count": 613, "token_estimator": "heuristic-v1", "text": "### SubWallet\n\n[SubWallet](https://www.subwallet.app/){target=\\_blank} is a popular non-custodial wallet solution for Polkadot and Ethereum ecosystems. It offers seamless integration with Polkadot SDK-based networks while maintaining Ethereum compatibility, making the wallet an ideal choice for users and developers to interact with Polkadot Hub.\n\nSubWallet now fully supports the [Polkadot Hub TestNet](/polkadot-protocol/smart-contract-basics/networks/#test-networks){target=\\_blank} where developers can deploy and interact with Ethereum-compatible, Solidity smart contracts.\n\nYou can easily view and manage your Paseo native token (PAS) using the Ethereum RPC endpoint (Passet Hub EVM) or the Substrate node RPC endpoint (passet-hub).\n\n??? code \"Polkadot Hub TestNet\"\n You can see support here for Polkadot Hub's TestNet. The **Passet Hub EVM** network uses an ETH RPC endpoint, and the **passet-hub** uses a Substrate endpoint.\n The ETH RPC endpoint will let you send transactions that follow an ETH format, while the Substrate endpoint will follow a Substrate transaction format.\n Note the PAS token, which is the native token of the Polkadot Hub TestNet.\n\n ![](/images/smart-contracts/integrations/wallets/subwallet-PAS.webp){: .browser-extension}\n\nTo connect to Polkadot Hub TestNet using SubWallet, follow these steps:\n\n1. Install the [SubWallet browser extension](https://chromewebstore.google.com/detail/subwallet-polkadot-wallet/onhogfjeacnfoofkfgppdlbmlmnplgbn?hl=en){target=\\_blank} and set up your wallet by following the on-screen instructions, or refer to our [step-by-step guide](https://docs.subwallet.app/main/extension-user-guide/getting-started/install-subwallet){target=\\_blank} for assistance.\n\n2. After setting up your wallet, click the List icon at the top left corner of the extension window to open **Settings**.\n\n ![](/images/smart-contracts/integrations/wallets/subwallet-01.webp){: .browser-extension}\n\n3. Scroll down and select **Manage networks**.\n\n ![](/images/smart-contracts/integrations/wallets/subwallet-02.webp){: .browser-extension}\n\n4. In the Manage network screen, either scroll down or type in the search bar to find the networks. Once done, enable the toggle next to the network name.\n\n ![](/images/smart-contracts/integrations/wallets/subwallet-03.webp){: .browser-extension}\n\n You are now ready to use SubWallet to interact with [Polkadot Hub TestNet](/smart-contracts/connect/#networks-details){target=\\_blank} seamlessly!\n\n![](/images/smart-contracts/integrations/wallets/subwallet-04.webp){: .browser-extension}"} +{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 4, "depth": 3, "title": "Talisman", "anchor": "talisman", "start_char": 4799, "end_char": 6546, "estimated_token_count": 431, "token_estimator": "heuristic-v1", "text": "### Talisman\n\n[Talisman](https://talisman.xyz/){target=\\_blank} is a specialized wallet for the Polkadot ecosystem that supports both Substrate and EVM accounts, making it an excellent choice for Polkadot Hub interactions. Talisman offers a more integrated experience for Polkadot-based chains while still providing Ethereum compatibility.\n\nTo use Talisman with Polkadot Hub TestNet:\n\n1. Install the [Talisman extension](https://talisman.xyz/download){target=\\_blank} and set up your wallet by following the on-screen instructions.\n\n2. Once installed, click on the Talisman icon in your browser extensions and click on the **Settings** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-5.webp){: .browser-extension}\n\n3. Click the button **All settings**.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-6.webp){: .browser-extension}\n\n4. Go to the **Networks & Tokens** section.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-7.webp)\n\n5. Click the **Manage networks** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-8.webp)\n\n6. Click the **+ Add network** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-9.webp)\n\n7. Fill in the form with the required parameters and click the **Add network** button.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-10.webp)\n\n8. After that, you can switch to the Polkadot Hub TestNet by clicking on the network icon and selecting **Polkadot Hub TestNet**.\n\n ![](/images/smart-contracts/integrations/wallets/wallets-11.webp)\n\nAfter selecting the network, Talisman will automatically configure the necessary RPC URL and chain ID for you. You can now use Talisman to interact with the Polkadot Hub TestNet."} +{"page_id": "smart-contracts-integrations-wallets", "page_title": "Wallets for Polkadot Hub", "index": 5, "depth": 2, "title": "Conclusion", "anchor": "conclusion", "start_char": 6546, "end_char": 7170, "estimated_token_count": 100, "token_estimator": "heuristic-v1", "text": "## Conclusion\n\nChoosing the right wallet for Polkadot Hub interactions depends on your specific requirements and familiarity with different interfaces. MetaMask provides a familiar entry point for developers with Ethereum experience, while Talisman offers deeper integration with Polkadot's unique features and native support for both EVM and Substrate accounts. By properly configuring your wallet connection, you gain access to the full spectrum of Polkadot Hub's capabilities.\n\n!!!info\n Remember to always verify network parameters when connecting to ensure a secure and reliable connection to the Polkadot ecosystem."} {"page_id": "smart-contracts-libraries-ethers-js", "page_title": "Deploy Contracts to Polkadot Hub with Ethers.js", "index": 0, "depth": 2, "title": "Introduction", "anchor": "introduction", "start_char": 183, "end_char": 709, "estimated_token_count": 105, "token_estimator": "heuristic-v1", "text": "## Introduction\n\n[Ethers.js](https://docs.ethers.org/v6/){target=\\_blank} is a lightweight library that enables interaction with Ethereum Virtual Machine (EVM)-compatible blockchains through JavaScript. Ethers is widely used as a toolkit to establish connections and read and write blockchain data. This article demonstrates using Ethers.js to interact and deploy smart contracts to Polkadot Hub.\n\nThis guide is intended for developers who are familiar with JavaScript and want to interact with Polkadot Hub using Ethers.js."} {"page_id": "smart-contracts-libraries-ethers-js", "page_title": "Deploy Contracts to Polkadot Hub with Ethers.js", "index": 1, "depth": 2, "title": "Prerequisites", "anchor": "prerequisites", "start_char": 709, "end_char": 1065, "estimated_token_count": 110, "token_estimator": "heuristic-v1", "text": "## Prerequisites\n\nBefore getting started, ensure you have the following installed:\n\n- **Node.js**: v22.13.1 or later, check the [Node.js installation guide](https://nodejs.org/en/download/current/){target=\\_blank}.\n- **npm**: v6.13.4 or later (comes bundled with Node.js).\n- **Solidity**: This guide uses Solidity `^0.8.9` for smart contract development."} {"page_id": "smart-contracts-libraries-ethers-js", "page_title": "Deploy Contracts to Polkadot Hub with Ethers.js", "index": 2, "depth": 2, "title": "Project Structure", "anchor": "project-structure", "start_char": 1065, "end_char": 1577, "estimated_token_count": 144, "token_estimator": "heuristic-v1", "text": "## Project Structure\n\nThis project organizes contracts, scripts, and compiled artifacts for easy development and deployment.\n\n```text title=\"Ethers.js Polkadot Hub\"\nethers-project\n├── contracts\n│ ├── Storage.sol\n├── scripts\n│ ├── connectToProvider.js\n│ ├── fetchLastBlock.js\n│ ├── compile.js\n│ ├── deploy.js\n│ ├── checkStorage.js\n├── abis\n│ ├── Storage.json\n├── artifacts\n│ ├── Storage.polkavm\n├── contract-address.json\n├── node_modules/\n├── package.json\n├── package-lock.json\n└── README.md\n```"} diff --git a/smart-contracts/integrations/wallets.md b/smart-contracts/integrations/wallets.md index cc5dbbae9..9ef110271 100644 --- a/smart-contracts/integrations/wallets.md +++ b/smart-contracts/integrations/wallets.md @@ -6,8 +6,6 @@ categories: Smart Contracts, Tooling # Wallets for Polkadot Hub ---8<-- 'text/smart-contracts/polkaVM-warning.md' - ## Introduction Connecting a compatible wallet is the first essential step for interacting with the Polkadot Hub ecosystem. This guide explores wallet options that support both Substrate and Ethereum compatible layers, enabling transactions and smart contract interactions. Whether you're a developer testing on Polkadot Hub or a user accessing the MainNet, understanding wallet configuration is crucial for accessing the full range of Polkadot Hub's capabilities.