Polkadot Substrate
This skill covers building custom blockchains (parachains) and decentralized applications (dApps) using Substrate, the framework powering Polkadot and Kusama. You learn to leverage its modular architecture for high-performance, interoperable blockchain solutions.
You are a seasoned blockchain architect and parachain developer, deeply familiar with the Substrate framework and the Polkadot ecosystem. You've launched custom runtimes, integrated complex pallets, and orchestrated cross-chain communication (XCM) for high-performance, specialized blockchain applications. Your expertise lies in leveraging Substrate's flexibility to build application-specific chains tailored for specific use cases, rather than shoehorning logic into general-purpose smart contract platforms.
## Key Points
1. **Install Rust:** Substrate development requires a `nightly` Rust toolchain.
2. **Clone the Substrate Node Template:** This provides a basic, runnable Substrate chain.
3. **Build the Node:** Compile your custom chain.
4. **Run Your Local Node:** Start your blockchain.
5. **Install `polkadot-js/api` (for client interaction):**
1. **Build your new runtime Wasm blob:**
2. **Submit the upgrade transaction using `polkadot-js/api`:**
## Quick Example
```bash
git clone https://github.com/substrate-developer-hub/substrate-node-template.git
cd substrate-node-template
```
```bash
cargo build --release
```skilldb get web3-development-skills/Polkadot SubstrateFull skill: 261 linesYou are a seasoned blockchain architect and parachain developer, deeply familiar with the Substrate framework and the Polkadot ecosystem. You've launched custom runtimes, integrated complex pallets, and orchestrated cross-chain communication (XCM) for high-performance, specialized blockchain applications. Your expertise lies in leveraging Substrate's flexibility to build application-specific chains tailored for specific use cases, rather than shoehorning logic into general-purpose smart contract platforms.
Core Philosophy
Substrate is not just another blockchain client; it's a modular framework for building any blockchain. Its core philosophy centers on providing a "blockchain-in-a-box" experience, allowing you to customize every aspect of your chain's logic, consensus, and governance. Instead of writing smart contracts on a predefined VM, you develop directly at the runtime level using Rust, compiling your logic to WebAssembly (Wasm). This approach offers unparalleled flexibility, performance, and upgradeability.
The Polkadot network extends this philosophy by providing a shared security model (via its Relay Chain) and a robust cross-chain messaging standard (XCM) for interoperability between these custom blockchains, known as parachains. When you build with Substrate, you're not just creating an isolated chain; you're developing a potential participant in a vast, interconnected web of specialized blockchains, unlocking truly novel decentralized applications that span multiple chains. This paradigm shift from dApps on a single chain to dApps leveraging an ecosystem of specialized chains is fundamental to building on Polkadot and Substrate.
Setup
To begin developing with Substrate, you need the Rust toolchain and the substrate-node-template.
-
Install Rust: Substrate development requires a
nightlyRust toolchain.# Install rustup if you don't have it curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh source $HOME/.cargo/env # Add the nightly toolchain and set it as default for your project rustup update nightly rustup default nightly # Add the Wasm target for compiling your runtime rustup target add wasm32-unknown-unknown -
Clone the Substrate Node Template: This provides a basic, runnable Substrate chain.
git clone https://github.com/substrate-developer-hub/substrate-node-template.git cd substrate-node-template -
Build the Node: Compile your custom chain.
cargo build --release -
Run Your Local Node: Start your blockchain.
./target/release/node-template --dev --ws-port 9944 --rpc-port 9933Your node is now running and accessible via WebSocket at
ws://127.0.0.1:9944. -
Install
polkadot-js/api(for client interaction):npm install @polkadot/api # or yarn add @polkadot/api
Key Techniques
1. Developing a Custom Pallet
Pallets are the core logic modules of a Substrate runtime. You define storage, events, errors, and dispatchable functions (extrinsics) within them.
// In your `pallets/template/src/lib.rs` (or your custom pallet's file)
#![cfg_attr(not(feature = "std"), no_std)]
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<T>(_);
#[pallet::config]
pub trait Config: frame_system::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
}
#[pallet::storage]
#[pallet::getter(fn get_value)]
pub type ValueStore<T> = StorageValue<_, u32, ValueQuery>;
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// A new value has been set. [who, new_value]
ValueSet(T::AccountId, u32),
}
#[pallet::error]
pub enum Error<T> {
/// The provided value is too large.
ValueTooLarge,
}
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Sets a new value in the storage.
#[pallet::weight(10_000 + T::DbWeight::get().writes(1))]
pub fn set_new_value(origin: OriginFor<T>, new_value: u32) -> DispatchResult {
let sender = ensure_signed(origin)?;
// Ensure value is not too large
ensure!(new_value <= 100, Error::<T>::ValueTooLarge);
<ValueStore<T>>::put(new_value);
Self::deposit_event(Event::ValueSet(sender, new_value));
Ok(())
}
}
}
After defining your pallet, you must add it to your runtime's src/lib.rs file.
// In `runtime/src/lib.rs`
// ...
// Add your pallet to the `construct_runtime!` macro
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system,
Balances: pallet_balances,
// ... other pallets
TemplateModule: pallet_template, // Your custom pallet
}
);
// ...
// Implement the `Config` trait for your pallet
impl pallet_template::Config for Runtime {
type Event = Event;
}
2. Interacting with Your Chain using polkadot-js/api
The @polkadot/api library is your primary tool for connecting to, querying, and submitting transactions to any Substrate-based chain.
// index.js
import { ApiPromise, WsProvider, Keyring } from '@polkadot/api';
async function main() {
const provider = new WsProvider('ws://127.0.0.1:9944');
const api = await ApiPromise.create({ provider });
console.log(`Connected to: ${api.genesisHash.toHex()}`);
// 1. Query chain state (e.g., account balance)
const keyring = new Keyring({ type: 'sr25519' });
const alice = keyring.addFromUri('//Alice');
const bob = keyring.addFromUri('//Bob');
const { data: balanceAlice } = await api.query.system.account(alice.address);
console.log(`Alice's balance: ${balanceAlice.free}`);
// Query your custom pallet's storage
const customValue = await api.query.templateModule.valueStore();
console.log(`Custom value from pallet: ${customValue.toNumber()}`);
// 2. Submit a transaction (e.g., transfer funds)
const transfer = api.tx.balances.transfer(bob.address, 12345);
const hash = await transfer.signAndSend(alice);
console.log(`Transfer sent with hash ${hash.toHex()}`);
// 3. Submit a transaction to your custom pallet
const setNewValueTx = api.tx.templateModule.setNewValue(42);
const setValueHash = await setNewValueTx.signAndSend(alice);
console.log(`Set new value with hash ${setValueHash.toHex()}`);
// 4. Subscribe to events
console.log('Listening for events...');
const unsubscribe = await api.query.system.events((events) => {
events.forEach((record) => {
const { event, phase } = record;
const types = api.registry.lookup.getSiType(event.typeDef.type);
console.log(`\t${event.section}:${event.method}:: (phase=${phase.toString()})`);
console.log(`\t\t${event.meta.docs.toString()}`);
event.data.forEach((data, index) => {
console.log(`\t\t\t${types.def.asVariant.variants[event.index].fields[index].name}: ${data.toString()}`);
});
});
});
// Keep subscription open for a bit, then close
setTimeout(() => {
unsubscribe();
console.log('Unsubscribed from events.');
process.exit(0);
}, 30000);
}
main().catch(console.error);
3. Runtime Upgrades
One of Substrate's killer features is its forkless runtime upgrade capability. You can deploy new logic to your chain without a hard fork. This is typically done via a set_code extrinsic from a privileged account (e.g., sudo or governance).
-
Build your new runtime Wasm blob:
cargo build --release --features runtime-wasmThis generates
target/release/wbuild/node-template-runtime/node_template_runtime.compact.compressed.wasm. -
Submit the upgrade transaction using
polkadot-js/api:import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; import { readFileSync } from 'fs'; async function upgradeRuntime() { const provider = new WsProvider('ws://127.0.0.1:9944'); const api = await ApiPromise.create({ provider }); const keyring = new Keyring({ type: 'sr25519' }); const sudoAccount = keyring.addFromUri('//Alice'); // Assuming Alice is sudo // Read the new runtime Wasm blob const code = readFileSync('./target/release/wbuild/node-template-runtime/node_template_runtime.compact.compressed.wasm'); // Create the `set_code` extrinsic, wrapped in a `sudo` call const setCodeTx = api.tx.system.setCode(code); const sudoCall = api.tx.sudo.sudo(setCodeTx); console.log('Submitting runtime upgrade...'); const hash = await sudoCall.signAndSend(sudoAccount, ({ status }) => { if (status.isInBlock) { console.log(`Runtime upgrade included in block: ${status.asInBlock}`); } else if (status.isFinalized) { console.log(`Runtime upgrade finalized. Chain is now running new code.`); process.exit(0); } }); console.log(`Transaction hash: ${hash.toHex()}`); } upgradeRuntime().catch(console.error);
4. Cross-Consensus Message Format (XCM) Basics
XCM is the language for cross-chain communication in Polkadot. It allows parachains to send messages, transfer assets, and execute logic across chains using a standardized instruction set.
Anti-Patterns
-
Unbounded Storage Growth in Pallets. Using StorageMaps or StorageValues that grow without bound allows state bloat that degrades node performance. Implement storage deposits or bounded collections.
-
Runtime Upgrades Without Migration Testing. Deploying forkless runtime upgrades without testing storage migrations on a forked chain risks corrupting live state when storage layouts change between versions.
-
Ignoring Weight Estimation. Assigning incorrect or hardcoded weights to dispatchable functions allows transactions that consume more resources than budgeted, potentially stalling block production.
-
Sudo-Only Governance Long-Term. Maintaining sudo access as the primary governance mechanism beyond the initial bootstrap phase centralizes control and undermines the decentralization properties that Substrate-based chains should provide.
-
Tight Coupling Between Pallets. Building pallets with direct dependencies on other pallets' storage or internal functions instead of using trait-based interfaces prevents modular composition and makes runtime upgrades fragile.
Install this skill directly: skilldb add web3-development-skills
Related Skills
Account Abstraction
Account Abstraction (AA) fundamentally changes how users interact with EVM chains by enabling smart contract accounts. This skill teaches you to build dApps with ERC-4337 compatible smart accounts, facilitating features like gas sponsorship, batch transactions, and flexible authentication methods.
Aptos Development
Develop dApps and smart contracts on the Aptos blockchain using the Move language, Aptos SDKs, and CLI tools. This skill covers building secure, scalable, and user-friendly web3 applications leveraging Aptos' high throughput and low latency.
Avalanche Development
This skill covers building decentralized applications and smart contracts on the Avalanche network, including its C-Chain, X-Chain, P-Chain, and custom Subnets. Learn to interact with the platform using SDKs, deploy EVM-compatible contracts, and manage cross-chain asset flows.
Base Development
Develop, deploy, and interact with smart contracts and dApps on Base, an Ethereum Layer 2 solution built on the OP Stack. Leverage its EVM compatibility for scalable and cost-efficient Web3 applications.
Cosmos SDK
Master the Cosmos SDK for building custom, sovereign blockchains (app-chains) and decentralized applications with inter-blockchain communication (IBC). This skill covers module development, message handling, and client interactions for creating high-performance, interoperable chains tailored to specific use cases.
Cosmwasm Contracts
Develop, test, and deploy secure smart contracts on Cosmos SDK blockchains using Rust and CosmWasm.